pub struct BiscuitMiddleware { /* private fields */ }
Expand description
On incoming request if there is a valid bearer token authorization header:
- deserialize it using the provided public key
- inject a biscuit as extension in handler
else return an 401 Unauthorized (missing or invalid header) or 403 Forbidden (deserialization error) with an error message in the body
Example
use actix_web::{get, web, App, HttpResponse, HttpServer};
use biscuit_actix_middleware::BiscuitMiddleware;
use biscuit_auth::{macros::*, Biscuit, KeyPair};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let root = KeyPair::new();
let public_key = root.public();
HttpServer::new(move || {
App::new()
.wrap(BiscuitMiddleware::new(public_key))
.service(hello)
})
.bind(("127.0.0.1", 8080))?;
// this code is ran during tests so we can't start a long-running server
// uncomment the two lines below and remove the `Ok(())`.
//.run()
//.await
Ok(())
}
#[get("/hello")]
async fn hello(biscuit: web::ReqData<Biscuit>) -> HttpResponse {
println!("{}", biscuit.print());
let mut authorizer = authorizer!(
r#"
allow if role("admin");
"#
);
authorizer.add_token(&biscuit).unwrap();
if authorizer.authorize().is_err() {
return HttpResponse::Forbidden().finish();
}
HttpResponse::Ok().body("Hello admin!")
}
Implementations§
source§impl BiscuitMiddleware
impl BiscuitMiddleware
sourcepub fn new<KP>(public_key: KP) -> BiscuitMiddlewarewhere
KP: RootKeyProvider + 'static,
pub fn new<KP>(public_key: KP) -> BiscuitMiddlewarewhere KP: RootKeyProvider + 'static,
Instantiate a new middleware.
RootKeyProvider is a biscuit-auth trait used to delegate PublicKey selection/rotation implementation.
If either selection or rotation are not required, you can pass a PublicKey (it already implements RootKeyProvider in biscuit-auth lib).
Examples
Selection and rotation are not required
use biscuit_actix_middleware::BiscuitMiddleware;
use biscuit_auth::KeyPair;
BiscuitMiddleware::new(KeyPair::new().public());
Setup a simple KeyProvider that only accepts tokens with a root_key_id corresponding to an index of an existing PublicKey
use biscuit_auth::{error::Format, Biscuit, KeyPair, PublicKey, RootKeyProvider};
use biscuit_actix_middleware::BiscuitMiddleware;
struct KeyProvider {
roots: Vec<KeyPair>,
}
impl KeyProvider {
fn new() -> Self {
let mut new = KeyProvider { roots: vec![] };
for _ in 1..11 {
new.roots.push(KeyPair::new());
}
new
}
}
impl RootKeyProvider for KeyProvider {
fn choose(&self, key_id: Option<u32>) -> Result<PublicKey, Format> {
Ok(self
.roots
.get(key_id.ok_or(Format::UnknownPublicKey)? as usize)
.ok_or(Format::UnknownPublicKey)?
.public())
}
}
let key_provider = KeyProvider::new();
let middleware = BiscuitMiddleware::new(key_provider);
sourcepub fn error_handler(
self,
handler: fn(_: MiddlewareError, _: &ServiceRequest) -> HttpResponse
) -> Self
pub fn error_handler( self, handler: fn(_: MiddlewareError, _: &ServiceRequest) -> HttpResponse ) -> Self
Add a custom error handler to customize HttpResponse according to MiddlewareError and ServiceRequest params
Example
use biscuit_actix_middleware::{BiscuitMiddleware, error::*};
let root = KeyPair::new();
let public_key = root.public();
BiscuitMiddleware::new(public_key)
.error_handler(
|err: MiddlewareError, _: &ServiceRequest| -> HttpResponse {
AppError::BiscuitToken.error_response()
});
#[derive(Debug, Display)]
enum AppError {
BiscuitToken,
}
impl ResponseError for AppError {
fn error_response(&self) -> HttpResponse {
match self {
AppError::BiscuitToken => HttpResponse::Unauthorized().finish(),
}
}
}
use actix_web::{error::ResponseError, dev::ServiceRequest, HttpResponse};
use derive_more::Display;
use biscuit_auth::KeyPair;
sourcepub fn token_extractor(
self,
extractor: fn(_: &ServiceRequest) -> Option<Vec<u8>>
) -> Self
pub fn token_extractor( self, extractor: fn(_: &ServiceRequest) -> Option<Vec<u8>> ) -> Self
Add a custom token extractor to an existing middleware
Example
use biscuit_actix_middleware::BiscuitMiddleware;
use actix_web::{dev::ServiceRequest};
use biscuit_auth::KeyPair;
let root = KeyPair::new();
let public_key = root.public();
BiscuitMiddleware::new(public_key)
.token_extractor(|req: &ServiceRequest| {
Some(
req.headers()
.get("biscuit")?
.to_str()
.ok()?
.to_string()
.into_bytes(),
)
});
sourcepub fn default_token_extractor(req: &ServiceRequest) -> Option<Vec<u8>>
pub fn default_token_extractor(req: &ServiceRequest) -> Option<Vec<u8>>
Middleware default token extraction logic. It can be use as a base of a custom token extractor to add pre/post processing to token extraction.