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

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.

Related

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

IdentityServer4 how to store and renew tokens in authorization code flow

I am looking for the best approach to work with the IdentityServer4 autorization code flow.
My apps system is quite ordinary: I have an MVC client, a WebAPI and the IS. I also use AJAX to request the API from the client side. So I need the access token on the client side to put it into the authorization header.
Is it good idea to store access token in the cookies?
Do I need self-contained or reference token (it is about security, I suppose)?
What is the best approach to renew when it was expired?
I thought about the two strategies:
Update access token when the first 401 status code was recieved. Can be the problem cause I send more than 1 query to the API and I need to synchronized them and recall the first one (to get result);
Every time before API calling call the MVC client method with GetTokenAsync, check the expire time and get or update and get access token. Seems cheating, cause I need to call the MVC client every time when I want to call the API.
Could you help me to find the best way?
"Is it good idea to store access token in the cookies?"
No, not with the authorization code flow. If you are using an MVC web application you should find a way to store tokens in some kind of datastore away from the browser. All the MVC application should administer is a cookie to access future MVC endpoints (that will make subsequent calls to Identity Server with the appropriate access token in the datastore).
"Do I need self-contained or reference token (it is about security, I suppose)?"
That's all up to you and what you think is best for your use cases. If you'd like to see the information in the access token and skip the extra backend call for validation then use reference tokens. Strategy 2 requires you to use self-contained tokens so that you can check the expiry.
"Could you help me to find the best way?
I don't know if I can give the "best" way, but I'd probably go with strategy 2 and use self-contained tokens.
EDIT: If you wanted to use "axios , to get data from the API" then I would suggest using the implicit flow which has no concept of a refresh token. In this case, leaving it in the cookie should be OK.

Does custom security HTTP headers violate separation of concerns

Does custom application specific, security related HTTP headers violate separation of concerns, is it considered a bad practice? I realize using custom header to control the service would tightly couple the client with the service implementation. Or in this case, to control the security framework behavior. The context where I planned using the custom header is the following:
We are using token based authentication, where token has a fixed lifetime, and new token is issued each time authenticated client calls the web API. SPA client may call the server with AJAX in two contexts
User action (navigation and submit)
Automatic refresh (current view re-fetches data at fixed intervals)
Now, if user leaves the page open, the session never expires, as new token is generated for each automatic fetch. Somehow, we need to differentiate user action from automatic refresh in the server side, and issue new token only for user actions.
I realize Websocket based refresh would be one solution, but we have decided to stick with timed AJAX call due specific matters. Another solution would be to provide token refresh as a separate endpoint, but this would violate the DRY principle from client's perspective, and would be more cumbersome to setup with Spring Security.
Only remaining option is to embed the user/automated information in the request itself, and using a header seems a viable option here. A presence of certain header would prevent the token refresh. Easy to implement with a few lines of code.
I'm only concerned, if this couples the client too much with the service implementation. Technically, it doesn't couple client with the service, but the preceding security filter, thus leaking security concerns in the user interface. Ideally security stuff should be transparent to user interface, so new client could be coded without knowing anything about security (especially when cookies are used).
In the other hand, this solution isn't destructive or mutative. It's an optional feature. By client utilizing it, security is enhanced, but in either case never reduced (from the perspective of server, as it is). Now the question is, what principles using a optional header to enhance security is violating, and is it a valid solution in this context?
In my option the security should be maximized transparently, but I don't see how to not leak security concerns in the client in this situation.
It sounds like you're using your own home-built custom Token Authentication solution here. This is not a good idea.
I'll take a moment to explain WHY you don't want to do what you're proposing, and then what the better option is.
First off -- the problem that you're trying to solve here is that you don't want a user to remain logged into your site forever if they leave a tab open. The reason you need to fix this is because right now, you're assigning a new Access Token on EVERY REQUEST from the user.
The correct solution to handling the above problem is to have two types of token.
An Access Token that has a very short lifetime (let's say: 1 hour), and a Refresh Token that has a longer lifetime (let's say: 24 hours).
The way this should work is that:
When the user first authenticates to your service, the Access and Refresh tokens are generated with their respective timeouts.
These tokens are both set in HTTP cookies that the client-side JS cannot access.
From this point on, every time your user's browser makes a request to your service, you'll parse out the Access token from the cookie, check to see if it's valid, then allow the request.
If the Access token is no longer valid (if it has expired), you'll then parse out the Refresh token from the cookie, and see if that is valid.
If the Refresh token is valid, you'll generate a NEW Access token with another 1 hour lifetime, and override the old Access token cookie with the new on.
If the Refresh token is invalid, you'll simply return a 301 redirect to the login page of your app, forcing the user to manually re-authenticate again.
This flow has a number of benefits:
There is a maximum session length, which is technical (duration of Refresh token + duration of Access token) -- aka: 25 hours in this example.
Access tokens are short lived, which means that if a token is somehow compromised, attackers can't use it for very long to impersonate the user.
What's nice about the above flow is that it is a web authorization standard: OAuth2.
The OAuth2 Password Grant flow does EXACTLY what you're describing. It generates both types of tokens, handles 'refreshing' tokens, handles the entire thing from start to finish in a safe, standards-compliant way.
What I'd highly recommend you do is implement an OAuth2 library on both your server and client, which will take care of these needs for you.
Now -- regarding the tokens, most OAuth2 implementations now-a-days will generate tokens as JSON Web Tokens. These are cryptographically signed tokens that provide a number of security benefits.
Anyhow: I hope this was helpful! I author several popular authentication libraries in Python, Node, and Go -- so this comes from my direct experience working with these protocols over the last several years.

