I'm developing an SPA with REST back end and want to have simple token based authentication. The goal for REST backed is to be stateless. I will explain the security model and try to reference all sources for decisions that were made during design. Would want a comment about the whole setup and answer to some specific questions.
Abstract
Authentication will be done on a dedicated endpoint (for example /auth/login). Login information will be passed as a JSON object. Information will contain username and password. Upon successful login, a signed JWT token will be issued. This token will be used for subsequent access to REST API.
Application will use HTTPS and I control all of the subdomains.
Specifics
JWT
- Contains username, issued at and expiration time
- Contains claims about role membership inside an application
- Contains a CSRF token (randomly generated from a cryptographically secure pseudorandom generator)
- Signed with a HMAC (SHA256) key only available to the server
Expiration
A token will be issued with a short expiration time (for example 30 minutes). An updated token with new expiration will be issued at every request (sliding window expiration) with a deadline of something reasonable (for example 8 hours). The process flow will be as follows:
- Initial login request will issue a token with expiration of 30 minutes
Next request will check if the token has expired. If it is expired, access will be blocked. If not, a request will be fulfilled. A check will be done at that point about the age of the token.
- If the age is within the deadline (less than 8 hours old), updated token will be generated containing new expiration time for another 30 minutes. Issued at time will remain the same as in original token.
- If the age of the token is pass deadline, no updated tokens will be generated and user will need to login again.
Rationale: I want to protect a token with a short expiration time in case it is compromised. I also don't want to force the user to relogin often. An attacker would need to request a new token in a timeframe less than expiration time of a token. In case an attacker manages to do that, maximum amount of time he/she can use the token is defined by the deadline. User is able to stay online for a period of set deadline. For a business application a deadline of 8 hours or a day is sufficient. Is this implementation safe enough? What are possible drawbacks and vulnerabilities?
JWT transport and storage
JWT will be transported as httpOnly cookie to the client and will be stored in Cookies repository on the browser.
Rationale: To protect a token from XSS attack which would compromise the token if held inside localStorage/sessionStorage. This is per a recommendation from this article. Anything wrong with this approach other than opening the implementation to a CSRF attack?
CSRF protection
Storing JWT tokens inside cookies will open the implementation to a CSRF attack. To mitigate this problem, a double submit cookie method is implemented. CSRF token is generated and included inside JWT token. This token is also supplied to the client application in a JSON object of a response to the login request. Application will store CSRF in localStorage and submit it with every request inside a custom header.
Rationale: As per an answer to this question referencing this paper, for an effective CSRF protection it is necessary to cryptographically tie the CSRF token with a session identification/authentication cookie. If I include a token inside a JWT, is it considered cryptographically tied to a security session?
Conceptually, do you see anything wrong with this implementation?