What I am trying to achieve
Let's say there is a web app that allows users to log in with Google.
The newest google identity services provide jwt tokens on successful Logins.
Instead of local or session storage, I decided I will be storing the jwt in client-side memory, and keep a refresh_token in a httpOnly secure cookie
Example:
After successful login, the web app will hit the backend /authenticate which will decode the jwt token, and it will keep add that to a map(refresh_token → jwt) and it will respond with that refresh_token
The web client will then save that refresh_token in a httpOnly cookie and it will instantiate a socket connection (using that refresh_token in the handshake)
the actual jwt remains in memory, and it is not prone to attacks
When a user refreshes the page, that refresh_token will be used to defer the current jwt token, or fetch a new jwt if expired.
The socket connection will always have a refresh_token in the handshake, which is mapped onto a valid jwt token that will be checked on each socket message
Question:
If an attacker manages to grab that refresh_token, they can request a new jwt token from my server, as if they were users, supposing they know there is an endpoint on my server for that... What is the benefit of storing the jwt in-memory and the refresh_token in a httpOnly cookie?
I understand that this makes the attack process more difficult than just storing the jwt in a httpOnly cookie, but at the end of the day the refresh_token is also useful, it's just useless to the outer world.
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.
Hi I don't know that I understand correct how it should work with refresh token.
I am creating spring boot backend with angular, and I want to implement JWT.
Currently I am working on backend.
access_token expire in 15 mins
refresh_token: expire date 7 days
When angular sends request with credentials, my spring boot generate jwt token and refresh token. Each refresh token, and access token have different secret(because if they have same secret, someone can access resources with refresh token)
If token expire, angular should access endpoint /refresh_token, on this endpoint send header "Authorization":"Bearer REFRESH_KEY_VALUE", and obtain both new refresh_token, and access_token
Make sure you follow the RFC more details about the same here:
https://datatracker.ietf.org/doc/html/rfc6749#page-10
And also look at the Security Threats and Mitigations here - https://datatracker.ietf.org/doc/html/rfc6750#section-5.1
What you're referring to is Token Disclosure
To protect against token disclosure, confidentiality protection MUST
be applied using TLS [RFC5246] with a ciphersuite that provides
confidentiality and integrity protection. This requires that the
communication interaction between the client and the authorization
server, as well as the interaction between the client and the
resource server, utilize confidentiality and integrity protection.
Since TLS is mandatory to implement and to use with this
specification, it is the preferred approach for preventing token disclosure via the communication channel. For those cases where the
client is prevented from observing the contents of the token, token
encryption MUST be applied in addition to the usage of TLS
protection. As a further defense against token disclosure, the
client MUST validate the TLS certificate chain when making requests
to protected resources, including checking the Certificate Revocation
List (CRL) [RFC5280].
I'm creating a React Js website with a Node.js backend. I've been attempting to figure out a user authentication implementation to prevent CSRF attacks however I'm really confused about where to store Anti-CSRF tokens.
My thought process of a secure implementation is as follows...
User submits request to login with credentials.
Credentials are authenticated.
Server creates session.
Server creates JWT to use as Anti-CSRF token.
Server stores JWT (Anti-CSRF token) in session storage.
Server sends response to client.
Response has header to store session ID in HttpOnly cookie on client-side.
Response payload includes JWT (Anti-CSRF token).
Client receives response.
HttpOnly cookie holding session ID is stored on client-side.
Client stores JWT (Anti-CSRF token) in localStorage.
I figure when a user needs to request information, the client can send the JWT (Anti-CSRF token) via a header or payload, and the session ID will be sent automatically due to it being a cookie. Then, the server can check if the JWT (Anti-CSRF token) exists in the session storage.
I know that the JWT (Anti-CSRF token) will need to be refreshed at some point.
My confusion is due to storing the JWT (Anti-CSRF token) on the client side. I keep reading that it should only be stored on the server. But if it's only stored on the server it doesn't seem to be doing anything at all.
I thought of using both cookies and localStorage because it seems that if a request to the server needs both a HttpOnly cookie and something from localStorage to send back an "authorized" response, an attacker would need to both successfully ride a session and successfully implement an XSS attack to get the Anti-CSRF token.
I just started learning about CSRF and XSS recently so I could be completely wrong and there could be a huge flaw in my implementation that I'm missing. But my main question is... don't Anti-CSRF tokens need to be stored on the client AND the server?
They are also called "CSRF Tokens". When a client requests for a form (e.g. bank login page), server generates the tokens and passes them to client and when the client fills the form, client passes CSRF token along with the completed form. Server verifies the token value and if it matches, request is fulfilled. CSRF tokens are stored on server-side in synchronizer token pattern.
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.
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.