Authentication and Authorization
In this section, we will discuss authentication and authorization. For user authentication, we will use a simple authentication scheme with email and password, which will return a token using the JWT (JSON Web Token) standard. The JWT is a JSON signed in Base64 format. Generate the JWT from the laboratory project swagger on the login route with user "admin@default.com" and password "default" to see how it looks.
You can visit jwt.io to decode it and you will see that the JWT has 3 parts in Base64 format separated by ".":
- Header - this describes what type it is, it will always be "JWT" and the signing algorithm used.
- Payload - this contains the useful information from the JWT called claims, which will be used for user identification and authorization.
- Signature - the JWT is signed with a key known only to the server; a hash is generated from the header and payload first, and then the hash is encrypted. The signature ensures that the JWT cannot be altered or forged by someone without the signing key.
An example of a JWT could be the following:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI2MTczNjJlMC1iZTlhLTQzOWItOGJiMy02OTlhYzBjNjA3NzMiLCJuYW1lIjoiQWRtaW4iLCJlbWFpbCI6ImFkbWluQGRlZmF1bHQuY29tIiwibmJmIjoxNzA0NjQ5OTI5LCJleHAiOjE3MDUyNTQ3MjksImlhdCI6MTcwNDY0OTkyOSwiaXNzIjoiaHR0cHM6Ly9teS5hcHAiLCJhdWQiOiJodHRwczovL215LmFwcCJ9.TLcWuBxVLIVCta9J0x1Sx8Zi9R26c0OPQdLuKzbuqvE
With header:
{
"alg": "HS256",
"typ": "JWT"
}
And payload:
{
"nameid": "617362e0-be9a-439b-8bb3-699ac0c60773",
"name": "Admin",
"email": "admin@default.com",
"nbf": 1704649929,
"exp": 1705254729,
"iat": 1704649929,
"iss": "https://my.app",
"aud": "https://my.app"
}
To use the JWT, it must be included in HTTP requests in the Authorization header with the bearer token scheme, in the format "Bearer <jwt>". From the swagger, you can set the token as "Bearer <jwt>" using the "Authorize" button. To protect different routes in controllers, you can place the [Authorize] attribute on the route or on the entire controller. The code in the laboratory is already configured to work with this authorization; you just need to use that attribute where needed.
You should know that JWT does not have to dictate the authorization; it only needs to be valid and identify the user. From the JWT payload, claims can be extracted, the standard ones being:
- sub/nameid (subject/name identifier) - usually identifies the holder of the JWT for whom it was issued, it can be an ID like a number or GUID or a username.
- iat (issued at) - the timestamp of when the JWT was issued.
- exp (expires at) - the timestamp of when the JWT will expire, it can be omitted but a JWT that does not expire is useless and a security breach.
- iss (issuer) - the authority that issued the JWT, usually the domain name of the identity provider.
- aud (audience) - the target audience for which the JWT is issued, usually the domain name of the client application.
In addition to standard claims, any other fields can be added to the payload, but sub/nameid are sufficient to identify the user in the database with their rights. In the laboratory code, there is code with comments to help you extract claims and implement customized user access rights. Use the JWT to identify the user and implement your own custom authorization logic where needed.
Do not rely solely on the information in the JWT; it should not guide authorization. If you include too much information in the JWT and rely heavily on it, you may have situations where you have outdated information in the JWT compared to the database, while it is still valid. These situations can pose serious issues for the integrity and security of the system.