Implications of increasing the Auth token TTL / Best practices - laravel

Using JWT Auth + Laravel and Ionic for a mobile app.
I want to have the users stay logged in until they log out physically with a button. JWT has '60' (an hour) as its TTL for the token.
I know I could just increase this and be done, but I imagine there is a reason to having it only an hour by default.
There is lots of terms for refreshing tokens etc but can anyone give a quick summary of how to deal with long term tokens?
Do I set a refresh every 60 minutes, every request or is having a long TTL fine?

If you look at the jwt-auth package wiki page on authentication. There is a middleware Tymon\JWTAuth\Middleware\RefreshToken the way this works is.
This middleware will again try to parse the token from the request,
and in turn will refresh the token (thus invalidating the old one) and
return it as part of the next response. This essentially yields a
single use token flow, which reduces the window of attack if a token
is compromised, since it is only valid for the single request.
in my opinion as long as your application has fairly constant communication without long periods of inactivity ( more than your 60 min window ) this is the best way to go about keeping your token fresh.
If your not using the jwt-auth package you can still apply the logic you just need to pass back a new token in the header of your response, see the RefreshToken Middleware for an example of this.

Related

Delay/Skip Token Expiration

Tokens are valid for 30 days from creation or last use, so that the 30 day expiration automatically refreshes with each API call. Tokens that aren’t used for 30 days expire.
Is there an api that basically doesn’t return anything but acts as a kind of dummy call to keep from token being expired when not used for more than 30days.
Basically this is when the test sites which uses token if not used for a longer period expires.
I am aware that refresh tokens is a way to get around token Expiration but rather than getting refresh token ,I just need to keep making a call for the token be to active.
So its typically recommend that we have a script hit one of the basic endpoints to keep on calling after every few days to keep the token from expiration.
Here's a response from okta forum
https://devforum.okta.com/t/delay-skip-token-expiration/22026?u=farhin

Spring Boot JWT - How to implement Refresh Token and Logout REST-API

We decided to switch from Basic-Auth to JWT because of the session-ids that were stored in the memory and which leads sometimes to over-memory consumption in shoot-down of our Spring-Boot server that serves an Android mobile app like Twitter.
But we have some questions about JWT for our mobile use-case:
How long should an access token lives ?
How long should the refresh token lives ?
How to logout a User by invalidating his access-token and refresh token ? (For the logout we already delete the tokens on the mobile app side, but what if the tokens have being stolen by somebody and are still valid ?)
I will try to answer your queries
How long should an access token live?
You can easily configure expiry time so it depends on your requirement.
In general, try to keep it short.
How long should the refresh token live?
Above goes for refresh token with a condition that refresh token generally lives longer than access token for obvious reasons.
How to logout a User by invalidating his access-token and refresh token?
This part can be a little tricky.
You cannot manually expire a token after it has been created. So, you cannot log out with JWT on the server-side, as you do with sessions.
Can implement a few options like
When a user performs logout action or compromised. Have a blacklist which stores invalid tokens until their initial expiry date. You will need to lookup DB for every request but storage should be less as you will be storing tokens that were between logout & expiry time. You can make the blacklist efficient by keeping it in memory instead of DB.
Store Client IP Address in the claims objects JWT. When validating the token you can check with this client's IP address if it is the same source or not. You can refine it based on need like use User-Agent along with Client IP.
Worst of all reset user credentials or JWT token components to generate a new one which automatically invalidates all existing ones.
Adding a few links for more in-depth detail
Invalidate JWT Token
Destroy JWT Token
I mean it looks more like you should just be using sessions.
JWTs are not a simple replacement. They have a specific function and for some reason they have become embedded as some sort of automatic go to for any auth system.
From what you have described (the lifting of a basic auth to a more secure and modern auth system) you should be using sessions.
Good ol' Cookie sessions.
I'd go in to why more but to sum up:
A) You can control the session without odd stick on "banlist" tables and extra architecture for the JWTs for users that are banned/logged out for a system that doesn't actually need these if you just used traditional cookie based sessions.
B) They are tried and tested and the browser will keep them safe! Session cookies can be made "secure" and "http-only". There are many odd places people put JWTs including the local/session storage of a browser just waiting for a naughty js injected advert to suck them up. JWTs,just like SessionIDs, should
be in an Http-Only, Secure and Same-Site strict Cookie.
So you may as well just use a session ID and get on with life without strange front end state management when the browser is quite happy and doing that securely for you when using a Session Cookie.
C) Traditional sessions are easy to implement. Harder to understand how/why they work with all the SameSite/HttpOnly/CORS/Secure parts going on...but to implement when once understood is 99x easier and require less code when there is the Spring Framework already doing that 99% for you.
I mean sure it isn't hard to write your own JWTAuthTokenAuthFilter and implement a JWTAuthenticationProvider and a JWTCreationService and a `JWTAutoRefreshFilter...and whatever else you dream of...but why bother if you just need a session. Spring does it in like 20 lines of well tested code.
To sum up:
I mean of course properly implemented JWTs are secure...it is just maybe they are not always the best fit tool for a job.
Have a read of:
Stop Using JWTs for Sessions
Of course JWTs have a use. They are for letting a 3rd party know "yes, this is someone I know" before the client hits their API end points. Or for say having one of your servers talk to another of yours...or having client's servers talk to yours or even your servers talk to another companies:
JWT Auth - Best Practices

