I am building a real world application where users will access the app primarily from Android, iOS devices as well as Desktops.
From my elementary research, I have realized that token based authentication mechanism is more better and elegant for client-server models as compared to session based authentication.
In Django, I have found two popular ways to do this -
http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication
http://getblimp.github.io/django-rest-framework-jwt/
From what I understood, option 2] is an extension of 1] except that the Token is in the form of JSON(serialized). I would like to understand what other differences there are between option 1] and 2] and the advantages/disadvantages of choosing either.
They both carrying out similar tasks with few differences.
Token
DRF's builtin Token Authentication
One Token for all sessions
No time stamp on the token
DRF JWT Token Authentication
One Token per session
Expiry timestamp on each token
Database access
DRF's builtin Token Authentication
Database access to fetch the user associated with the token
Verify user's status
Authenticate the user
DRF JWT Token Authentication
Decode token (get payload)
Verify token timestamp (expiry)
Database access to fetch user associated with the id in the payload
Verify user's status
Authenticate the user
Pros
DRF's builtin Token Authentication
Allows forced-logout by replacing the token in the database (ex: password change)
DRF JWT Token Authentication
Token with an expiration time
No database hit unless the token is valid
Cons
DRF's builtin Token Authentication
Database hit on all requests
Single token for all sessions
DRF JWT Token Authentication
Unable to recall the token without tracking it in the database
Once the token is issued, anyone with the token can make requests
Specs are open to interpretations, no consensus on how to do refresh
Related
Am trying to access forge api endpoint using 2- legged authentication token, but at certain point of time my token becomes invalid or expired. Is that any option to refresh/ increase token expire time in 2- legged authentication process?
For 2-legged token, once they expire, you have no choice but to request another one. That being said, I think this will be managed for you if you use one of the forge/design-automation sdk.
I am calling the app script execution API from my web app. I am getting ScriptApp.getOauthToken() and storing it inside sheet. When I open my web app I will get the stored access token and calling the execution API with the help of it.
But the problem is, after some time the token is getting expired and it is saying
authorization is required
when I call execution API.
Is there any way to keep access token alive or refreshing it whenever is needed?
I. You cannot and you should not. At least not natively
There is no native Google Apps Script service method for obtaining and exchanging a refresh token (and you would need one if you want to refresh an expired OAuth 2.0 token) for a bearer token. That said, there is no practical reason in storing the short-lived token obtained via getOauthToken method - if a user authorized your application, you can request a token on the fly each time you need to make a request.
II. If you still want to, use a library
There is an officially endorsed library for Google Apps Script that manages OAuth 2.0 flow for you. When using it, you can obtain a refresh token if you set the offline access to true when issuing the token.
III. If you really want to DIY, you can always make your own flow
It is possible to perform a complete Oauth 2.0 flow (both with and without user interaction) by using only the native tools by building a custom JWT token and exchanging it with Google Identity Platform endpoints. But that means you will have to manage everything:
Build JWT custom token headers and payload, then base64 urlencode them and sign with an appropriate signature and concatenate into a token.
Exchange the custom JWT for a short-lived bearer token, validate it and extract expiration time, then persist the token.
Each time you get the token from storage, check for the expiration time, and reissue the token again using the procedure in point 1 - 2.
Handle token revocation (note that you will not be able to invalidate it from Google's servers, only in your application).
And many more caveats along the way.
Note that the token cannot be "kept alive", it goes against the idea behind the OAuth protocol - the lesser the lifespan of an individual token, the better the security of your application.
It looks like CAS can issue JWT Token after login:
https://apereo.github.io/cas/5.1.x/installation/Configure-ServiceTicket-JWT.html
I have two questions about this functionality:
It is possible to configure live time (expiration) for JWT Tokens ?
It is possible to refresh such tokens on backend (using refresh token)?
The expiration time of the generated JWT is controlled by the length of the assertion returned as part of the validation event. If the assertion validity length is not specified, then the expiration time is controlled by the length of the SSO session defined as part of SSO expiration policy of the CAS server.
Not OpenID Connect
Remember that you are just receiving a ticket in form of a JWT, thereby removing the need from your client to validate a normal service ticket. The ticket is internally validated by CAS and you as the client are only left in charge of validating the JWT itself. Do not confuse this with OpenID Connect. While a JWT, the token itself is not an ID token, cannot be refreshed and must be obtained again once you deem it expired. If you need more, consider using the OpenID Connect protocol instead.
Is it ok to store user credentials (username / password) in the JWT (so sign it and verify the resulted token later)?
I heard that
No, it is not secure to send a password in a JWT. This is because the
JWT claims are simply encoded and can easily be decoded by anyone that
sees them. It is not secure to store any sensitive information in a
JWT that returned to a user
but I don't know why does the JWT website recommends using it for authentication purposes then:
When should you use JSON Web Tokens?
Here are some scenarios where JSON Web Tokens are useful:
Authentication: This is the most common scenario for using JWT. Once
the user is logged in, each subsequent request will include the JWT,
allowing the user to access routes, services, and resources that are
permitted with that token. Single Sign On is a feature that widely
uses JWT nowadays, because of its small overhead and its ability to be
easily used across different domains
The JWT is the result of the authentication. For example
User sends his credentials (e.g. username/password) to an authentication service. It could be a third party one or one inside your monolith or your own microservices dedicated to authentication.
The service validates username-password. If authentication success it returns an JWT that represents that the user is already authenticated, in other words he is who claim he is. This JWT could contain a payload without sensitive information (don't store the password here).
The user sends another request to a service business with the JWT. If the JWT isn't expired and is not corrupted (the sign is still valid) then the service could trust in its JWT. Maybe this task will be delegated to an authorization service.
What is inside the JWT token?
Well, the simplest JWT contains information about the sign (I can't enter in much detail here because I'm not a security expert) that allows to check if the sign has been corrupted when a request with the JWT is received.
This information can be verified and trusted because it is digitally signed
Besides that, the JWT allows to send a payload.
More formally, the JWT is composed by:
Header: type of the token + hashing algorithm being used
Payload: Claims are statements about an entity (typically, the user) and additional metadata.
Signature: The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
For example, if I send a request to a authentication service with my credentials username:password being gabriel:giussi, it will check these credentials and if they're OK it could create the following JWT:
Then with every request I will then the encoded JWT that contains my username and the service will
Perform authorization (What Gabriel is authorized to do?) if the JWT sign is valid.
Ask me to login again if the JWT has expired
Return an authentication error if the sign is broken.
Shortly: yes, it is OK to pass/receive sensitive data in JWT if you encrypt the data before placing into JWT's payload and decrypt it after the JWT validation to use it.
In a general case you would not need to keep user credentials in the JWT because the JWT is by itself a dynamically generated credential that represents the login / password (or the other means of authentication) provided at the JWT's first generation time.
1.1 You could however pass something that is not as sensitive as pure login / password but still bears the valuable information you need at the JWT validation time. It can be user ID (in a sub claim, hashed if desired), or access level code or the like.
Nevertheless if you wish you can pass the sensitive information with JWT. And this is all pretty easy as per below.
2.1 For sensitive data you could use your specific private claims in the JWT's payload, e.g.:
{
// These are registered claims: (see https://www.rfc-editor.org/rfc/rfc7519#section-4.1)
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
// There can be some public claims you are not afraid to expose to the world
// these are omitted here for brevity (see https://www.rfc-editor.org/rfc/rfc7519#section-4.2).
"omitted": "for brevity",
// And here can go some private claims you wish to include in the payload, e.g.:
"sensitiveInfo": {
"username": "admin",
"password": "12345",
"account_balance": 10000,
"etc": "something else"
}
}
2.2 The sensitiveInfo payload key by default is only base64-encoded (so it is easily read by anyone who gets the JWT). To make it secure you can encrypt it with some external module (e.g. crypto or bcrypt on NodeJS or PHP's techniques of your choice).
2.3 In this case:
At the JWT generation step you have to encrypt the key's data before you provide the entire payload to JWT generator.
At the JWT validation step, after the JWT successfully passes the standard validation (e.g. jsonwebtocken jwt.verify() in Node) you get the decoded payload with encrypted data in sensitiveInfo key. You now just have to decrypt the data and use it as you planned.
This is it.
You should use jwt only to store a token which your API will consume. The token will be generated after a successful login and it can be attached to any request sent to your API and all request should be proceeded only if the token is valid.
I am using oauth2.0 to get service token from CAS server. When trying to validate token using
/cas/serviceValidate url getting response
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>JJuH5FMVz6Lsq+4xwIpe39iCZx0=</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
where user is in encrypted format. I know that may user/pass is admin/admin. How can we identify user or encryption technique used.
Thanks,