Why django-rest-framework stores token in database? - django

Is token supposed to be stored only in client-side not in server-side?
from rest_framework.authtoken.models import Token
Django-rest have a model for token, that means token is stored in database.
So why Django-rest store token in database?

It depends on the token type
Some tokens are just a unique random string and the only way of knowing which user is associated with it is to store it somewhere and then look it up when needed.
There is also another type of token which doesn't need to be stored. Basically, you encrypt the token string with a key and then send it to the user.
The string must include some sort of data that you can find the user with.
For example, you can create a token string like this: userID=2-some-random-string. Then you encrypt this string with a key and any algorithm you think that will work best for you and pass it to the user. When you receive the token from a user, all you need to do is to decrypt it using the key and extract the user id from that string. if there wasn't any user id or token failed to get decrypted, then the token is not valid.
Django rest framework uses the first type of tokens which they need to be stored somewhere.
There are other libraries for rest framework that works with other types of tokens. You can choose between all of them based on your needs or even you can create one yourself.

Related

Delete expired tokens from database (Django + JWT)

Currently I am using JWT (rest_framework_simplejwt) with Django Rest Framework.
The database table containing tokens got bigger and bigger.
Is there any way to delete all expired access tokens from the database?
I mean all expired Outstanding_Tokens and Blacklisted_Tokens related to them.
I tried running the following command from django shell but didn't work:
from rest_framework_simplejwt.tokens import AccessToken
AccessToken.objects.filter(expires__lt=datetime.now()).delete()
==>
AttributeError: type object 'AccessToken' has no attribute 'objects'
Thanks a lot for your help!
The short answer:
JWT Tokens are not stored in the database. Thus you do not need to delete any tokens. There isn't any django models declared in simplejwt.
The long answer:
AccessToken is only an object not a django model. Thus it does not support what you are trying to do. JWT is a type of token that the expiry date and the additional data are encrypted with a passphrase where only server side knows. Frontend will have this encrypted data with user information but cannot read it. Whenever the request is made its way to backend, it's being decrypted and with the information you may authorize user.
JWT tokens are not being stored anywhere. Unless the expiry date not passed the token remains valid. In some cases you want existing tokens to be invalidated. Then you need to store these tokens, if these tokens(blacklist) are used, you need to refuse them. simplejwt app also provides a blacklist app which handles the blacklist operation. If you are referring to them there are 2 models. Then to delete those you might need to use the following code:
from rest_framework_simplejwt.token_blacklist.models import \
OutstandingToken, BlacklistedToken
BlacklistedToken.objects.filter(token__expires_at__lt=datetime.now()).delete()
OutstandingToken.objects.filter(expires_at__lt=datetime.now()).delete()

Is there a way that we can avoid multiple token generations for a single user if he/she try to login on different browsers?

I am using django-rest-framework-jwt in my backend and calling API's from Angular Project.
When user try to login on multiple Browsers, each time a new token is generated for the user on new browser. And every token is valid.
What I want is that when user is already logged in in one browser and he/she tries to login on second different browser the previous token for first browser should be invalidated.
In a simple word, NO, you can't just avoid generating tokens unless you made a little twist in django-rest-framework-jwt module. But that's not pure jwt anymore.
JWT stands for JSON Web Tokens and it's a mechanism for exchanging data between computer systems that happens to be convenient for generating authorization headers that can be used to implement statless auth in web apps.
SO
stateless means that you don't track user tokens, You just verify them. If token is valid and the payload is valid, then OK. It doesn't care how many tokens are generated and it doesn't care that they are related to one user. The token is created based on timestamp and will be verified compared to lifetime and timestamp of it.
It means that django rest jwt module, will create a token based on current timestamp of system, whenever user request for it.
Remember you can't delete a jwt token. Because it's not stored in database. So if your token is spoofed, that's it. You can't do anything with it, unless life cycle of the token ends and token expire.
If you want to track these tokens and be able to control them and for example don't create redundant tokens for a user as you asked:
consider changing to another token based authentication that stores token in database so you could track it.
change jwt system to what is suitable for you (I did it before). For example add a lookup id in database and check tokens by that bounded to each user. I know it's not jwt anymore, But you can still use some goodies of it. Like don't hit database on not valid jwt tokens and store some payload in it, if verified don't hit database for that info. Like permissions and ...

How does default_token_generator store tokens?

