I have implemented Oauth2.0 using JWT token until it seems to be basically worked with Spring Boot.
Question1 : I can call this URL in order to get 'access_token' and 'refresh_token' as a response.
https://myapp/oauth/token?grant_type=password&username=______&password=_______
But when every time I re-called the url, both access_token and refresh_token were regenerated and the old access_token can still be used until it expired.
Is it how it really works?
Regenerate both every time?
Question2 : Moreover, when I need to refresh my access_token, I called this URL
https://myapp/oauth/token?grant_type=password&username=______&password=_______
I, again, got both new access_token and new refresh_token. It is pretty strange for me that refresh_token was used to generate a newer refresh_token. But the old refresh_token can still works?!
If this already what JWT token should really work, please tell me why we need refresh_token when we can call the first URL to get new token anyway.
I have spent sometime on this but still could not find a clear reference mentioning these things.
If you could tell me the right flow that it should work I would appreciate that.
Thank you in advance.
Regarding Question 2: yes, you get a new access_token and refresh_token.
It's up to you (or whoever is responsible for the RefreshTokenProvider) that the resfresh_token can only be used once.
This blog article: http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/ (scroll down to step 6) shows an example.
Related
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
It seems Google's official package Oauth express-oauth2-handlers hides too much information. On e important piece is how do we get refresh token or where is the refresh token stored?
Here is how I use it:
const auth = Auth('datastore', requiredScopes, 'email', true);
Then auth succeeds, the access token in stored in datastore. But refresh token is not there. So I am curious where to retrieve it when the current access token expired.
I took a quick look at the source code and it seems that the refresh token is stored inside the JSON encoded and encrypted stored token.
You can take a look yourself on github.
If the token is expired (or close to expiration date) the library makes a call to refresh the access token providing the refresh token stored in the oauth2credentials or from the token if the former doesn't exists.
Note: I have never used this library, maybe it's worth to wait for somebody with a deeper knowledge about the topic to give a more detailed answer.
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.
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.
I'm at the point of involuntary hair loss while trying to refresh the Yahoo OAuth access token in Ruby.
Using the OmniAuth and OAuth gems, I'm able to get an access token from Yahoo, however it expires in one hour.
I'm following the Yahoo instructions to refresh an expired token, and am consistently returned a 401.
If someone could show me how to refresh the access token using the OAuth gem, I'd be greatly appreciative.
First, make sure you are saving your oauth_session_handle parameter from your original get_access_token call.
Then, when you are looking to refresh the access_token do something like this:
request_token = OAuth::RequestToken.new(consumer,
config["ACCESS_TOKEN"],
config["ACCESS_TOKEN_SECRET"])
token = OAuth::Token.new(config["ACCESS_TOKEN"],
config["ACCESS_TOKEN_SECRET"])
#access_token = request_token.get_access_token(
:oauth_session_handle => config["SESSION_HANDLE"],
:token => token)
... where ...
config["ACCESS_TOKEN"] is your old access token
config["ACCESS_TOKEN_SECRET"] is your old secret
config["SESSION_HANDLE"] is your oauth_session_handle
consumer is your OAuth::Consumer.new reference
I store the config variable in a yaml file and then load it on startup.
Remember to store the #access_token for next time.
I adapted this from an answer at YDN OAuth Forum.
Note: oauth_session_handle is returned as a param by the call to get_access_token:
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
oauth_session_handle = access_token.params['oauth_session_handle']
This was less than obvious from looking at the oauth-ruby/oauth code