I have an application to save Azure Active Directory users to SQL Server. For this I am using MSAL authentication to get the users.
But sometimes my access token will get expired and I will get 401 unauthorized error from Graph. So I need to add the logic of validating the expiry in my code itself. I searched a lot but couldn't find a good solution.
Could anybody help me how to achieve this?
The default lifetime of an access token is variable. When issued, an access token's default lifetime is assigned a random value ranging between 60-90 minutes (75 minutes on average). I suggest you save the Refresh token instead and then obtain the access token any time you want to query the users resource.
The reason for that is that the Refresh tokens have a longer lifetime than access tokens. The default lifetime for the tokens is 90 days and they replace themselves with a fresh token upon every use. As such, whenever a refresh token is used to acquire a new access token, a new refresh token is also issued. The Microsoft identity platform doesn't revoke old refresh tokens when used to fetch new access tokens. Securely delete the old refresh token after acquiring a new one. Refresh tokens need to be stored safely like access tokens or application credentials.
More about Refresh token in Microsoft identity platform can be found here - https://learn.microsoft.com/en-us/azure/active-directory/develop/refresh-tokens
Related
I have implemented a JWT authentication and a policy-based authorization in ASP.NET Core. There is a certain user with admin privileges who can assign permissions to non-admin users. If the admin updates the permissions/claims of a non-admin user, is there a way to force expire the access token so that user carrying it will be forced to request a new access token with the newly updated permissions/claims? Right now, the only way to that is to wait for the token to expire but I want to force expire it immediately.
Authentication based on JWT tokens is stateless in serverside. So when a token is not expired it will work. There are some approaches to the problem:
Not including the roles and permissions in the token claims and getting these values from the database in each request.
Using refresh token mechanism and set a refreshing time to a few minutes and return a new token when refreshing time is expired. Therefore for the tokens with the expired refreshing time you know to get the new access permissions(not in each request). New permissions will set in few minutes but the authenticated user doesn't need to log in again.
Creating a set of black-list tokens and append the last issued token to that (not recommended).
I have a service which needs to run under user context, because some endpoints of Microsoft need an user context to execute. My problem now is 01.09.2019 MFA is mandatory. So, at least at the beginning, the service needs a person who logs in, but this is not possible because it is an non interactive Windows Service. So my question is, it is possible to login as a user by code or not? If it is, how? And will the refresh token be stored in the aad cache?
UserIdentifier user = new UserIdentifier(Cred.UserName,UserIdentifierType.OptionalDisplayableId);
return Task.Run(() => authContext.AcquireTokenAsync(
"https://api.partnercenter.microsoft.com",
Cred.ApplicationId,
new Uri("http://localhost"),
new PlatformParameters(PromptBehavior.Auto),
user)).Result;
You'll need to have some kind of app that authenticates the user and stores their refresh token in a secure place like an Azure Key Vault.
Your background service can then use the refresh token to get a new access token and new refresh token.
You can use the access token to call the API and store the new refresh token over the old one.
Then if the refresh token does not work, you'll need to repeat the authentication process.
Refresh tokens can go invalid for some reasons, so your app needs to be ready for that.
it is possible to login as a user by code or not?
yes it is possible
In Authentication time the app receives both sign in info (the id_token) and artifacts (ex: an authorization code) that the app can use for obtaining an access token. That token can be used to access other resources -
This sample shows how to use MSAL to redeem the authorization code into an access token, which is saved in a cache along with any other useful artifact (such as associated refresh_tokens) so that it can be used later on in the application.
I have a Web API that provides the user all the data that needs to be shown on my mobile application.
OWIN JWT Authentication is implemented and it's working properly. There's an endpoint /oauth2/token which provides the user a token and all the endpoints has [Authorize] attribute filter to validate it.
The token expiration is set to 5 minutes.
Login session is maintained through a separated SESSION-ID which is stored into the Keychain and also server-side to check the active session. Everytime a user login inside the application a new token is generated and the user can access API methods to get data.
The question
What if the user leave the application opened for more than 5 minutes (Token expiration time)? The token will not be available since it has expired, how can I refresh it? And when should I refresh it?
I read about refresh tokens but not sure how to handle them (Is thist the right choice?), since the [Authorize] attribute will just reject my call if the token has expired, without providing an expiration message, I can't understand when it is an expired token or an invalid one.
What if the user leave the application opened for more than 5 minutes
(Token expiration time)? The token will not be available since it has
expired, how can I refresh it?
If I understand right, you set The token expiration to 5 minutes, that means if the user leave the application opened for more than 5 minutes, the token is no longer valid. Actually the user has to relogin to get the new token.
So back to your question, at the moment the token is expired, my advice is you can present the loginPage and tell user that he has to login again to use the app.
I don't know if there is another way to get a new token, if there is one, use may not have to relogin,.
Also, I found a thread that may help: webapi-2-0-how-to-implement-refresh-jwt-token-when-access-token-expired
I am using resource owner password flow and i got successfully access token and refresh token and i did not persist any token in database and everything works fine locally.
But when i deploy identity server in production refresh token is not working as expected.
i have set access token expired time 20 minutes and refresh token expiry time 7 days.
if i refresh access token within 20 minutes or before expiry of access token then refresh token refresh access token and work as expected but after expiry of access token refresh token does not refresh access token and throw invalid_grant error.
As i did not save refresh token in database and i searched on google but answers are confusion.
So can anyone tell me :
Do i need to store refresh token while it is working fine locally without storing ? if yes any implementation reference i am using mysql as database.
or something else i need to look.
Thank you.
Your response is valuable for me.
When running IdentityServer4 locally and "out of the box", things like refresh tokens aren't persisted and that's usually fine in the early stages of development.
When planning to deploy your Identity Provider to a server however, you'll need an operational store anyway (for storing grants, user consent, etc.).
This operational store can also store refresh tokens and reference tokens (read up on it in the IdentityServer4 docs).
Setting up token storage on the IdP is a good idea. Storing tokens opens the door to clean token revocation. A cleanly implemented sign-out in a client application would call the token revocation endpoint on your IdP. That's because when a user logs out, neither the access token nor the refresh token is needed any longer.
You can also revoke tokens from your end, making subsequent API calls fail for that access token and there are some compelling use cases for that as well.
I am using Azure Service management API and OAuth API for generating Access token. But while making the call for grant type "refresh_token", to refresh access token it returns new access token but that response does not has new refresh token. So I have to use old refresh token for refreshing access token. And the problem is after 5-6 hours, refreshing token returns error invalid_client(Error validating credentials. Invalid client secret is provided).
In other cases like Office 365 app authentication via Azure AD it returns everything.
Is there is any specific parameter or header that I have to pass with the API call ?
Below is the screenshot of my code
Please help.
Thanks in advance
If you use the v2 endpoint scopes are requested dynamically and a refresh token must be requested using "offline_access" scope. This is much different than in the v1 model, where scopes are pre-registered with the app registration and a refresh token is always returned w/o explicit scope. If you're using v1 & you don't get refresh token, it might be due to restricted security policy about refresh tokens by your ADFS provider, which is not sending back a refresh token to the API calling the OAuth authentication and authorization.
This is security enhancement/block to disable your application not to hold a lifetime refresh token that can be lived forever (if refreshed).
So if you can use v2 endpoint - use offline_access scope. Otherwise check security policies with you ADFS provider.
I run into the same problem as you & gathered most of the information that helped to answer this question from here:
https://stackoverflow.com/a/44813531/4446128.