JWTs
JSON Web Tokens (JWTs) are a common component of many auth systems. Each auth system will have a slightly different set of fields available in the JWT; however, there are a few common fields as well as a few standards that could be used by any implementation, particularly a custom auth system.
JWT extractor
To make it easier to use JWTs with Roadster, we provide an Axum JWT extractor to get the JWT from the Bearer Authorization header. By default the extractor will extract all claims to the IETF standard (plus any custom claims to a map), or a custom claim struct can be provided instead.
IETF claims
/// Example extracting the IETF [`ietf::Claims`] and a map of custom fields for the JWT.
async fn api_with_ietf_claims(jwt: Jwt) -> impl IntoResponse {
info!(subject=?jwt.claims.subject, user=?jwt.claims.custom.get("userId"), "Handling request");
}
struct CustomClaims {
user_id: Uuid,
}
/// Example extracting both the IETF [`ietf::Claims`] and the [`CustomClaims`] for the JWT.
async fn api_with_ietf_and_custom_claims(
jwt: Jwt<ietf::Claims<CustomClaims>>,
) -> impl IntoResponse {
info!(subject=?jwt.claims.subject, user=%jwt.claims.custom.user_id,
"Handling request",
);
}
/// Example using the [`CustomClaims`] as the only claims extracted for the JWT.
async fn api_with_custom_claims(jwt: Jwt<CustomClaims>) -> impl IntoResponse {
info!(user=%jwt.claims.user_id, "Handling request",);
}
OpenID claims
Along with the IETF claims, Roadster also provides a claims struct to extract OpenID standard claims.
/// Example extracting the OpenID [`Claims`] and a map of custom fields for the JWT.
async fn api_with_openid_claims(jwt: Jwt<openid::Claims>) -> impl IntoResponse {
info!(subject=?jwt.claims.subject, user=?jwt.claims.custom.get("userId"), "Handling request");
}
struct CustomClaims {
user_id: Uuid,
}
/// Example extracting both the OpenID [`Claims`] and the [`CustomClaims`] for the JWT.
async fn api_with_openid_and_custom_claims(
jwt: Jwt<openid::Claims<CustomClaims>>,
) -> impl IntoResponse {
info!(subject=?jwt.claims.subject, user=%jwt.claims.custom.user_id,
"Handling request",
);
}
JwtCsrf extractor
Some apps may want or need to support clients that don't have javascript available. In those cases, the app will typically set an auth cookie so it can be sent automatically by the client on every request. However, THIS MAY MAKE THE APPLICATION VULNERABLE TO CSRF ATTACKS.
Roadster provides a special
JwtCsrf
extractor that allows
extracting a JWT either from the cookies sent by the client or the Bearer Authorization header as normal. The extractor
contains a special field that indicates whether it's safe to use or if the server needs to apply some CSRF protections
before the token can be safely used. The token is considered safe if it was extracted from the Bearer Authorization
header, or if the request is an HTTP verb that does not modify resources (e.g. GET
). In any other case, e.g. the
JWT is extract from a cookie and the HTTP verb is a POST
, the server must apply a CSRF protection mechanism before
using the token. If the JwtCsrf
extractor is used for a route with a GET
verb, take care not to modify resources,
otherwise the application will still be vulnerable to CSRF attacks.
See the following for more information and recommendations for how to implement CSRF protection mechanisms:
- https://owasp.org/www-community/attacks/csrf
- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
If the functionality to extract from a cookie is not required, it’s recommended to use the normal
Jwt
extractor directly.