When creating a web application there are different ways to handle authentication (e.g. signing in). My previous web applications used username / password but is it the best way to handle it?

The Drawbacks of Username / Password Combo

Using a username and password combination helps authenticate users (e.g. someone needs both the username and password to be able to log in). Strong passwords (e.g. NCSC’s Three Random Words) should be recommended to users, and a connection over HTTPS should be enforced, other the username / password may be sent in clear text or just Base64 encoded (encoding is not encryption!) in the authorization header using the Basic option.

If the web app is checking the password, or password hash, in each logged in request this can see multiple lookups to the backend database, creating a bottle neck at the database layer. If the password is compromised, then a new password needs to be created.

Bearer Tokens

Bearer Tokens can be used as an alternative to passwords. Bearer Tokens can be carried via the authorization header, using the Bearer <token> option, rather than the Basic option.

Bearer format types include the JSON Web Token (JWT).

Long lived bearer tokens can be problematic. If a token is compromised it can be revoked, killing all sessions using it.

JSON Web Token

So what makes a JWT a good alternative? JWTs are stateless (no database lookup needed for checking them!), can contain the users role, they have an expiration time, and they are cryptographically verified.

The JST is made up of:

header.payload.signiture

The header contains the algorithm used to sign the token and the token type, e.g:

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

This examples say that the HMAC SHA256 algorithm is to be used, and that the type is JWT. This header is then Base64 encoded.

The payload then has statements that the user is claiming. Note: Although this information is protected against tapering it is still readable. Do not put any secret, confidential or sensitive information in the payload or header of a JWT.

An example payload:

{
 "sub":"geektechstuff.com",
 "name":"Geek_Dude",
 "admin": true
}

The payload is then Base64 encoded.

Finally the signature takes the Base64 encoded header, Base64 encoded payload, and uses the algorithm specified in the header (with a secret) to sign the JWT.

HS256_Algorithm(Base64_Encoded_Header + Base64+Encoded+Payload + Secret)= JWT