2023-01-08 13:45:21 +01:00
# jwt-authorizer
2023-04-17 21:23:39 +02:00
JWT authoriser Layer for Axum and Tonic.
2023-01-08 13:45:21 +01:00
2023-01-25 08:38:09 +01:00
## Features
- JWT token verification (Bearer)
2023-02-26 20:30:55 +01:00
- Algoritms: ECDSA, RSA, EdDSA, HMAC
2023-01-25 08:38:09 +01:00
- JWKS endpoint support
- Configurable refresh
2023-02-01 22:10:18 +01:00
- OpenId Connect Discovery
2023-02-26 20:30:55 +01:00
- Validation
- exp, nbf, iss, aud
2023-01-25 08:38:09 +01:00
- Claims extraction
- Claims checker
2023-02-26 20:30:55 +01:00
- Tracing support (error logging)
2023-08-14 08:04:53 +02:00
- *tonic* support
- multiple authorizers
2023-01-25 08:38:09 +01:00
## Usage Example
2023-01-08 13:45:21 +01:00
```rust
2023-08-14 11:26:49 +02:00
# use jwt_authorizer::{AuthError, Authorizer, JwtAuthorizer, JwtClaims, RegisteredClaims, IntoLayer};
2023-02-01 22:08:28 +01:00
# use axum::{routing::get, Router};
# use serde::Deserialize;
2023-01-08 13:45:21 +01:00
2023-02-01 22:08:28 +01:00
# async {
2023-01-08 13:45:21 +01:00
// let's create an authorizer builder from a JWKS Endpoint
2023-05-18 17:02:28 +02:00
// (a serializable struct can be used to represent jwt claims, JwtAuthorizer< RegisteredClaims > is the default)
2023-08-14 11:26:49 +02:00
let auth: Authorizer =
JwtAuthorizer::from_jwks_url("http://localhost:3000/oidc/jwks").build().await.unwrap();
2023-01-08 13:45:21 +01:00
// adding the authorization layer
let app = Router::new().route("/protected", get(protected))
2023-08-14 11:26:49 +02:00
.layer(auth.into_layer());
2023-01-08 13:45:21 +01:00
2023-02-01 22:10:18 +01:00
// proteced handler with user injection (mapping some jwt claims)
2023-05-18 17:02:28 +02:00
async fn protected(JwtClaims(user): JwtClaims< RegisteredClaims > ) -> Result< String , AuthError > {
2023-01-08 13:45:21 +01:00
// Send the protected data to the user
2023-05-18 17:02:28 +02:00
Ok(format!("Welcome: {:?}", user.sub))
2023-01-08 13:45:21 +01:00
}
axum::Server::bind(& "0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service()).await.expect("server failed");
2023-02-01 22:08:28 +01:00
# };
2023-01-21 08:34:11 +01:00
```
2023-08-23 08:16:55 +02:00
## Multiple Authorizers
A layer can be built using multiple authorizers (`IntoLayer` is implemented for `[Authorizer<C>; N]` and for `Vec<Authorizer<C>>` ).
The authorizers are sequentially applied until one of them validates the token. If no authorizer validates it the request is rejected.
2023-02-26 20:30:55 +01:00
## Validation
Validation configuration object.
If no validation configuration is provided default values will be applyed.
docs: [`jwt-authorizer::Validation` ]
```rust
# use jwt_authorizer::{JwtAuthorizer, Validation};
# use serde_json::Value;
let validation = Validation::new()
.iss(& ["https://issuer1", "https://issuer2"])
.aud(& ["audience1"])
.nbf(true)
.leeway(20);
let jwt_auth: JwtAuthorizer< Value > = JwtAuthorizer::from_oidc("https://accounts.google.com")
.validation(validation);
```
2023-01-21 08:34:11 +01:00
## ClaimsChecker
2023-02-01 22:10:18 +01:00
A check function (mapping deserialized claims to boolean) can be added to the authorizer.
2023-01-21 08:34:11 +01:00
A check failure results in a 403 (WWW-Authenticate: Bearer error="insufficient_scope") error.
Example:
```rust
use jwt_authorizer::{JwtAuthorizer};
use serde::Deserialize;
// Authorized entity, struct deserializable from JWT claims
#[derive(Debug, Deserialize, Clone)]
struct User {
sub: String,
}
2023-01-23 23:36:29 +01:00
let authorizer = JwtAuthorizer::from_rsa_pem("../config/jwtRS256.key.pub")
2023-01-25 08:38:09 +01:00
.check(
2023-01-21 08:34:11 +01:00
|claims: & User| claims.sub.contains('@') // must be an email
);
```
2023-01-25 08:38:09 +01:00
## JWKS Refresh
2023-02-01 22:10:18 +01:00
By default the jwks keys are reloaded when a request token is signed with a key (`kid` jwt header) that is not present in the store (a minimal intervale between 2 reloads is 10s by default, can be configured).
2023-01-25 08:38:09 +01:00
2023-03-02 07:43:26 +01:00
- [`JwtAuthorizer::no_refresh()` ] configures one and unique reload of jwks keys
- [`JwtAuthorizer::refresh(refresh_configuration)` ] allows to define a finer configuration for jwks refreshing, for more details see the documentation of `Refresh` struct.
[`jwt-authorizer::Validation` ]: https://docs.rs/jwt-authorizer/latest/jwt_authorizer/validation/struct.Validation.html
[`JwtAuthorizer::no_refresh()` ]: https://docs.rs/jwt-authorizer/latest/jwt_authorizer/layer/struct.JwtAuthorizer.html#method .no_refresh
[`JwtAuthorizer::refresh(refresh_configuration)` ]: https://docs.rs/jwt-authorizer/latest/jwt_authorizer/layer/struct.JwtAuthorizer.html#method .refresh