In IdentityServer3, how should you link the Claims to Token in a custom TokenHandleStore implementation? - identityserver3

I am implementing an IdentityServer3 application, while closely following the EntityFramework IdentityServer3 solution. However, the problem is this...
When a Token object is saved, if the Claims are not somehow linked to the Token when the Token is saved here it will inevitably result in unauthorized requests when your client calls your resource server. This happens when the Token is loaded from the database because the Claims that were originally attached to the Token are no longer existent (since they were not saved).
The in memory solution in IdentityServer3 does not have this issue because your object stays in memory, so the list of claims inside the Token object stay "attached" to the token. See here for the in memory solution.
If you don't link claims to the Token upon the save, a reference token cannot be verified when it is retrieved from the database.
I imagine you need to save the relationship between the Claims and the Token when you save the Token. However, this is problematic because at that point in the code (see here) you cannot easily and reliably determine if a Claim is a Scope Claim, Client Claim or a User claim.
How will you properly insert a record into a joining/linking table that would link the Token to the correct claims table? Since there is a ScopeClaims table, a ClientClaims table and there can be a UserClaims table... Usually the claims associated with any given Token are a mixture of Client, Scope and User claims.
What are the recommendations for handling the Token save in such a way that it will keep the claims?
Update
As John pointed out, the EF solution serializes the entire Token object at save time so when the Token is queried a deserialization process occurs that re-hydrates the Claims and other fields that were in the Token. Following this approach you do not have to figure out a way to link the Claims to the Token using a join table or something similar. I initially overlooked this important functionality.

One approach is to follow what how the EF implementation handles it - by storing the extra claims as a serialized JSON string. Since that is written by the authors of idsrv, it's also a great reference :)

Related

Is my mongodb the right place to store my refresh tokens?

I am trying to implement a JWT Token/RefreshToken Auth Backend server.
There is a lot of resources out there, and it has been really helpful, but somehow nothings tell me how/where to save my refresh tokens.
I am working so far with a mongo db to store the information of my app. Is it safe to store my refresh token in the same db? Is there any more secured, or more performant solution I am not seeing?
Ideally, you should not even have to store your access or refresh tokens in any database. One of the main motivations behind the JWT pattern was to eliminate the need to persist session state in the server. Instead, the session state is maintained in the JWT tokens themselves. To better understand this, let's examine the simplest sequence of events when the server receives an incoming access token.
When the server receives an incoming access token, the first thing it will do is to check the claims section of that token. One of the claims, typically called exp, contains the token expiry date. Any access attempt in the server which uses an expired token will be rejected. The server also can ensure that the incoming JWT has not been tampered with by computing the checksum. Any token whose expiry or other claims have been doctored would fail the checksum test.
The main point here is that ideally a JWT acts as a standalone passport of sorts. There should not be a need to store it in a database for comparison or lookup. Sometimes, there might be a need to blacklist certain JWT. In this case, the need might arise to store them on the server. But here we would still not use a database, but rather a lightweight cache with really fast access times. And, we would only be storing a very small number of blacklisted JWT, so the server would still remain largely stateless.

Why is UserDetailsService being used in filters? JWT

I checked a lot of tutorials and examples of jwt, for example, if you google "spring-security jwt example" you will probably see those links:
https://www.callicoder.com/spring-boot-spring-security-jwt-mysql-react-app-part-2/
https://dzone.com/articles/spring-boot-security-json-web-tokenjwt-hello-world
https://www.javainuse.com/spring/boot-jwt
Question) Their authFilters use UserDetailsService, so they fetching data from Database as it just a Simple Token, and not JWT.
So I think I don't understand something.
UPD: what I would do:
Or create my custom Authentication and custom AuthProvider.
Or just use JwtUtil class which will decode jwt and then create default UsernamePasswordAuthToken and set it into SecurityContextHolder.
After another review, I noticed, that I missed important note in Rajeev Singh's tutorial on callicoder
Note that, the database hit in the above filter is optional. You could
also encode the user’s username and roles inside JWT claims and create
the UserDetails object by parsing those claims from the JWT. That
would avoid the database hit.
However, Loading the current details of the user from the database
might still be helpful. For example, you might wanna disallow login
with this JWT if the user’s role has changed, or the user has updated
his password after the creation of this JWT.

What benefit does JWT provide?

I have implemented JWT based security in a test Core Web API REST project, it is working fine but I am not sure that I see the benefit of this. The web says JWT is good because it's lightweight and can be used to verify that the source of data but in my implementation:
The client first provides a username and password to authenticate
If user + pwd is ok the a token is returned and every subsequent call to the api uses that jwt token (instead of the username and password) to authenticate.
This is fine but why not just use the username + password on every call to the api (and skip the complication of managing the token)?
In fact in my case there's additional complications because I now have to factor in an expiry date (of the token) that resides outside of my system.
Can someone explain what I'm missing here?
One of the main benefits and motivations for using JWT is that it allows your server side application to push all session state information outside of the application. That is, in a theoretical limit, a JWT implementation is actually stateless.
To directly answer your question, we can compare the workflows for what happens when username/password is submitted in every request versus submitting a JWT.
First, a JWT contains a claims section, which is typically written by the issuer of the token, i.e. the server side application. One of the fields is called exp, and contains the expiry time of the token. One property of JWT is that it is not possible for the user to tamper with them. This is enforced via a checksum, which would change if any part of the JWT changes. Taken together, this means that the user cannot alter the expiry time (or any other claim), and the server can implicitly trust this time. When the user submits a request with a JWT, in theory all the server has to do is just check exp to see if the token still be valid. That is, the session state actually lives outside the application, at least in theory.
In contrast, when the user submits a username/password each time, the server has no way of knowing what to do just based on that information. Rather, the server has to maintain the session state itself, and this can be costly both in terms of memory and performance.
In practice, JWT is never completely stateless, but, using a good implementation, it is usually possible to get the memory footprint very small, requiring only a bit of space in a cache (e.g. Redis or a similar tool).

