I'm upgrading to the latest Android and iOS sdks for Facebook and had two question.
Now that we have a concept of an access token that has to be refreshed periodically, I have been reading about the iOS SDK and noticed the below in the SDK:
/*!
#abstract Refresh the current access token's permission state and extend the token's expiration date,
if possible.
#param completionHandler an optional callback handler that can surface any errors related to permission refreshing.
#discussion On a successful refresh, the currentAccessToken will be updated so you typically only need to
observe the `FBSDKAccessTokenDidChangeNotification` notification.
If a token is already expired, it cannot be refreshed.
*/
+ (void)refreshCurrentAccessToken:(FBSDKGraphRequestHandler)completionHandler;
This method is for refreshing the SDK and is in the class FBSDKAccessToken. On the Android side I'm trying to find out if the same is true and read the code as well as documentation on this, it doesn't say if the AccessToken class's refresh method (refreshCurrentAccessTokenAsync) has to be called before expiration.
I have read this in the documentation:
https://developers.facebook.com/docs/reference/android/current/class/AccessToken/
Even for getLastRefresh() it says the below:
Gets the date at which the token was last refreshed. Since tokens expire, the Facebook SDK will attempt to renew them periodically.
This is unlike iOS where refreshing doesn't happen automatically. Is my assumption correct? That the iOS and Android sdks are handling refreshing differently?
Also, what is the best practice for refreshing tokens? I have been refreshing tokens in didFinishLaunchingWithOptions in iOS and on Android I do it when the application loads. However, it would help if there was more information on the best strategy with the SDKs.
I have been reading the following on this:
https://www.sammyk.me/access-token-handling-best-practices-in-facebook-php-sdk-v4
https://www.quora.com/With-the-Facebook-Graph-API-is-there-a-way-to-get-a-new-access-token-without-needing-to-re-enter-the-users-password
The access token will get refreshed automatically in the Android SDK if you make a graph request (it gets piggy-backed onto the request that you make).
Related
I am working on an application, which uses OAuth - Token based authentication.
This is how the flow looks like, considering we have the access and refresh token.
Api call -> intercepter appends access-token -> api returns 200
Api call -> intercepter appends expired access-token -> api returns
401 -> intercepter refreshes token using refresh token ->
interceptor retries same req -> returns 200
Api call -> intercepter appends expired access-token -> api returns
401 -> intercepter refreshes token using refresh token(refresh token
is also expired) -> prompt guest to sign-in -> guest signed-in ->
retry request
This all works great and fine - I am considering to optimise it a bit i.e i don't want to call api and wait for 401 to return.
Instead check for token expiration beforehand, get the new access token and then call the api with valid token.
This approach of calculating the expiry of token using android system time might work - but can be misused sometimes when user changes the android time.
Wondering if there a better solution to avoid the expiry issue of time based on android system time.
Even if you add such a check in your code, you will still need that flow you presented in the question (so catching 401s and refreshing tokens accordingly). This is because, as you noticed, time settings on the client device can be changed, or there might be a slight clock skew between the client and the server (so no intentional tampering with time settings).
The approach where you check for expiry before the API call will work only if you have access to the expiration time of the access and refresh tokens. So either you received that information together with tokens and persisted it, or JWTs are used and you can easily check expiration.
Personally, I wouldn't add such a check unless there is some strong argument for it (e.g. you know that your app will be mainly used in remote locations with slow connections and you want to limit traffic to a minimum, etc.). The flow that you presented is a common one and works just fine.
In our Android app that uses MSAL 1.0 we can successfully sign-in to Azure AD. However, we cannot find a way to get ID token. Some examples on line show two ways to get ID token: IAuthenticationResult.getIdToken() and IAccount.getClaims().get("id_token"). Neither of the methods works for us. The former does not exist as a method in IAuthenticationResult. The latter always returns null.
I've looked at the source code that does the signing in and noticed that ID tokens are acquired and parsed into claims. However, it does not look like they are made available to library users in their raw formats.
I've verified during debugging that valid ID tokens are being acquired.
Our app needs to pass ID tokens to our back-end server.
Is there another way to access ID tokens using MSAL?
Btw, we do not have this problem on iOS and MSAL.
I have confirmed that the feature is not present in the Android version (although the id token is accessible as a string in the iOS version). It will be implemented in the future. For reference look here:
https://github.com/AzureAD/microsoft-authentication-library-for-android/issues/850
I am trying to access users YouTube private data like subscriptions which require OAuth authentication. I have tried 2 approaches so far.
1.Using GoogleAuthUtil.getToken() method. But it's deprecated and using this function only access token can be acquired which expires after 1 hour. I have no idea how to retrieve refresh token using this method.
2.According to this article and this answer we should avoid use of getToken method because of security and UX problems. So I tried using Auth.GOOGLE_SIGN_IN_API. According to the documentation, we need to use GoogleSignInOptions. So I used it and using requestScopes() i added the Youtube scope. Also I used requestserverauthcode() to get the exchange code, using which access and refresh token can be acquired. Now here's my problem, we need to use GoogleApiClient with addApi(). The available set of API's doesn't have a Youtube API listed to put it in addApi(). So there is no way I can get access to access tokens / refresh token.
Can anyone help me out?
EDIT:
I solved it. I used getToken approach to get tokens. Whenever a 401 authorization error occurs, we need to call getToken method returns a new token.
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?