74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
|
use paseto::tokens::{validate_public_token, PasetoPublicKey};
|
||
|
use paseto::PasetoBuilder;
|
||
|
use ring::signature::Ed25519KeyPair;
|
||
|
use rocket::{
|
||
|
fairing::AdHoc,
|
||
|
http::Status,
|
||
|
request::{self, FromRequest, Request},
|
||
|
Outcome, State,
|
||
|
};
|
||
|
use rusty_ulid::generate_ulid_string;
|
||
|
use serde::{Deserialize, Serialize};
|
||
|
|
||
|
pub fn ed25519_keypair() -> AdHoc {
|
||
|
AdHoc::on_attach("ed25519 keypair for paseto", |rocket| {
|
||
|
let cfg = rocket.config();
|
||
|
let table = cfg.get_table("paseto").unwrap();
|
||
|
let private = table["private"].as_str().unwrap().to_string();
|
||
|
let private = hex::decode(&private).unwrap();
|
||
|
let public = table["public"].as_str().unwrap().to_string();
|
||
|
let public = hex::decode(&public).unwrap();
|
||
|
let kp = Ed25519KeyPair::from_seed_and_public_key(&private, &public).unwrap();
|
||
|
|
||
|
let token = PasetoBuilder::new()
|
||
|
.set_ed25519_key(kp)
|
||
|
.set_issued_at(None)
|
||
|
.set_issuer("manual API call".into())
|
||
|
.set_audience("wizards".into())
|
||
|
.set_jti(generate_ulid_string())
|
||
|
.set_subject("Within".into())
|
||
|
.build()
|
||
|
.unwrap();
|
||
|
debug!("token: {}", token);
|
||
|
|
||
|
Ok(rocket
|
||
|
.manage(Ed25519KeyPair::from_seed_and_public_key(&private, &public).unwrap())
|
||
|
.manage(PasetoPublicKey::ED25519KeyPair(
|
||
|
Ed25519KeyPair::from_seed_and_public_key(&private, &public).unwrap(),
|
||
|
)))
|
||
|
})
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Deserialize)]
|
||
|
pub struct Token {
|
||
|
pub jti: String,
|
||
|
pub sub: String,
|
||
|
pub aud: String,
|
||
|
}
|
||
|
|
||
|
impl<'a, 'r> FromRequest<'a, 'r> for Token {
|
||
|
type Error = ();
|
||
|
|
||
|
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
|
||
|
let keys: Vec<_> = request.headers().get("authorization").collect();
|
||
|
match keys.len() {
|
||
|
1 => {
|
||
|
let tok = keys[0];
|
||
|
let paseto_key = request.guard::<State<PasetoPublicKey>>().unwrap();
|
||
|
|
||
|
match validate_public_token(tok, None, &paseto_key) {
|
||
|
Ok(val) => {
|
||
|
let tok: Token = serde_json::from_value(val).unwrap();
|
||
|
Outcome::Success(tok)
|
||
|
}
|
||
|
Err(why) => {
|
||
|
error!("paseto error: {}", why);
|
||
|
Outcome::Failure((Status::Unauthorized, ()))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
_ => Outcome::Failure((Status::Unauthorized, ())),
|
||
|
}
|
||
|
}
|
||
|
}
|