OAUTH2 - Using refresh tokens to implement sliding expiration

I have a single-page web application that uses OAuth bearer tokens to authenticate users. We do not use cookies, and there is no support for sessions. It simply makes calls to an ASP.NET Web API to access protected resources with an access token. We also support refresh tokens to obtain a new access token.
How would I implement a sliding expiration? I only see three options:
Issue a new access token on every request using the refresh token. This defeats the whole purpose of refresh tokens.
Track when the last request was in the client app. Each request would see when the last one was, and if it was after a set period, log them out and bring up the login screen. If not and their access token has expired, issue a new one and let them continue. This seems kind of messy and insecure to me.
Forget refresh tokens. Store access tokens in a database with the expiration date and update it on every request. I prefer to not do a DB operation on every request.
Is there another option or do one of these actually sound acceptable?
You said there is no session support. But this is pretty much what sessions are for, and ASP.NET and IIS support them with quite a few options for how they are managed, with or without cookies and with or without a database if I recall right. If sessions are not available in your case...
There is also the option of using an encrypted token, which contains session identity and timeout info. Then the server merely needs to know the key for decrypting the token. The server decrypts the token on each request, updates the time and sends a new encrypted token back with the new response. You can send the token as a header, cookie, part of url, take your pick. But cookies and headers are designed for this use pattern and take less work in my experience.
A token that does not decrypt is treated as an unauthorized request. Timeout is handled as you normally would, e.g. using the refresh token to get a new authentication.
If you have a server farm, only the key for decryption has to be shared between the servers. No need for a session in a database or shared cache.
You can elaborate this to expire keys over time. Then servers only have to infrequently check with a directory service, shared cache, or database, message or queue to get the most recent keys. If you generate them properly and expire them faster than someone can brute force hack them, you win! (joke) Windows has apis to support you on the encryption and key management.
I did this for a project years ago with success. It is, in effect implementing sessions without server side state. And as with all session methods and all authentication methods it has vulnerabilities.
But without some special reason to the contrary, I would just use sessions for their intended purpose. If I want each browser tab to have separate authentication I would use header based session tokens. If I want browser tabs in a browser session to share authentication I would use session cookies.
Or I would use your option three, maybe with a shared cache instead of a database, depending on performance requirements and infrastructure. I suspect that IIS+ASP.Net may even do that for you, but I have been away from them too long to know.

Protect Web API from unauthorized applications