I recently built a Django-based authentication system using a tutorial. Within this System I created a token within a forms.py. This Token is then send (as a link) in an activation activation mail.
from django.contrib.auth.tokens import default_token_generator
token = default_token_generator.make_token(user)
The view which receives the get request matches the token and the user-id supplied in this link and checks the token using:
default_token_generator.check_token(user, token)
This verifies that the token was sent though my site. But I don't understand the process. The token is unique but I don't seem to save the token somewhere? So how does check_token()verify the token?
A token consist of a timestamp and a HMAC value. HMAC is a keyed hashing function: hashing uses a secret key (by default settings.SECRET_KEY) to get a unique value, but "unhashing" is impossible with or without the key.
The hash combines four values:
The user's primary key.
The user's hashed password.
The user's last login timestamp.
The current timestamp.
The token then consists of the current timestamp and the hash of these four values. The first three values are already in the database, and the fourth value is part of the token, so Django can verify the token at any time.
By including the user's hashed password and last login timestamp in the hash, a token is automatically invalidated when the user logs in or changes their password. The current timestamp is also checked to see if the token has expired. Note that even though the current timestamp is included in the token (as a base36 encoded string), if an attacker changes the value, the hash changes as well and the token is rejected.

How to extract/decode expiration time from externally issued Json Web Token

so I am working with a 3rd party RESTful webservice where I have to authenticated myself by requesting a JWT and provide it to any further requests.
I do that by just posting my username and password and recieve a token for this. I neither know the secret used to create the token nor anything else besides username and password.
Now, I would like to check the expiration time of the JWT before I either reuse it for subsequent webservice requests or just renew it. I know i could just used it and catch some kind of expiration exception but I would prefer not to.
I tried to follow this tutorial: [https://stormpath.com/blog/token-auth-for-java]
but get stuck at the point where I have to provide signing key.
How would I do that since I do not have the secret used to encode it.
Bye the way: I am working with groovy and wslite on this one.
You should just be able to take the body of the token, and decode it.
The private key isn't used to encrypt the body of a JWT, it's just used to generate the signature...
So, in Groovy you can just do:
// A JWT from the link you gave above
String key = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9.43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs'
// Just the body (middle section)
String body = key.split(/\./)[1]
// Un base64 it (using the Java 8 Base64 class)
String unencoded = new String(Base64.decoder.decode(body), 'UTF-8')
// Parse the json into a map
Map data = new groovy.json.JsonSlurper().parseText(unencoded)
// Get the expiry
long exp = data.exp
assert exp == 1300819380
Of course, there's nothing to say that the body of the token has to contain any form of expiry time for you to look at... It could just be an internal ID
If you don't know the cipher used to encode it nor want to crack their cipher then you can't decode any information from the token. There is nothing like 'standard information that must be encoded in token', there's no need to the token that it should contain any ciphered information at all, it could be just an randomly generated UUID stored on their side in DB, so in that case you can't decode it at all.

Is there any point in encrypting identity tokens?

I am developing a restful web service and it needs securing. I am doing this using a token system where the client passes a token unique to them via the request header. The service has to be called via HTTPS.
I have seen a few articles which encrypt the token but is there any real benefit to doing this as the token would naturally be encrypted by HTTPS anyway....?
After re-reading the above I realise that it is not entirely clear what I meant...
The articles I have seen give the client a pre-encrypted Token which was encrypted with a public key. They then decrypt this token on receipt of the request and check it against the stored unencrypted token. To me it seems that this has no benefit over simply giving the client an unencrypted token and saving on the whole decryption overhead....
I think it's a broad question and the answer will depend on your requirements. But, in most of cases, you won't need cryptography in your identity tokens.
Identity tokens (used to perform authentication) can be opaque (tokens that reveal no details other than the value itself, like a random string) or can be self-contained (like JSON Web Tokens).
For more details, see below:
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 Tokens (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) in a payload, which is a JSON encoded as Base64. The payload can be decoded and read by the client.
With JWT, you can perform stateless authentication, that is, you won't need to persist JWT tokens if you don't need to track them. Just check the integrity of the token by verifying its signature on the server side.
Although, by persisting the tokens, you will have the possibility of invalidating and revoking the access of them. To keep the track of JWT tokens, instead of persisting the whole token, you could persist the token identifier (the jti claim) and some metadata (the user you issued the token for, the expiration date, etc) if you need. To find some great resources to work with JWT, have a look at http://jwt.io.
For tokens with cryptography, have a look at JSON Web Encryption (JWE), defined in the RFC 7516. Use JWE when you need confidentiality, so the client will need a key to decrypt the content of the token.