In our application new JWT token is returned in a cookie each time user sends a request, even though previous has still much lifetime. If user makes multiple request in a short period of time, there exists multiple valid tokens almost full lifetime on each. Browser is of course using the latest one, but someone may still use the previous ones to impersonate user.
Is there way to invalidate the previous token when dispatching a new one, or is the only choice to dispatch new token only when there is not much lifetime on the last one?
The only way to 'invalidate' tokens is by keeping track of them statefully.
This usually means doing something like keeping a key/value cache of tokens that are valid, and invalid, and checking incoming request tokens against these lists on each request.
The downside to doing things this way is that you lose a lot of the 'stateless' benefits of JWTs (since you are still checking a centralized store for token validity), but the benefit is that you can be more 'secure' by immediately revoking tokens you no longer want service-able.
One workaround is to have your access tokens be extremely short lived (5 minutes or so), to minimize any abuse.
Related
We are using the ADAL Mac library to authenticate. When using this library we get a 300 error (AD_ERROR_CACHE_MULTIPLE_USERS) with the description:
The token cache store for this resource contains more than one user. Please set the 'userId' parameter to the one that will be used.
When does this happen? How should one handle this scenario?
Background
ADAL has a token cache for all access/refresh tokens on the device. The cache keys on things like the user, resource being requested, etc.
The app can get into a state in which there are multiple tokens in the cache for the same request. While these tokens may represent something some different information, the information provided in the token lookup request was ambiguous in some way. Simple example:
Cache
hash(userA,B,C) -> token pair 1
hash(userB,B,C) -> token pair 2
hash(userA,F,G) -> token pair 3
Lookup (AcquireTokenSilent)
So now we do an AcquireTokenSilent request (cache lookup). This request doesn't require every pivot of the cache. For example,
AcquireTokenSilent(B, C)
There's ambiguity in this request, it could map to token pair 1 or 2.
Handling this Error
So there's two workarounds at this point:
Provide more information in the same request.
You can do a new AcquireTokenSilent request providing some more information that allows ADAL to definitively pick a cache entry. In this case, ADAL needs a userId meaning your app would need to store or lookup this value and pass it in the request. In our example,
AcquireTokenSilent(userA, B, C)
Ignore the cache and start from scratch.
If you cannot retrieve the userId and have no way to recover, your app can perform an interactive authentication request and ask the end user to enter their credentials. If you have a valid token, this is an adverse experience as your users will need to sign in more than necessary. This would just be a standard AcquireToken request. From our example (there's no user to request,
AcquireToken(B, C)
I have a system which gives an access to the set of resources via access tokens. So when clients need to access some particular resource they ask for the token (one resource - one token). I need to make one-off (or at least limited in time) token, to ensure even if tokens are leaked, they will soon become inactive.
What is the proper way to achieve that in CQRS based system? Querying the resource should not change the system state. In other words - we can't invalidate token in query handler. Can we?
These are different concerns. What I would do:
An edge check the authorisation (using the token provided) and
calls the query handler, together with the query/token info
Query returns the result
The edge publishes an event "TokenHasBeenUsed"
The edge returns the query result
Token provider consumes the event and invalidates the token.
You can also build it scheduling, invalidating the token after a while if not used. Plus, you can also have a usage counter or something and it all does not need to be blended to the edge or query handler.
I have a question about Spring MVC controllers scope and REST services. I have a couple of REST services, wich returns a token in the response so I can later recreate the state of the application, but I don't want the users use the same token twice, so I've decided to save an unique identifier inside the token and also in HttpServletRequest, so I can check it when I get the requests (a new identifier is generated in every request).
So, my questions are: 1) is there any other way to be sure that some user will not use the same token more than once (also considered to save that identifier in DB, but I would have lot of queries to insert, delete, verify, etc).2) is it ok for the controller that receives the requests to be a singleton, or should it be prototype? (considering that the identifier is taken from session and I don't want to mix it between different sessions).
A few words on tokens that are valid only once
It's not possible to achieve it
without keeping the track of the tokens somewhere. This security schema require some trade-offs, deal with it.
Give the user a token and keep the track of it on server side, just like a white list:
When a token is issued, add it to the white list.
When a request comes to the server with a token, check the white list and:
If the token is valid, accept the request and remove the token from the white list.
If the token is invalid, refuse the request by returning a proper status code such as 403.
Also, consider assigning an expiration date to the token and refuse any request that comes to the server with an expired token.
Regarding your performance concerns: Bear in mind that premature optimization is the root of all evil. You shouldn't optimize until you have a performance problem and you have proven that the performance problem comes from the way you store your tokens. You could start storing the tokens in the database and then consider a cache in memory, for example. But always be careful when fixing a problem that you currently don't have.
Working with JWT
If you go for JWT, there are a few Java libraries to issue and validate JWT tokens such as:
jjwt
java-jwt
jose4j
The jti claim should be used to store the token identifier on the token. When validating the token, ensure that it's valid by checking the value of the jti claim against the token identifiers you have on server side.
For the token identifier you could use UUID. In Java, it's as simple as:
String uuid = UUID.randomUUID().toString();
Since HttpSession#getId() is unique, you can use it to create an unique token:
// pseudo code
String token = httpSession.getId() + "-" + System.currentTimeMillis();
You can also create your own counter.
Here my two techniques to prevent it
Disable submit button:
We can disable submit button right before our function call HTTP request and enable it again after finish gets HTTP response. This technique is effective for the process that takes a long time to finish (more than 5 sec.). The user can not click n’ click again because of impatience to get the result. Additionally, we may show a loading box for a good experience.
Issue request token/id:
This technique actually more complicated and difficult to implement, but thanks to a good framework (such as Spring Boot) to make this easier. Before we are going to the code implementation, let’s talk about the mechanism first;
When form page is loaded, issue a new requestId
put issued requestId to HTTP header before calling the backend service
backend service identify a requestId is already registered or not
if requestId is already registered then we can mark as a violation request
I am curious about the value of PHPSESSID because, I created a simple login-type web app. When I try to login with different accounts, the value of the PHPSESSID is not changing. I got curious if it does okay or not. Because I tried to login in youtube with different account too. But their SID's differ on each user.
My question is:
1) Is what happening on my web app okay ?
2) Is yes, how can I make a session ids per account/user ?
3) If no, how can I fix it ?
I would really appreciate your suggestions.
It partly depends on exactly how you implemented "login." One way to do it is simply to change the user-identity (which, by definition, is part of the data that is stored in the session), while keeping the same session.
Another equally-valid way to do it is to first update the existing session (to show that the user, in that session, is now "logged off") (maybe...), and then to coin a completely new session-id, thus starting an entirely new session, in which you now "log on."
One advantage of the second approach ... and probably the reason why so many sites do it this way ... has to do with the possibility that the user might wish to open a new browser-window, and to log-in to the application a second time, intending to keep both logins alive at the same time. If the session-id token is part of the URL, or maybe is part of a hidden form or what-have-you, such that both session-id's can be retained independently, it becomes possible for the user to do what he has done without conflict. Two parallel sessions exist. In one, he is logged on as "joe," and in the second, he is logged on as "jeff." And so on. One set of browser-windows (somehow ...) carries the "jeff session" token; others carry the "joe session" token.
Fundamentally, a "session" is just a pool of server-side values, identified by the (PHPSESSID ...) token furnished each time by the client. Exactly how you choose to manage it, is at your discretion. It's a design-decision with no "correct" approach.
EDIT2: Clarification: The code ALREADY has refresh cache on miss logic. What I'm trying to do is reducing the number of missed cache hits.
I'm using Redis as a cache for an API. The idea is that when the API receives a call it first checks the cache and if the data isn't in cache the API will fetch it and cache it afterwards for next time.
At the moment the configuration is the following:
maxmemory 50mb
maxmemory-policy allkeys-lru
That is, use at most 50mb memory, keep trying keys in there and when memory is full start by deleting the least recently used keys (lru).
Now I want to introduce a second category of keys. For this second category I'm going to set a certain expiry time. Now I would like to set up a mechanism such that when these keys expiry this mechanism kicks in and refreshes them (and sets new expiry).
How do I do this?
EDIT:
Some progress. It turns out that Redis has a pub/sub messaging system which in particular can dispatch messages on event. One of them is expiring keys, which can be enabled as such:
notify-keyspace-events Ex
I found this code can describes a blocking python process subscribing to Redis' messaging system. It can easily be changed to detect keys expiring and make a call to the API when a key expires, and the API will then refresh the key.
def work(self, item):
requests.get('http://apiurl/?q={param}'.format(param=item['data']))
So this does precisely what I was asking about.
Often, this feels way too dangerous and out of control. I can imagine a bunch of different situations under which this will very quickly fail.
So, what's a better solution?
http://redis.io/topics/notifications
Keyspace notifications allows clients to subscribe to Pub/Sub channels
in order to receive events affecting the Redis data set in some way.
Examples of the events that is possible to receive are the following:
All the keys expiring in the database 0. (e.g)
...
EXPIRE generates an expire event when an expire is set to the key, or
a expired event every time setting an expire results into the key
being deleted (see EXPIRE documentation for more info).
To expire keys, just use Redis' built-in expiry mechanism. You don't need to refresh the cache contents on expiry, the simplest is to do it when the code experiences a cache miss.