Firebase are providing AuthResult on the callback for user sign in using startActivityForSignInWithProvider (in my case the provider is apple on Android platform).
I can't seem to fetch the idToken from it in a proper (synchronous) way.
So far I found two options, both aren't satisfying:
Option 1: casting
((OAuthCredential)authResult.getCredential()).getIdToken()
This works but I'm not sure if it's a safe cast. Plis, I'm thinking, if Firebase would have wanted us to fetch the idToken this way, they would have added it to AuthCredential.
Option 2: fetching it from the user
authResult.getUser().getIdToken(false).addOnCompleteListener { ... }
This seems to be a safe solution, but it's an async method. It doesn't seem to make sense to performing another async method, after the user just manually signed in (this is what i'm doing for an existing user).
You should be using the asynchronous listener. The reason for this is because the ID token will expire every hour, and your listener is how you know the very moment when the token has been refreshed, so you can start using that new token right away.
Related
I have been reading around on different ways to refresh the cognito session after 1 hour, and I have yet to get a conclusive answer from aws team or anyone else. How do you get new tokens after the sessions have expired without re-authenticating, that is, the user has to login again (enter their password/email credentials).
There is a method refresh() in CognitoCachingCredentialsProvider class, that I believe refreshes the session. However, after that is called how do you get the new tokens (idToken/accessToken/refreshToken)? In my case the refreshToken is set to the maximum expiration time which is about 10 years.
The only way to get new tokens as I have done so far, is through user authentication when the user is logging in, where cognitoUser.getSessionInBackground(authenticationHandler) is called. This interface provides the tokens retrieved from CognitioUserSession. It seems very counterproductive for my application in particular to prompt the user to login, using their password each time after 1 hour.
I would like to add one more thing, is it even possible to get new tokens after the idToken and accessToken have expired? Looking at the aws cognito raw code, I have not seen an interface that provides that outside of login in the user despite what the documentation says.
My app uses Firebase to authenticate users by phone number, a migration from Digits.
I add the idToken from Firebase to my calls.
I listen with an interceptor on my httpclient if a 401 was trown, if so, I logged out.
I noticed after one hour the 401 came in, so I added an addIdTokenListener in my App class. When it changes I update my token to sign my calls.
It worked, but not flawless, sometimes a 401 was thrown and I still logged the user out...
I am writing something in my interceptor to get the IdToken from the user, but the call firebaseUser.getIdToken() is async. So I'm starting to make things complicated, I guess.
Could anyone point me in the right direction? What is your workflow?
You're going in the right direction. One thing you may want to do is alter your logic a little based on the reason for the ID token validation failure. You can unpack the ID token data yourself and check the expiration field. If the token has expired, return a different code that triggers the retrieval process, before trying the call again.
In the example OutlookQuickStart for Android works fine in the first request after logon().Now I want to keep connect my app to that user and continue checking for new emails.. How can I re use the access token and build the request to check for new emails? Do I have to save the access token, refresh token ?
How I can refresh the token in Android if it is expired.
According to the documentation for the auth library at https://github.com/AzureAD/azure-activedirectory-library-for-android, the library caches the token and refresh token for you. So you would just use acquireTokenSilentSync to get the token each time you need it. That function would return the current token from the cache if it is still valid, and would refresh it if it is expired.
UPDATE: I've taken a closer look at the sample you're using and the Outlook SDK that it uses. The key thing here is the DependencyResolver object. You pass that object to the OutlookClient constructor. Then anytime you make an API call with that OutlookClient, it just calls the getCredentials override that you supply when you create the DependencyResolver.
So as the sample stands, you should be able to make multiple calls through that OutlookClient without having to change it at all. However, after an hour, when the access token expires, calls will start to fail. The fix for that would be to change the getCredentials override to always call acquireTokenSilentSync. Something like:
#Override
public Credentials getCredentials() {
logger.debug("getCredentials in resolver called");
AuthenticationResult result = mAuthContext.acquireTokenSilentSync(
scopes,
getResources().getString(R.string.AADClientId),
UserIdentifier.getAnyUser());
logger.debug("AcquireTokenSilentSync SUCCESS");
logger.debug("Token expires: ", result.getExpiresOn());
logger.debug("Token: ", result.getAccessToken());
return new OAuthCredentials(result.getAccessToken());
}
Caveat: I'm unable to run this code to validate it due to problems getting the Android emulator running on my dev machine :(.
I am developping an android app based on firebase that connects to the Nest API. While it worked for some time, it now rejects authentification.
I get the folowing error "The active or pending auth credentials were superseded by another call to auth" when I'm pretty sure firebaseRef.auth() method is only called once...
EDIT : I'm getting close to the 1000 Users limitation after wich we should request more users from Nest.
Any idea where this is comming from ? Can it be comming from the online service I am calling or is this necessarilly due to my code ?
thanks.
P.
We discovered that every time the user is passed through the Works with Nest web sign up dialog, it generates a new auth token. Is it possible you've run through the process on multiple devices and generated a new auth token, invalidating your previous one?
I have implement function retrieve credentials from saved token in SharedPreferences.
mCredential = new GoogleCredential.Builder()
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.setJsonFactory(mJsonFactory)
.setTransport(mHttpTransport).build();
mCredential.setRefreshToken(accessRefreshTokenSave);
mCredential.setAccessToken(accessTokenSave);
Long expires = mCredential.getExpiresInSeconds();
boolean result = mCredential.refreshToken();
When the token is expired. We should call mCredential.refreshToken() to refresh the token, is it right ?
When i call refreshToken i got exception.
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant"
}
What should i need to do to refresh the token ? I found some document in Using OAuth 2.0 say about refresh token. But i don't know how to implement it in Android code? Is there any sample code do this ?
Generally (in my experience, since I haven't found any documentation) 'invalid grant' means there is some problem with your stored refresh token. This includes (I think):-
The user has revoked it
Your testing has caused multiple refresh tokens to be generated. Only 25 may be extant
The scopes associated with the stored token have changed
To recover the situation, delete the stored refresh token and start the process again. The good news, is that apart from the user revocation scenario (1) this is a testing environment issue and doesn't necessarily mean you have a bug.
Have a look on https://developers.google.com/+/mobile/android/sign-in that's the OAUTH for Android, and you can check what is wrong, or maybe use the example code in your Project. To give you more details, you have to post the entire project (linking it to GitHub for example) or post the interested Class ;-)