I was integrating azure adb2c on my native android app using MSAL. My token expiry is set to 60minutes in the portal. Currently I'm calling the acquireTokenSilentAsync each time the app launches in order to make sure access token is not expired. But is there any way to avoid calling acquireTokenSilentAsync each time and make the call happens only when the access token expires? This is to make the app load much faster,by avoid calling acquireTokenSilentAsync every time.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.microsoft_azure);
context = MicrosoftAzureActivity.this;
initializeUI();
// Creates a PublicClientApplication object with res/raw/auth_config_single_account.json
PublicClientApplication.createSingleAccountPublicClientApplication(MicrosoftAzureActivity.this,
R.raw.auth_config_single_account,
new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
#Override
public void onCreated(ISingleAccountPublicClientApplication application) {
/**
* This test app assumes that the app is only going to support one account.
* This requires "account_mode" : "SINGLE" in the config json file.
**/
loadAccount();
}
#Override
public void onError(MsalException exception) {
displayError(exception);
}
});
}
Interactively fetching Token:
mSingleAccountApp.signIn(MicrosoftAzureActivity.this, null, getScopes(), getAuthInteractiveCallback());
Load Account when already token is fetched Interactively and account is already Loaded:
private void loadAccount() {
if (mSingleAccountApp == null) {
Log.d("SKT","Account Not Signed In");
return;
}
Log.d("SKT","Account Not Signed In#1");
mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
#Override
public void onAccountLoaded(#Nullable IAccount activeAccount) {
// You can use the account data to update your UI or your app database.
mAccount = activeAccount;
if (activeAccount != null) {
Log.d("SKT","Account Already Signed In");
mSingleAccountApp.acquireTokenSilentAsync(getScopes(), B2CConfiguration.getAuthorityFromPolicyName("B2C_1_SignInSignUp"), getAuthSilentCallback());
}
}
#Override
public void onAccountChanged(#Nullable IAccount priorAccount, #Nullable IAccount currentAccount) {
if (currentAccount == null) {
// Perform a cleanup task as the signed-in account changed.
showToastOnSignOut();
}
}
#Override
public void onError(#NonNull MsalException exception) {
displayError(exception);
}
});
}
No, you must call acquireTokenAsync for this, it evaluates whether the token in cache is expired or for a different scope than being requested. If neither is true, MSAL returns the tokens from the cache, it doesn’t make any network calls and should be almost instant. You wouldn’t get any perf advantage by doing anything different as that is the minimum.
Related
I am trying to sign in to my android application using Microsoft Single Sign on, using MSAL implemenation as provided here.
In onCreate
mApp = new PublicClientApplication(this.getApplicationContext(), API.CLIENT_ID, API.AUTHORITY);
When the user presses "Sign in with Microsoft" option, I call the method to acquire token as
mApp.acquireToken(this, getResources().getStringArray(R.array.msal_scopes), getAuthInteractiveCallback());
After handling redirect request in onActivityResult, I grab the authentication response at the callback as
private AuthenticationCallback getAuthInteractiveCallback() {
return new AuthenticationCallback() {
#Override
public void onSuccess(AuthenticationResult authenticationResult) {
/* Successfully got a token, use it to call a protected resource */
accessToken = authenticationResult.getAccessToken();
Log.d("AuthSuccess"," "+accessToken);
}
#Override
public void onError(MsalException exception) {
/* Failed to acquireToken */
Log.d("AuthFail"," "+exception.getMessage());
if (exception instanceof MsalClientException) {
/* Exception inside MSAL, more info inside MsalError.java */
} else if (exception instanceof MsalServiceException) {
/* Exception when communicating with the STS, likely config issue */
}
}
#Override
public void onCancel() {
/* User canceled the authentication */
}
};
}
The problem is, AuthenticationResult object gives the access token, but not the refresh token. The object simply does not have refresh token as one of it's parameter. Do I need to further call another method to grab the refresh token as well? How does one get both access and refresh token from microsoft single sign on using MSAL?!
Currently, the library is not exposing the refresh token:
https://github.com/AzureAD/microsoft-authentication-library-for-android/issues/202
I am currently trying to setup user login and registration in my app. The first thing I am doing though is having my MainActivity check to see if a user is logged in and if they are, check if the session is valid. I am not sure if I am getting the ParseSession correctly, and if I am, I am not sure what to do at this point. (The docs are not very clear at showing how to accomplish this). Here is my code:
public class MainActivity extends AppCompatActivity {
ParseUser currentUser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId(getResources().getString(R.string.parse_app_id))
.clientKey(getResources().getString(R.string.parse_client_key))
.server(getResources().getString(R.string.parse_server_url))
.build()
);
if (isFirstLaunch()) {
Toast.makeText(this, "This is the first launch", Toast.LENGTH_LONG).show();
}
if (!isUserLoggedIn()) {
Toast.makeText(this, "User is not logged in", Toast.LENGTH_LONG).show();
}
}
private boolean isFirstLaunch() {
return false;
}
private boolean isUserLoggedIn() {
currentUser = ParseUser.getCurrentUser();
if (currentUser == null) {
return false;
} else {
ParseSession.getCurrentSessionInBackground(new GetCallback<ParseSession>() {
#Override
public void done(ParseSession object, ParseException e) {
/*
* if session is valid
* return true
* if session is invalid
* run ParseUser.logOut()
* return false
*/
}
});
}
}
}
Session are automatically managed by ParseSession these objects are stored on Parse in the Session class, and you can view them on the Parse.com Data Browser
More information on Session :Sessions represent an instance of a user logged into a device. Sessions are automatically created when users log in or sign up. They are automatically deleted when users log out.
There is one distinct Session object for each user-installation pair; if a user issues a login request from a device they’re already logged into, that user’s previous Session object for that Installation is automatically deleted.
Reference of Site for more detail on Session class.
How to check if logged in user session is valid in Android Parse SDK?
As mentioned above if user is valid (you can check it by ParseUser.getCurrentUser()!= null) and authenticated using isAuthenticated() method of ParseUser class. Session must be valid by default (Automatically managed by ParseSession). And the way you checked for Session is correct but there is no need to check for valid session if user is valid and authenticated.
Hope this is Helpful.
I'm trying to create a SyncAdapter for Microsoft calendars and the first step is Authentication. i'm using com.microsoft.aad:adal:2.0.4-alphaand using this code for first authentication:
getAuthenticationContext().acquireToken(
mContextActivity,
Constants.SCOPES.split(" "),
null,
Constants.CLIENT_ID,
Constants.REDIRECT_URI,
PromptBehavior.Auto,
new AuthenticationCallback<AuthenticationResult>() {
#Override
public void onSuccess(final AuthenticationResult authenticationResult) {
if (authenticationResult != null && authenticationResult.getStatus() ==
AuthenticationResult.AuthenticationStatus.Succeeded) {
dependencyResolver = new ADALDependencyResolver(
getAuthenticationContext(),
resourceId,
Constants.CLIENT_ID);
token = authenticationResult.getToken();
UserInfo userInfo = authenticationResult.getUserInfo();
if (userInfo != null) {
userIdentifier = new UserIdentifier(userInfo.getUniqueId(),
UserIdentifier.UserIdentifierType.UniqueId);
}
}
}
#Override
public void onError(Exception t) {
Log.e("initialize", "onError : " + t.getMessage());
result.setException(t);
}
}
);
this works perfectly and after entering username and password i can get token.
BUT this is for sync adapter and at some point i need to get token silently. so i used this code:
public void getTokenSilent() {
getAuthenticationContext()
.acquireTokenSilent(Constants.SCOPES.split(" "),
Constants.CLIENT_ID,
userIdentifier,
new AuthenticationCallback<AuthenticationResult>() {
#Override
public void onSuccess(
AuthenticationResult authenticationResult) {
UserInfo userInfo = authenticationResult.getUserInfo();
}
#Override
public void onError(Exception e) {
Log.e("getTokenSilent", "onError : " + e.getMessage());
}
});
}
After executing this code i got the error:
AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED Prompt is not allowed and failed to get token: ver:2.0.4-alpha
onError : Refresh token is failed and prompt is not allowed
how can i resolve this error and get or refresh token silently?
tnx in advance.
If you want to get the token silently, there are two ways for using Azure AD V2.0 endpoint.
First, acquire the access token and refresh token interactively, then get the access token in the cache or renew the access token using refresh token via acquireTokenSilent method.
Second is that the Azure AD V2.0 endpoint also support the Client Credentials flow(refer here) which normally used for the service daemon application. However the MSAL for android doesn't support this flow at present. You need to implement it yourself. You can follow this article about detail of this flow. And this flow only works for the Azure AD account.
I have registered one user using AWS Cognito android SDK. I am login with user on one device and I am able to fetch all the attributes of the user.But when I log in with same user on different device it gives me CognitoNotAuthorizedException (user is not authenticated message) and I am not able to fetch the attributes.
I have checked on Cognito user pool and the user has been registered and confirmed also phone number has been verified.Is there any version specification for getUserDetails() method which I am missing.I also ran signup/login/forgot password functionality on second device and all are working fine except getUserDetail.Below Code I am using for getting user details.
private void getDetails() {
AppHelper.getPool().getUser(mUsername).getDetailsInBackground(detailsHandler);
}
GetDetailsHandler detailsHandler = new GetDetailsHandler() {
#Override
public void onSuccess(CognitoUserDetails cognitoUserDetails) {
AppHelper.setUserDetails(cognitoUserDetails);
}
#Override
public void onFailure(Exception exception) {
showDialogMessage(getString(R.string.could_not_fetch_user_data), AppHelper.formatException(exception), true);
}
};
Hello everyone i am working with http://quickblox.com/developers/Sample-webrtc-android its works fine
But i want know that is there any way to keep user logged in as quick blox user in my app.
Because right now everytime user open my app user have to login first so i want to keep session alive if it is possible android,
Because its better to do for performance instead of everytime login just prevent to login and keep session alive
Thanks in advance
I have used below code
private void createSession(final String login, final String password) {
final QBUser user = new QBUser(login, password);
QBAuth.createSession(login, password, new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle bundle) {
Log.d(TAG, "onSuccess create session with params");
user.setId(session.getUserId());
if (chatService.isLoggedIn()) {
initQBRTCClient();
} else {
chatService.login(user, new QBEntityCallbackImpl<QBUser>() {
#Override
public void onSuccess() {
Log.d(TAG, "onSuccess login to chat");
/*
* ListUsersActivity.this .runOnUiThread(new
* Runnable() {
*
* #Override public void run() {
* showProgress(false); } });
*
* startCallActivity(login);
*/
islogin = true;
initQBRTCClient();
}
#Override
public void onError(List errors) {
Toast.makeText(HomeAppActivity.this, "Error when login", Toast.LENGTH_SHORT).show();
for (Object error : errors) {
Log.d(TAG, error.toString());
}
}
});
}
}
#Override
public void onError(List<String> errors) {
Toast.makeText(HomeAppActivity.this, "Error when login, check test users login and password",
Toast.LENGTH_SHORT).show();
}
});
}
As described in documentation session token is valid for 2 hours.
Once you have logged, you can store session token & expiration time somewhere in app storage - preference, database, etc. Token can be retrieved by BaseService.getBaseService().getToken().
When user opens your app again, you can set session using stored token BaseService.createFromExistentToken()
Here is the documentation.
Also to keep running permanently chat connection it’s better to use android service.