JWT and one-time tokens?

I'm in the process of rolling my own JWT token auth, however, I would really like it to be a one time-token – so once it's used, the server generates a new token and the client will have to use that token during the next request/call.
However, it has come to my understanding that JWT is supposed to be 'stateless' – but with the approach of a one time token, I guess I would need to somehow store the valid tokens, since the token will be refreshed once it's used. Or is there any way to avoid storing a value on the server, and still be able to create one-time tokens?
The two main reasons for why I don't want to store any value is first of all scalability (sure, I could have cache-server inbetween to store the values, but it would be nice if that wasn't required), secondly, JWT is supposed to be stateless from my understanding, which it wouldn't be if I need to store a value on the server to be able to validate the token.
Any ideas?
Use the user's current password's hash for signing the JWT token, in this way all tokens generated before a successful password change would get invalidated the next time. I got the idea from here https://www.jbspeakr.cc/howto-single-use-jwt/.
Solutions exist, of course.
As with any distributed system (you mentioned scalability) you have to choose between availability and consistence.
You choose availability. In this case you could maintain a list of already-used tokens that you replicate in a eventually consistent manner between all the endpoints. For example when a token is used the respective endpoint send that token to the other endpoints in the backgound. There is however a (short) time frame when that token can be used a second time by another endpoint until that endpoint is updated.
You choose consistency (you won't allow a token to be used multiple times whatsoever). In this case you use a central database with already-used tokens and you check that database everytime you need to perform an action. Scalability? You could use sharding on the token and have n databases, each one being responsible for a tokens subset.
It depends on your business what solution fits best.
Not really no, a JWT token is valid if it hasn't expired and the signature is correct, commonly people will keep a DB of blacklisted tokens which are usually ones where people have logged out etc.
The only sensible way I can think of is give them a short expiry time and maintain a list of tokens that have already been used, you'd then periodically remove the ones that subsequently expire from the DB.
There are actually some DB's that have a TTL on records (dynamoDB, mongodb) so you'd just put the tokens in and set a TTL for when the token expires.
Update 2022
Just to be clear JWT tokens AREN'T stateless they have claims that, as long as they're signed by the right private key - give you a stateful piece of data that can be reissued by your API to reflect the current state of the user.
You'd just need to handle token re-issue on the consumer.
Like others have mentioned, it depends on your business case. Password resets links can be like mentioned on https://www.jbspeakr.cc/howto-single-use-jwt/.
If you have the Single-Use & Single-Auth scenario, where you might want to invalidate any previously used and unused token, you can store a single nonce and update it on every new token request and also when its used.

How to make a valid access token invalid

In restful application, for some reqirements,e.g. On client side,for the same user can using only one access token at the same time and user can get new access token via login successfully.if logined twice,the user will got two different access token say it's access token A and B.In the backend,when user still use token A to talk with server, it should be invalid and the latter B should be valid!How to implement this without using cache framework or db?
Additionally in the backend, i don't want store any access token, the access token contains simple user info and timestamp etc, which is a string encrypted with aes and encoded with Base64.
Unfortunately, you won't be able to do what you want without persisting the tokens.
I answered a question related to token based authentication before. Maybe you can get some inspiration from there.
Different types of tokens
Basically, a token can be opaque (which reveals no details other than the value itself, like a random string) or can be self-contained (like JSON Web Token).
Random String: A token can be issued by generating a random string and persisting it to a database with an expiration date and with a user identifier associated to it.
JSON Web Token (JWT): Defined by the RFC 7519, it's a standard method for representing claims securely between two parties. JWT is a self-contained token and enables you to store a user identifier, an expiration date and whatever you want (but don't store passwords on it) in a payload, which is a JSON encoded as Base64. The payload can be read by the client and the integrity of the token can be easily checked by verifying its signature on the server. You won't need to persist JWT tokens if you don't need to track them. Althought, by persisting the tokens, you will have the possibility of invalidating and revoking the access of them. To find some great resources to work with JWT, have a look at http://jwt.io.
Persisting tokens
There are many databases where you can persist your tokens. Depending on your requirements, you can explore different solutions such as relational databases, key-value stores or document stores.
Just remember to remove old tokens in order to prevent your database from growing indefinitely ;-)
The access token must be send in every request in Authorization header. For every user you store his access token. So access token arrives, you check its value and find which user it is. If you do not find access token, user is not authorized.
So basically when you generate new token, you replace the old access token for given user, when old access token comes you are not able to recognize it (it is not stored anywhere), therefore it is invalided.