Authentication

Thu, 11 Apr 2024 06:26:20 GMT

 Properties

Key Value
Identifier authentication
Name Authentication
Type Topic
Creation timestamp Thu, 11 Apr 2024 06:26:20 GMT
Modification timestamp Thu, 11 Apr 2024 09:14:54 GMT

Jason Web Tokens (JWTs)

  • JWTs consist of three parts separated by dots (.) Therefore, a JWT typically looks like the following: xxxxx.yyyyy.zzzzz
    • Header: in the header, we find claims about the token itself, like what algorithm was used for signing that token.
    • Payload: the payload (or the body) carries information about a given asset. In a login scenario, this would be information about the user.
    • Signature

The header and payload have claims, which are statements about an entity and all additional data that needs to be passed in a request.

The final part is the signature, and it helps you ensure that a given token wasn't tampered with because signing JWTs requires either a secret or a public/private key pair agreed on previously. The signature itself is based on the header and payload, in combination with a secret, or private/public key pair, depending on the algorithm.

Header

The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm such as HMAC SHA256 or RSA. For example:

{
  'alg': 'HS256',
  'typ': 'JWT'
}

Then, this JSON is Base64Url encoded to form the first part of the JWT.

Payload

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional metadata. There are three types of claims: reserved, public, and private claims.

  • Reserved claims: These are a set of predefined claims, which are not mandatory but recommended, thought to provide a set of useful, interoperable claims. Some of them are: iss (issuer), exp (expiration time), sub (subject), aud (audience), among others. Notice that the claim names are only three characters long as JWT is meant to be compact.
  • Public claims: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
  • Private claims: These are the custom claims created to share information between parties that agree on using them.

An example of payload could be:

{
  'sub': '1234567890',
  'name': 'John Doe',
  'admin': true
}

The payload is then Base64Url encoded to form the second part of the JWT.

Signature

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way.

HMACSHA256(
  base64UrlEncode(header) + '.' +
  base64UrlEncode(payload),
  secret)

The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message was't changed in the way.

Putting all together

The output is three Base64 strings separated by dots that can be easily passed in HTML and HTTP environments, while being more compact compared to XML-based standards such as SAML.

The following shows a JWT that has the previous header and payload encoded and it is signed with a secret.

In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required.

Whenever the user wants to access a protected route, it should send the JWT, typically in the Authorization header using the Bearer schema. Therefore the content of the header should look like the following:

Authorization: Bearer <token>

This is a stateless authentication mechanism as the user state is never saved in the server memory. The server's protected routes will check for a valid JWT in the Authorization header, and if there is, the user will be allowed. As JWTs are self-contained, all the necessary information is there, reducing the need of going back and forward to the database.

This allows to fully rely on data APIs that are stateless and even make requests to downstream services. It doesn't matter which domains are serving your APIs, as Cross-Origin Resource Sharing (CORS) won't be an issue as it doesn't use cookies.



Typical Flow

Here's how JWT typically works, including access tokens and refresh tokens:

  1. User Authentication: When a user logs in to a system (like a web application or an API), the server verifies the user's credentials (such as username and password). Upon successful authentication, the server generates a JWT.
  2. JWT Creation: The JWT consists of three parts: a header, a payload, and a signature, separated by periods. The header typically specifies the token type (JWT) and the hashing algorithm used to create the signature. The payload contains the claims, which are statements about the user and additional data. These claims can include user ID, username, roles, permissions, or any other relevant information. The signature is created by encoding the header, payload, and a secret key using the specified algorithm.
  3. Access Token: The server sends the JWT back to the client, usually as part of the authentication response. This JWT serves as the access token. The client then includes this token in subsequent requests to the server to access protected resources or endpoints.
  4. Token Verification: When the client sends a request to the server with the JWT included, the server verifies the token's authenticity and integrity. It does this by decoding the JWT, verifying the signature using the secret key, and checking the expiration time (if an expiration time is specified in the payload). If the signature is valid and the token hasn't expired, the server considers the request authenticated and processes it accordingly.
  5. Refresh Tokens: Access tokens typically have a relatively short lifespan for security reasons. To extend the user's authenticated session without requiring them to log in again, refresh tokens are used. A refresh token is a long-lived token that is issued alongside the access token during authentication. When the access token expires, the client can use the refresh token to obtain a new access token without needing the user's credentials again. This process involves sending the refresh token to the server, which verifies it and issues a new access token if the refresh token is valid.
  6. Token Revocation: To enhance security, systems may implement mechanisms for revoking tokens. For example, if a user logs out or their account is compromised, the server can invalidate the associated tokens. This prevents unauthorized access even if a valid token is presented.