Server-to-server Facebook Access Token expires

I am building an Integration that allows users to schedule creation of Custom Audiences on the Facebook Ads platform. Once the user authenticates, we pass the client side token to the server from the client and then exchange their short lived token with the ads_management permission for a long-lived token, but that token only lasts 60 days?
The idea of the integration is that the user can set it and forget it (but disconnect any time). Now it seems like they need to visit the app at least once every 60 days. Is there any way around this? In my app, the person who turns on the Integration might not necessarily visit the app, or could leave the company and the integration would then break in 60 days.
You can simply ask Facebook for a new access token by passing your current access token.
It's as easy as exchanging the long-lived token, just re-call the same operation (using the current long-lived token). You will get a new one.
I suggest doing so some days before it expires (say, 10 days). This will ensure your system is going to have a spare time if any error occurs (e.g. Facebook's server down, User rejected permissions on your app, ...).
Just like Michael Hirschler said in his answer, you can simply use the old (non-expired) access token to fetch a new one. You should save the expiry date returned on every request when getting an access token: (This property is called expires_in)
{
"access_token":"{long-lived-user-access-token}",
"token_type": "bearer",
"expires_in": 5183944 //The number of seconds until the token expires
}
When expiration date is almost reached, you can use the same api endpoint for that with some changed query params. Insert your old access token as the user-access-token.
curl -i -X GET "https://graph.facebook.com/{graph-api-version}/oauth/access_token?
grant_type=fb_exchange_token
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={user-access-token}"
As you can see, you will also need your app-id and app-secret for doing so.
Further reading: https://developers.facebook.com/docs/facebook-login/access-tokens/refreshing/

access token / refresh token with MSAL

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.

Authorize PHP application permanently to make requests to JWT auth protected API

Maybe I searched with the wrong keywords but I never found anything about the following scenario:
I have both an API with JWT auth (Laravel + tymon/jwt-auth) and a PHP application that should query that API protected by a JWT token.
How can I make sure that the app always is authentificated? After reading a lot of tutorials and article about JWT auth I'm left with this ideas:
using a never expiring token which is stored permanently in the consuming application. If I understand it right this could be a security concern because someone who has access to that token has access to the api as long as he want? But I don't understand why this token shouldn't be invalidated if the token has been stolen?
refresh the token on every request and invalidate the old one. This implies that the consuming application have to update the token after each request in it's storage (database would make the most sense, I guess). In my opinion this produces a lot of overhead and it doesn't prevent for jwt-auth's refresh_ttl setting.
using an additional API request (perhabs cron based?) to a refresh route to prevent the token from expiring. Again there is the jwt-auth's refresh_ttl problem I think.
I wonder why there seems to be no discussions/articles about that scenario.
Any help on that subject I would very much welcome!
You don't want your user logging in every time but you also don't want them to be logged forever.
Here are my thoughts
I have worked with 1 year tokens for comercial applications, I was using it for low level third party developers, the api concept was already overwhelming for them so I went easy on the auth thingy. Once every year their application broke and they had to reach out to get the new token, bad design but it worked.
Refreshing your token on every request will kill your performance and let attackers have a consistent way to break/predict your key, no good.
In my opinion, this is your most elegant suggestion. You could use some PWA features to accomplish that.
I would suggest increasing the refresh_ttl to 30 days and keep the ttl on one hour.
If you're using SPA or heavy js apps:
On your javascript you could do an ajax setup (or prototype or whatever your javascript framework uses for oop) and have a call to refresh whenever you get a .
If you're using just common page refresh for your apps, store you JWT on a cookie, then your application can refresh it whenever it needs and there will be no special js to make. HTTPS will take care of security.

Resources