I am working on a web page that uses a lot of AJAX to communicate with the server. The server, in turn, has an extensive REST/JSON API exposing the different operations called by the web client.
This web site is used by both anonymous and authenticated users. As you might expect, the web service calls issued by authenticated users require authentication, and are thus protected from unauthorized users or applications.
However, the web site has a lot of features that require no authentication, and some of these make use of anonymous web services. The only way I am using to prevent outsiders from calling this web services is by using a CSRF token. I know, the CSRF token is not very useful in this regard... with some time in hand, you can figure out how to consume the web services even if they use a CSRF token.
Of course, you can use a CAPTCHA to prevent applications or bots from autonomously using your web service. However, any human will be able to use it.
Sharing a secret key between client and server, on the other side, would be useless. This, because of the ability of any outsider to read it from the web page source code.
I would like to make these web services as difficult to invoke as posible to any 3rd party application. What would you do besides using the CSRF token? It sounds a little stupid, but hey, maybe it is stupid and I am just losing my time.
Note: given this application uses a browser and not an "executable" as the client, this question is irrelevant to the discussion. I cannot use a secret between server and client (not to my knowledge, at least)
I would take a few steps.
Force https on the site. Automatically redirect any incoming http requests to https ones (the RequireHttps attribute is handy for this)
Each page needs to (securely, hence the https) send a one-time use token to the client, to be used for the page. The script running on the client can hold this in the page memory. Any request coming back sends a hashed & salted response, along with the nonce salt. The server can repeat the steps with the saved token + salt and hash to confirm the request. (much like explunit's answer above)
(It's worth noting that the secure request from a client isn't being authenticated from a user account, merely a token sent with the full page.)
The definition for one-time could either be session or page load, depending on your security vs convenience preference. Tokens should be long and expired fairly quickly to frustrate attackers.
The SSL + Hash(token + nonce) should be enough for your needs.
This is interesting. Below is a crazy suggestion. Remember, your question is also equally crazy.
Your website, once opened through a browser, should generate a long polling connection (Comet programing). This will create a unique session between the browser and the server. When ur JS is making the ajax call, send some token (unique token every time) to the server through the long polling thread. Let the AJAX also send the same token. At the server, get the AJAX token and check whether you have a similar token in you long polling session. If yes, fulfill the request. Any coder can break this. But, it won't be easy. Chances are the freeboarders won't even see these second piece of comet code. You can implement the comet code in such a way it is not easy to detect or understand. When they call ur service, send a 'Service Unavailable' message. They will be confused. Also make the comet code https.
You can also check how long that long polling thread is open. If the session was just opened and you get a ajax call right away, you can assume it is a 3rd party call. It depends on ur website flow. If ur Ajax call happens after 1 second of page load, you can check for that pattern on server side.
Anyone coding for your public api, will have 1 to 2 secret checks that they wouldn't even know and even if they know, they might be discouraged by all the extra coding they have to do.
You might have an easier problem than the one described in the linked question since you don't need to distribute a binary to the users. Even if your app is open source, the HMAC/signature key (in the "Request Signatures" part of that answer) can be controlled by an environment/configuration setting.
To summarize:
The secret key is not actually sent between client and server. Rather, it's used to sign the requests
Be sure that the requests include some unique/random element (your CSRF key probably suffices) so that two requests for the same API data are not identical.
Sign the request with the secret key and append the signature to the request. You linked to a PHP question but not clear if what language you're using. In .Net I would use a HMAC class such as HMACSHA256.
On the API server-side use the same HMAC object to verify that the request was signed with the same secret key.
Maybe you could use counters to keep track of conversations. Only the Server and Clients will be able to predict the next iteration in a conversation. This way, I think, you can prevent third party applications to impersonate someone (Just an idea though).
At the beginning, they start talking at some iteration (i=0, for example).
Every time the client requests something, the counter is incremented by some number in both the server side and the client (i=i+some_number).
And, after a few minutes of no communication, they both know they have to reset the counter (i=0).
This is just an idea based on the concept of RSA and also placing Fraud Detection on your system. The Risk from Authorized users is minimal however they can attempt to make anonymous calls to your web-service too.
For UN-Authorised users : For each web-service call , generate a token say using RSA which changes after some time(can be configured say 30 min). This way prediction of code is minimized. I have not heard of RSA collision till now. Send this token back to the user for his browser session. For further security , we might want to attach a session id with RSA token. Since session ids are unique new anonymous calls would require new session id.
Calls can be tracked using Auditing mechanism. Also per-web service there can be a different RSA setup. How the Algorithm for Fraud Detection would work is a challenge by itself.
For Authorized Users :
Every user should be tracked by his IP Address using Header block. The RSA token principle can be applied.
The solution is very vague but worth considering.

Resources