The GitkitDemo on GitHub says
Now use the idToken to create a session for your user. To do so, you
should exchange the idToken for either a Session Token or Cookie from
your server. Finally, save the Session Token or Cookie to maintain
your user's session.
In the sample code from the answer to the question Validating OAuth2 token obtained on Android device via Google Identity Toolkit (GitkitClient) on 3rd-party backend (custom python backend, non-gae)? the backend-server token verification of the token obtained through Android seems to be enough to ensure having a valid, secure token which can be added to the Android client headers during any follow-up communication with the backend.
So why is there a recommendation to you should exchange the idToken for either a Session Token or Cookie from your server?
Is this due to the size of the idToken (almost 1KB, IIRC)?
Which recommendations exist (the simplest and most secure way) to generate such a Session Token?
Are there any other arguments against using the idToken as a Session Token other than the size?
Can the Session Token be the first part ("token") of the idToken ( idToken.split(".")[0] in Python )? Or the payload (idToken.split(".")[1])? Or maybe creating a SHA1 of the idToken? EDIT: Ok, I realize that using the JTW header would be stupid, but the payload has at least a couple of variables (iat and exp and possibly as well the user_id), but the signature?
The token/cookie created by gitkit.js ("gtoken") is the idToken itself, should that one be replaced by a session token as well?
There are several reasons for the recommendation to use your own session token/cookie:
1) Most existing web server frameworks have their own session management mechanism (cookie generation with expiration time etc.). The common approach is to generate a random string as session id, and associate the server-side user activities with the session id. The server then instruct the browser to set a cookie of the session id. It is unnecessary, and sometimes very hard, to replace that mechanism.
2) As you mentioned, the IdToken is much larger than normal session cookies.
3) Currently the Google Identity Toolkit IdToken will expire after two weeks.
Other than these consideration, the IdToken is secure enough as the session token. Be sure -not- to use any sub-part of the IdToken as the session cookie, since attackers can easily create a fake one.
If your server issues its own session cookie, you should delete the gtoken after the user session terminates, so that the Sign In button state of the gitkit.js is kept sync'ed with your server.
Related
I'm implementing security for my React SPA using Spring Security on the backend. After a lot of reading, I opted for the following approach :
HTTPS everywhere
POST /login takes credentials returns JWT_TOKEN & XSRF_TOKEN in cookie form. I build the JWT_TOKEN myself whereas Spring Security handles the XSRF_TOKEN. Both cookies are Secured and SameSite=Strict. The JWT token is HttpOnly.
Subsequent API calls require the X-XSRF-TOKEN header. This is read from the aforementionned cookie. Both are sent and Spring Security compares them. JWT is automatically sent and checked in a Filter.
Every time a XSRF token is used, Spring Security generates a new one to prevent session-fixation attacks
XSS protections are applied by Spring Security
So now I'm wondering about refresh tokens. I'm reading a lot of contradictory info out there. Do I need them with this setup? If so how best to handle this ?
Many Thanks
In general, as its name says, the refresh token changes from one token to another. Typically they are used in OAuth protocol-based authentication. They are useful when an access token has expired, but the user's session is still valid.
First, JWTs are a great choice for access tokens. They have claims that match the access tokens requirements, such as: exp, iat, jti, sub, etc. But, when using a cookie-based authentication there is no need for access tokens and possibly no need for JWT.
As you said, your JWT_TOKEN is being set as an HttpOnly cookie, which means that only the server has access to it. JWT is useful for sharing the initial state between the client and server, and vice-versa. If your server is just taking it to look up the database, you don't need a JWT, you are just using a session concept, and keeping session data on a JWT may not be a good practice.
Second, if your authenticated cookie data will live at /login and die at /logout, there is no need for refresh tokens. Refresh tokens are an exchange key for short-life access tokens. Instead, your cookies keep the session live and don't need to be exchanged by something else.
For example, if the user uses the /login route to exchange your username and password for one short life access_token. He may need the refresh_token to get a new access_token without needing to send his username and password again.
If you are using the OAuth protocol or similar, refresh tokens are essential to provide a more seamless experience for your users and avoid the inconvenience of repeatedly having to re-enter their credentials. But even on OAuth, they are not mandatory.
I have implemented a spring boot application which does authentication and authorization using Spring OAuth2.
I am using JDBC token store to main the token issued to the client for performing Custom claim verification and some other user status verification during application run-time.
The question is, since i had used traditional JSESSIONID with CSRF token, i cannot find any advantage with the new OAuth standards because after login i would store the user details in the session and retrieve it whenever needed similarly for OAuth i store the User details in the JWT token itself and decode the token every time to get the user information, also i need to hit the database anyway for custom claim verification such as JTI verification .
Everyone says JWT is for stateless application but with JDBC token store i'm holding all the token that is issued to each client. Also there is an additional overhead to purge the expired token which will be done automatically with Session. Also i'm using refresh token as the way to implement session timeout.
Therefore can anyone explain me, when should i use JSESSIONID and when to use JWT ? My application is running on AWS architecture.
From my experience, cookie-based authentication sufficiently complicates scaling and load-balancing. If you have authenticated via the first service replica, your cookie will be not appliable to another replica, cause all sessions are stored in memory. So, if you want to scale your service in the future, session-based authentication can make things much more complex.
It has been a long road but I have SignalR working with my Web API which uses OWIN for token authentication.
I have a mechanism where if a user authenticates on terminal #1 and then later authenticates on terminal #2, I can send them a Javascript alert saying "Hey, only one session at a time. Which one do you want to log out?"
The question I have is how to kill their "session" on one of the terminals? I say "session", but since this is a REST based API there really is no session. If I could force them to re-authenticate on the terminal they choose to "log out" from that would be sufficient.
I have the SignalR connectionId of each client. Is there a way I can expire their authentication token and force a logout?
Note - The client is separate from the Web API in that they are hosted on two different servers. The client is just HTML/Javascript making calls to the Web API.
If you are using a bearer token approach, and you are not storing tokens (or token hashes) into some kind of persistent storage (e.g. a DB), then you have no way to invalidate a token.
Since OAuth is not an Authentication protocol, it do not have any kind of log out concept in it. Your only option is to remove the token from the client storage (I can imagine it is stored inside the localStorage or in a cookie).
Of course this does not really invalidate anything, and if the token is not deleted for some reason, it can still be used for authorization purposes.
Your only option, if you really need a single access token valid at a single time, is to store some information about it in a database, and check that storage every time you validate the token. You could, for instance, store the hash of the token (never store the real token for this reason, they have the same value of passwords once stored) with the username, but please note that this approach makes your authorization protocol a little less stateless than before.
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.
I understand that JWT are stateless tokens that store signed information about the client's claim and are passed to a server via the Authorization HTTP header.
My question is, why do we need JWT when we already have client sessions (https://github.com/mozilla/node-client-sessions)? Client sessions are conceptually the same. They're cookies that contained signed information which when verified means the cookie hasn't been tempered with. Also, client sessions are stored in a cookie and passed via the Cookie HTTP header. It's the same thing only using different words. Am I wrong?
So, why is JWT even around? I could understand that maybe the point is to standardize the way authentication tokens work, but we got along fine without a session ID based standard (each implementation did things their own way). Also, why would the JWT not use cookies as a means of transfer. With cookies, you wouldn't need explicitly send the correct header for every request (simplifying Ajax requests).
Am I missing something?
JWT tokens are signed JSON formatted documents that assert claims about a user (or any principal). If you trust the issuer of the token, you trust the claims in the token and can make authorization decisions based on this.
JWT tokens are often used for calling external Web APIs. These APIs do not necessarily live on the same domain as your website and therefore cannot use the same cookies as your site. JWT tokens are used in REST services as they do not need any session info stored on the server. Using JWT tokens is also not vulnarable to CSRF attacks.