I am doing some testing around authenticating the webapi2.1 stuff and I am a little unsure how it works.
I have a webapi controller set with a [Authorize] so when I try call it without the bearer token I get the 401 as expected.
Step 1 - I generate a new token and add it to the header of my request and I get back the expected result.
Step 2 I generate a new token with the same account details. I can access the data using either the old token or the new one.
Why does the first token still work? I would have thought this should return a 401 using the old token?
Consider bearer tokens to be similar to a ticket at a movie hall or a museum. When you pay at the counter(Auth server) using cash or credit card(credentials like username/pwd) you are given a ticket (token from the Auth server). You can now use this ticket to access a secure environment (web page or method) that you previously couldn't access.
Buying another ticket for yourself doesnt invalidate the previous ticket you bought. You now have two tickets that do essentially the same thing. It has only costed you more. The cost in this case is another hit to the database to match your credentials.
Hope that makes sense.
Related
I am working on an eCommerce Website and an App. We use SAP Hybris for OAuth 2.0.
To get an access token I send a Cliend ID, Client secret, Username and Password to the auth server.
Problem Example:
If I log in with the App first and then the Website, I won't be able to refresh my token in one of the sessions.
The token I receive from the server is pretty standard and looks like this:
{
"access_token":"9T7IziRSIM_QIqFtttM8rhf83zU",
"token_type":"bearer",
"refresh_token":"MztkOmh67gIEiMwX5sED-Rug51c",
"expires_in":43199,
"scope":"basic"
}
The only difference is that in the "Website Token" the expires_in would have a lower value than 43199 since it was requested after the "App Token".
Since both the access_token as well as the refresh_token are identical, the moment one of them expire and we try to fetch a new token the first session that does it will receive completely different credentials. As soon as the second session (which is now expired) tries to also refresh it's credentials the server will deny new credentials since the old credentials can be used only once to get new tokens.
Every 12 hours the tokens become expired and the first client to request a new token effectively logs out the other client by doing so.
Question:
What could I do to deal with this problem?
I was thinking it should be possible to send a unique ID to my request to generate a unique token. However I cannot find any information about this on the SAP Docs.
I have implemented google-signin using the oauth2 from Angular Application.
Once authentication is successful and the token is generated, I am storing it in the LocalStorage/IndexedDB and also trying to send this Token, UserProfile info etc, to my flask-backend.
I would validate the token and continue the flow
Now, I want to use the user bearer token as my Session-ID, i.e, each API call I am doing, I will be doing by validating against this bearer token.
I believe by doing so, I will be able to avoid 'creating sessions' and also leverage the google-generated tokens for uniquely identifying users and the calls to backend.
Please let me know what security flaws this would give rise to and also what are the alternatives for the same
Although at the point of time I was making the question, it was a bit unclear on how to proceed, heres a summary of what I have accomplished -
1 - I have used Angular for frontend and I have refered this page
2 - While doing so, my doubt was how would I proceed with user authentication and how I would continue to register the user and get the required details like profile, contact, address etc.
What I have done ->
Once a bearer was issued, I was passing this info to backend and then, from the backend, I was reaching out to various google api's and getting relevant info with the bearer.
Also this bearer was being stored on client end so as to ensure UNTIL the token expires, I would continue to not issue another token and meanwhile, as and when the user session times out, I would read the locally stored(client side) token and validate it on backend,
should the token be valid, backend server would go and all the info for all the scopes, and deal the other flows accordingly.
I am working with Spring 5 and Java 8 and creating a RESTful client that will login to CoinBase and make trades for me at given times. I know there is an unsupported Java SDK for Coinbase out there, and I am looking into that code as well for clues.
I am using the CoinBase Oauth2 client in my Spring app, and it has been very successful so far. I make the authorization call with a callback URL. This opens up a dialog box and if I am logged in, asks me to authorize My Coinbase Acct with MyApp and I get an email indicating that this is done. If I am not logged into Coinbase already, then I get asked for my Coinbase username/password and then it is authorized, again I get an email that this is ok.
The next step I see is that my redirect URL is called with a code that is passed back with it. That code, as you all know, then allows me to request an access token. Which I can do, and yes, I get my access token. I can now make calls to Coinbase API with that Access token. However, this access token is only good for 7200 (seconds?), so for two hours? I want to be able to get an access token and have this automatically login to coinbase for me. I don't want to have to re-authorize every time I want to make a trade ... or do I have to?
It seems to me that the "code" that comes back from authorizing is very short lived, and I can use it immediately to get that access token.
So, for me the big question is ... for Coinbase API, how can I keep myself authorized indefinitely? I want to be able to be authorized already, and then get an access token on a regular basis so I can make trades for myself????? Is this even possible with coinbase API?
Do I have to use Coinbase Pro for that ability, which I am fine with using? Is it even possible with Coinbase Pro?
I am a newbie with Coinbase as it's yet another third-party API that I have learn the nuances of. I am not a newbie when it comes to writing Java code to access third-party RESTful api's.
So, any help would be much appreciated. Thanks!
I guess you are missing 'refresh token' in your application.
What is the purpose of a "Refresh Token"?
It is hard to say how to implement it without code snippets but here some steps that should help:
Take a look at coinbase article about refresh tokens they provide
https://developers.coinbase.com/docs/wallet/coinbase-connect/access-and-refresh-tokens
Obtain and save refresh_token as well as token after authorization
Create function that will be using your refresh token to obtain new pair (token, refresh_token). You can find curl example in step (1)
a. Make ExceptionHandler that will call (3) if gets 401 (i guess it is 401 - if token expired)
b. Save 'expires_in' from step 2 and check it before each request. Call (3) if needed
I'm creating an API server which will be consumed by a mobile app that I will work on later. I have yet to see any reference of API best practices related to user flow and returned data even after searching for several hours.
My question is whether the login response of an API should return the a personal access token with the refresh token along with the user info? Or should I just return the token and make another API call for getting the user info.
I could just do what I have in mind but I'm trying to learn the best practices so that I don't have to adjust a lot of things later.
I need suggestions as well as good references related to my question.
Thank you.
It depends on what you are using for your authentication. If you are using libraries like Laravel Passport or JWT, you can have the token endpoint which returns the access token, refresh token, validity period and the token type (Bearer). You can then have an authenticated endpoint which will be used to get a user's profile based of the token passed in the request header.
However, if you go through the documentation for those libraries, in most there is an allowance to manually generate a token. You can use this in a custom endpoint that will return the token as well as the user profile Passport Manually Generate Token.
If you are using JWT, you can also embed a few user properties in the token itself. The client can the get the profile info from the JWT itself without having to make a round trip to the server. Passport ADD Profile to JWT
If you have a custom way in which you are handling authentication, you can pass the token as well as the user profile in the same response.
In the end, it's up to you to decide what suits you best.
Have you looked at OpenID Connect? It's another layer on top of OAuth 2.0 and provides user authentication (OAuth 2.0 does not cover authentication, it just assumes it happens) and ways to find information about the current user.
It has the concept of an ID_token, in addition to the OAuth access token, and also provides a /userinfo endpoint to retrieve information about the user.
You could put user information in your access token, but security best practice is to NOT allow your access token to be accessible from JavaScript (i.e. use HTTP_ONLY cookies to store your access token).
I'm moderately familiar with OAuth2 and the concepts of the AccessToken and RefreshToken.
It looks like MSAL is doing some work for us when using ClientApplicationBase.AcquireTokenSilentAsync().
I'm not clear as to whether it will always check the expiration of the current AccessToken and automatically refresh it (using the RefreshToken) on method call.
Regardless, is there a "best practice" for how often we should call AcquireTokenSilentAsync() ? Should we keep track of the expiration ourselves and call this method to update our bearer authentication header? Should we be calling AcquireTokenSilentAsync() on every Request? (doubtful)
I can't see how the GraphServiceClient (tangent topic, I know) using the DelegateAuthenticationProvider will do anything helpful WRT refreshing. Do we need to extend that class and perform our own refresh when the token is nearing expiration? I feel like this would/should be already in the SDK.
Thanks for any tips.
-AJ
Update Nov 2020
This answer was originally written for V2 of the MSAL client. Since then a V3 has been released which may work differently from V2.
Original answer
I'm not clear as to whether it will always check the expiration of the current AccessToken and automatically refresh it (using the RefreshToken) on method call.
A refresh token is automatically supplied when the offline_access scope is provided, if I understand this answer correctly
...you've requested the offline_access scope so your app receives a Refresh Token.
The description of AcquireTokenSilentAsync implies that when an refresh token is provided, it will check the expiration date on the token, and get a new one if it's expired or close to expiring.
If access token is expired or close to expiration (within 5 minute
window), then refresh token (if available) is used to acquire a new
access token by making a network call.
It will repeat this behavior until the refresh token is expired. Optionally you can force a refresh of the access token via the refresh token by utilizing the forceRefresh parameter on AcquireTokenSilentAsync
Lastly, I am going to quote this answer on SO since it gives a nice insight about MSAL and tokens
Just to make a small clarification, MSAL doesn't actually issue tokens
or decide a token expiration, but rather ingests an acquires token
from the Azure AD STS.
MSAL will automatically refresh your access token after expiration
when calling AcquireTokenSilentAsync. .... The default token
expirations right now are:
Access Tokens: 1 hour
Refresh Tokens: 90 days, 14 day inactive sliding window
(June 13th '17)
Regardless, is there a "best practice" for how often we should call
AcquireTokenSilentAsync() ? Should we keep track of the expiration
ourselves and call this method to update our bearer authentication
header? Should we be calling AcquireTokenSilentAsync() on every
Request?
The documentation also lists a 'Recommended call pattern' for calling the AcquireTokenSilentAsync. The documentation also mentions that
For both Public client and confidential client applications, MSAL.NET maintains a token cache (or two caches in the case of confidential client applications), and applications should try to get a token from the cache first before any other means.
Based on examples I've seen, including the recommended call pattern from the documentation, I would argue you could simply call AcquireTokenSilentAsyncand catch the MsalUiRequiredException as an indication that the token has expired and the user has to log in again.
I can't see how the GraphServiceClient (tangent topic, I know) using the DelegateAuthenticationProvider will do anything helpful WRT refreshing. Do we need to extend that class and perform our own refresh when the token is nearing expiration? I feel like this would/should be already in the SDK.
If I understand the DelegateAuthenticationProvider correctly, what it does is modify the requestMessage before we pass it to Graph. All we got to do is provide our access token with an authorization header for the request. We already know that when we fetch our access token, it is valid, so we can just add it.
new DelegateAuthenticationProvider(async (requestMessage) =>
{
ConfidentialClientApplication cca = new ConfidentialClientApplication(_ClientId, _Authority, _RedirectUri, new ClientCredential(_ClientSecret), _UserTokenSessionCache.GetTokenCache(identifier, httpContext), _ApplicationTokenCache.GetTokenCache());
AuthenticationResult result = await cca.AcquireTokenSilentAsync();
requestMessage.Headers.Add("Authorization", result.CreateAuthorizationHeader());
//OR
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);
});
(There is no difference between either way of setting the headers)
I've been down this path and this does the trick for me. I highly advise reading their documentation, because it does gives a good insight in how to implement MSAL.Net.
I haven't had time yet to play around with the token durations yet. Nor the behavior if no refresh token is provided (if that's even possible)
I hope this helps!
Mentioning one thing missed above, quoting my answer to Get refresh token with Azure AD V2.0 (MSAL) and Asp .Net Core 2.0
For context, OAuth 2.0 code grant flow mentions the following steps:
authorization, which returns auth_code
using auth_code, to fetch access_token (usually valid for 1 hr) and refresh_token
access_token is used to gain access to relevant resources
after access_token expires, refresh_token is used to get new access_token
MSAL.NET abstracts this concept of refresh_token via TokenCache.
There is an option to serialize TokenCache. See Token cache serialization in MSAL.NET. This is how to preserve sign-in info b/w desktop application sessions, and avoid those sign-in windows.
AcquireTokenSilentAsync is the process by which refresh_token is used to get new access_token, but, this is internally done. See AcquireTokenSilentAsync using a cached token for more details and other access patterns.
Hope this clarifies on why TokenCache is the 'new' refresh_token in MSAL.NET, and TokenCache is what you would need to serialize and save. There are libraries like Microsoft.Identity.Client.Extensions.Msal that aid in this.
#AlWeber/ #Raziel, the following pattern would apply for PublicClientApplication:
on startup, to deserialization and load TokenCache (which has refresh_token), try acquire access_token silently.
if that fails, use interactive UI to fetch token.
save and re-use the AuthenticationResult, which has AccessToken and ExpiresOn. Redo acquire access_token silently (bit expensive if you are an API user, hence caching of result), once you are close to ExpiresOn property (personally, I set 30 min before expiry).
is there a "best practice" for how often we should call AcquireTokenSilentAsync() ? Should we keep track of the expiration ourselves and call this method to update our bearer authentication header? Should we be calling AcquireTokenSilentAsync() on every Request? (doubtful)
I don't think this is a good idea. As mentioned, this call is still a bit expensive. Alternative, is to store AuthenticationResult in-memory, re-use it, and go to silent acquire workflow only close to ExpiresOn property.