I'm using the google play services authentication example here
How do I reset the GoogleAuthUtil so it will ask for permission again?
It asks for permission by throwing the userRecoverableException which is fed to a dialog. But it only asks for permission one time. I need to test asking for permission again.
I've tried to uninstall the sample app and re-install the sample app and this didn't work it doesn't ask for permission seems it already knows the app.
protected String fetchToken() throws IOException {
try {
return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
} catch (UserRecoverableAuthException userRecoverableException) {
// GooglePlayServices.apk is either old, disabled, or not
// present, which is
// recoverable, so we need to show the user some UI through the
// activity.
MyGooglePlay.handleException(userRecoverableException);
} catch (GoogleAuthException fatalException) {
onError("Unrecoverable error " + fatalException.getMessage(),
fatalException);
}
return null;
}
/**
* This method is a hook for background threads and async tasks that need to provide the
* user a response UI when an exception occurs.
*/
public void handleException(final Exception e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (e instanceof GooglePlayServicesAvailabilityException) {
// The Google Play services APK is old, disabled, or not present.
// Show a dialog created by Google Play services that allows
// the user to update the APK
int statusCode = ((GooglePlayServicesAvailabilityException)e)
.getConnectionStatusCode();
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(statusCode,
HelloActivity.this,
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
dialog.show();
} else if (e instanceof UserRecoverableAuthException) {
// Unable to authenticate, such as when the user has not yet granted
// the app access to the account, but the user can fix this.
// Forward the user to an activity in Google Play services.
Intent intent = ((UserRecoverableAuthException)e).getIntent();
startActivityForResult(intent,
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
}
}
});
}
You can use the Google Settings app to de-authorize connected applications, by following these steps:
Launch the Google Settings app
Choose the Connected apps option (at the top)
A list of connected apps is displayed; find the app you want to de-authorize and select it. Sorry there is no screenshot as I'm not able to remove personal info from it ATM - but it should be quite straightforward what to do here :)
Finally, click the Disconnect button (at the bottom) on the details page of the app
Note that it might take a moment before the app is de-authorized.
You can also call GoogleAuthUtil.invalidateToken or GoogleAuthUtil.clearToken, that should make it ask the permission again.
If you're a user, like what free3dom answered, you can go to Google Settings app to revoke the access.
If you want to revoke the access programmatically, you can call Google's revoke token API: https://developers.google.com/identity/protocols/OAuth2WebServer#tokenrevoke. Basically, you should first get a valid token with a set of scopes by calling GoogleAuthUtil.getToken(), and then revoke the token. After the token is revoked, you should see the permission dialog again.
Related
After some back and forth I finally got this to work but I had to use version 0.2.0 because I followed the google guide presented in the Readme.
Anyway, Im struggling with handling what will happen when the oAuth token times out. Then it needs to open the browser again to log in or is there a background process available for this as it automatically redirects back to the app because the server remembers the user so there is no need for a new username/password input?
Im getting a refresh token like this :
if(mAuthService == null){
mAuthService = new AuthorizationService(context);
}
mAuthState.performActionWithFreshTokens(mAuthService, new AuthState.AuthStateAction() {
#Override public void execute(
String accessToken,
String idToken,
AuthorizationException ex) {
if (ex != null) {
return;
}
// Getting the access token...
}
});
Thats working fine but after the user is idle for some time it wont work. How to handle this properly?
Solution for my problem was this:
I changed to using offline_access for the token in the scope. Depending on the site/service you're login into if they accept it or not. For me it was accepted and will keep the user logged in for a long time and removes the need to re-login.
I am building an app where I use AWS Cognito to make user accounts. I can get it to work just fine most of the time, I have successfully made all the necessary classes and handlers to create and authenticate users and just abut everything else. However, I seem to run into this strange problem ONLY when trying to sign a user in right after their account has been created.
com.amazonaws.mobileconnectors.cognitoidentityprovider.exceptions.CognitoInternalErrorException: Authentication failed due to an internal error
If I restart the app, I can sign in just fine, so it is an issue with signing in right after an account has been created. It is very unspecific and the documentation just says "An internal error has occurred. Retry your request, but if the problem persists, contact us with details by posting a message on the AWS forums." How do you get around this?
Basically after you create an account and authenticate it, there is something cached in one of the AWS API related classes which still points towards the account not being authenticated. This error is only occurring if trying to immediately sign in after the account was created. In my case and in most cases, all of the AWS Cognito API code is contained in a manager/helper class, mine is an AWSHelper Class. To get around this issue, in my Handler after the user is confirmed, I simply recreated the AWSHelper in my activity, and I am able to sign in just fine.
GenericHandler confirmationCallback = new GenericHandler() {
#Override
public void onSuccess() {
Log.w("DMJ", "user has been confirmed!");
if (!mainActivity.updateAWS()) {
Toast.makeText(activity, "Account created! Please sign into your account", Toast.LENGTH_LONG).show();
activity.changeFragment(new SignInFragment(), "SignInFragment");
} else {
Toast.makeText(activity, "Account created!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Exception exception) {
Log.w("DMJ", "confirmation got rekt m8");
exception.printStackTrace();
}
};
In my MainActivity, I have the following method
public boolean updateAWS() {
awsHelper = new AWSHelper(this);
if (awsHelper.isSignedIn) {
changeFragment(new HomeScreenFragment(), "HomeScreenFragment");
return true;
}
return false;
}
ALSO, I have not checked but I suspect if you try to sign in the user after the the onSuccess() method entirely, the CognitoUser will be updated and able to sign in without the CognitoInternalErrorException
I have an app in which user authentificates in Office365 with AzureAD library for Android.
It works well, users can authentificate and work with the app. Unfortunately, after a while they start hitthing AuthenticationException with ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED as an error code.
I checked the source code of AzurelAD. The only place, which is throughing this issue is acquireTokenAfterValidation() method:
private AuthenticationResult acquireTokenAfterValidation(CallbackHandler callbackHandle,
final IWindowComponent activity, final boolean useDialog,
final AuthenticationRequest request) {
Logger.v(TAG, "Token request started");
// BROKER flow intercepts here
// cache and refresh call happens through the authenticator service
if (mBrokerProxy.canSwitchToBroker()
&& mBrokerProxy.verifyUser(request.getLoginHint(),
request.getUserId())) {
.......
Logger.v(TAG, "Token is not returned from backgroud call");
if (!request.isSilent() && callbackHandle.callback != null && activity != null) {
....
} else {
// User does not want to launch activity
String msg = "Prompt is not allowed and failed to get token:";
Logger.e(TAG, msg, "", ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED);
callbackHandle.onError(new AuthenticationException(
ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED, msg));
}
// It will start activity if callback is provided. Return null here.
return null;
} else {
return localFlow(callbackHandle, activity, useDialog, request);
}
}
My source code:
authenticator.getAccessTokenSilentSync(getMailService());
public class Authenticator {
..............
public String getAccessTokenSilentSync(ServiceInfo serviceInfo) {
throwIfNotInitialized();
return getAuthenticationResultSilentSync(serviceInfo).getAccessToken();
}
private AuthenticationResult getAuthenticationResultSilentSync(ServiceInfo serviceInfo) {
try {
return authenticationContext.acquireTokenSilentSync(
serviceInfo.ServiceResourceId,
Client.ID,
userIdentity.getAdUserId());
} catch (AuthenticationException ex) {
// HERE THE EXCEPTION IS HANDLED.
}
}
..............
}
Stacktrace I'm getting:
<package name>.data_access.error_handler.AuthenticationExceptionWithServiceInfo: Refresh token is failed and prompt is not allowed
at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1294)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
at com.microsoft.aad.adal.AuthenticationContext.refreshToken(AuthenticationContext.java:1609)
at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1261)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
at com.microsoft.aad.adal.AuthenticationContext.refreshToken(AuthenticationContext.java:1609)
at com.microsoft.aad.adal.AuthenticationContext.localFlow(AuthenticationContext.java:1261)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenAfterValidation(AuthenticationContext.java:1229)
at com.microsoft.aad.adal.AuthenticationContext.acquireTokenLocalCall(AuthenticationContext.java:1123)
at com.microsoft.aad.adal.AuthenticationContext.access$600(AuthenticationContext.java:58)
at com.microsoft.aad.adal.AuthenticationContext$4.call(AuthenticationContext.java:1072)
at com.microsoft.aad.adal.AuthenticationContext$4.call(AuthenticationContext.java:1067)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
Version of AzureAD library I'm using: 1.1.7 (to prevent blaming too old version - I've checked the changelist since from 1.1.7 to 1.1.11 and haven't found anything related to question)
Problem: Right now, I'm treating this error, as a signal to through the user to the login screen. In my opinion, it leads to a poor experience for the user. The fact that it happens very often and affects many users make it even worse.
Question: Is there anything I can do different to avoid this AuthenticationException or workaround it somehow (i.e. avoid user enters credentials once again).
Have you verified that AuthenticationContext.acquireTokenSilentSync() is truly the method that you wish to invoke?
The docs indicate that this method will explicitly not show a prompt. From the docs:
This is sync function. It will first look at the cache and automatically checks for the token expiration. Additionally, if no suitable access token is found in the cache, but refresh token is available, the function will use the refresh token automatically. This method will not show UI for the user. If prompt is needed, the method will return an exception.
The refresh token you are issued should last two weeks per this AAD book. After the refresh token expires users are expected to reauthenticate. Can you inspect net traffic with Fiddler or Charles and inspect the expiry of the tokens? If you can verify that the tokens are failing to refresh before their expiry it may indicate a bug in the AD library.
To clarify the difference in methods on AuthenticationContext - there are two categories of methods: "silent" methods (which will not present a dialog to user in the event that they need to reauthenticate), and non-silent. Non-silent methods will, in the event of requiring reauthentication (or consent) from the user, start a new Activity containing the AAD login. At that point the authentication flow is restarted.
Additionally, if you make changes to your application's registration in Azure such as adding new permission scopes your users will be required to re-grant consent for the application to continue to handle their data.
This is because you need to refresh your token and implement this in your code so the user won't be prompt to login every time the access token is expired. please check out how to implement refresh token here:
https://msdn.microsoft.com/en-us/library/azure/dn645538.aspx
Hope this helps.
i (lets say app 'C' )am trying to get the auth token of an installed app ( say 'S' ) through Android's AccountManager's getAuthToken function.
this function is not working as expected, it doesn't return any results (the run function is never called )
AccountManagerFuture<Bundle> future1 = AccountManager.get(Main2.this).getAuthToken(account,account.type,null,false, new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
Bundle result = null;
try {
result = future.getResult();
String check = "";
}
catch (OperationCanceledException e){ }
catch (IOException e1){}
catch (AuthenticatorException e2){}
}
} , new Handler(Looper.getMainLooper()));
when i see the device ADB Logs, i see the following
java.lang.SecurityException: Activity to be started with KEY_INTENT must share Authenticator's signatures
at com.android.server.accounts.AccountManagerService$Session.onResult(AccountManagerService.java:2580)
at com.android.server.accounts.AccountManagerService$6.onResult(AccountManagerService.java:1677)
at com.android.server.accounts.AccountManagerService$6.onResult(AccountManagerService.java:1652)
at android.accounts.IAccountAuthenticatorResponse$Stub.onTransact(IAccountAuthenticatorResponse.java:59)
Apps 'C' and 'S' described above are unrelated, so they are signed with different certificates.
I am guessing the function should have worked in above scenario ( which is one of the main purpose of AccountManager - Sharing of account access tokens across apps ) as well ( with a security dialog thrown to the user on whether he should allow 'C' to access 'S' ) , whats the reason it is not working ? Am i missing anything here ?
Thanks
First go to your implementation of AbstractAuthenticator in app S. Find getAuthToken() implementation. Check, which activity you return as KEY_INTENT. It must be in same app as authenticator (yes, there are ways to launch an activity from another app).
Make sure, you run on a real device, because you must see a "grant permissions" android system screen in that case.
If you come here, than I don't know another reason except some bug. Try totally removing both apps and restarting emulator, then check if problem persists.
I'm using Azure Mobile Services in my android application to add authentication to the app, via Facebook and Google. However, every single time I attempt to login from the app, I receive the following error:
"com.microsoft.windowsazure.mobileservices.MobileServiceException: Logging >in with the selected authentication provider is not enabled".
No other errors occur. This is my code:
private void authenticate(boolean bRefreshCache)
throws ClientProtocolException, IOException {
bAuthenticating = true;
if (bRefreshCache || !loadUserTokenCache(mClient)) {
mClient.login(MobileServiceAuthenticationProvider.Facebook,
new UserAuthenticationCallback() {
#Override
public void onCompleted(MobileServiceUser user,
Exception exception,
ServiceFilterResponse response) {
synchronized (mAuthenticationLock) {
if (exception == null) {
cacheUserToken(mClient.getCurrentUser());
Log.i("MappingRoadConditions",
"authenticating");
createAndShowDialog(String.format(
"You are now logged in - %1$2s",
user.getUserId()), "Success");
} else {
createAndShowDialog(exception.getMessage(),
"Login Error");
}
bAuthenticating = false;
mAuthenticationLock.notifyAll();
}
}
});
} else {
// Other threads may be blocked waiting to be notified when
// authentication is complete.
synchronized (mAuthenticationLock) {
bAuthenticating = false;
mAuthenticationLock.notifyAll();
}
}
}
The function for logging in by Google is exactly the same, other than the name of the provider of course.
1) I have tried troubleshooting by logging in through the browser and I can login perfectly well using both Facebook and Google.
2) I have added the internet permission in the manifest file.
3) I have also tried testing the app by changing the internet connections, in case it's a network connection problem but to no avail. I am able to login perfectly well through the browser on the same internet connection.
Any ideas on what could be happening?
I struggled with this for a while when moving my working code over into a fresh app
It seems that after I eliminated the provider app connection as your problem (I used the javascript html client in parallel ) I needed to go back to basics because I found this similar question
Check your Manifest
I also had this issue just happen on a successful build - the ADB bridge had failed and the emulator could not connect to the internet (I had switched networks)
This error code is not descriptive, but Azure seems to assume if it can't connect to a provider then you didn't set it up!