The Signature

The signature part of a JWT is crucial for ensuring the integrity and authenticity of the token. It's the mechanism used to verify that the token hasn't been tampered with and was indeed issued by a trusted party.

Here's how the signature part works in JWT:

  1. Header and Payload: Before discussing the signature, it's essential to understand the structure of a JWT. A JWT consists of three parts: header, payload, and signature. The header typically includes metadata about the token, such as the type of token (JWT) and the hashing algorithm used to create the signature. The payload contains the claims, which are statements about the user and additional data.
  2. Signing Process: To create the signature, the header and payload are first encoded using a specified encoding algorithm, typically Base64 URL encoding. Then, these encoded strings are concatenated with a period ('.') to form what's known as the "signature input."
  3. Secret Key: The signature is created by taking the signature input and hashing it using a cryptographic hashing algorithm, such as HMAC (Hash-based Message Authentication Code) or RSA (Rivest-Shamir-Adleman). This hashing process involves using a secret key that is known only to the server that issued the token. The secret key ensures that only the server with the correct key can generate or verify the signature.
  4. Verification: When a JWT is received by a party (typically a server), it extracts the header and payload, decodes them, and re-creates the signature input. Then, using the same hashing algorithm and the secret key, it generates a new signature. If the newly generated signature matches the signature contained in the JWT, it indicates that the token has not been tampered with and can be trusted.
  5. Ensuring Integrity: The signature ensures the integrity of the JWT because any modifications to the header or payload would result in a different signature when verified. This prevents attackers from tampering with the token's contents without being detected.
  6. Authenticity: By using a secret key known only to the issuer, the signature also provides a means to verify the authenticity of the token. Only parties with access to the correct secret key can generate valid signatures, ensuring that the token was indeed issued by a trusted source.

Overall, the signature part of JWTs plays a critical role in maintaining the security and trustworthiness of the tokens, enabling secure transmission of information between parties in a distributed system.

Refresh Tokens

Refresh tokens typically don't follow the same structure as JWT access tokens. While JWT access tokens consist of three parts (header, payload, and signature), refresh tokens often have a different format.

Refresh tokens are long-lived tokens that are used to obtain new access tokens after the original access token expires. They are typically opaque tokens, meaning their contents are not meant to be deciphered or manipulated by clients. Instead, they serve as identifiers or tokens of proof that the bearer has been previously authenticated and authorized to access certain resources.

The structure of a refresh token can vary depending on the implementation and the system's requirements, but it generally includes:

  1. Token Identifier (ID): A unique identifier that allows the server to look up the corresponding refresh token in its database.
  2. Expiration Time: An expiration timestamp indicating until when the refresh token is valid. This helps mitigate the risk associated with long-lived tokens.
  3. Additional Metadata (Optional): Some systems may include additional metadata in the refresh token, such as the user's identity or scope of access. However, sensitive information is usually kept on the server side, and the refresh token itself is kept opaque to the client.

Refresh tokens are typically stored securely on the client side and exchanged with the server in a secure manner (e.g., over HTTPS). When a client presents a refresh token to the server, the server validates it and, if valid, issues a new access token to the client. This process allows the client to maintain an authenticated session without requiring the user to log in again.

In summary, refresh tokens serve a different purpose than JWT access tokens and often have a simpler structure, focusing primarily on identifying and authorizing the client to obtain new access tokens.

Back to top

 Context