2020-11-03 19:55:03 +00:00
|
|
|
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);
|
|
|
|
|
2020-11-04 12:09:41 +00:00
|
|
|
Ok(rocket.manage(PasetoPublicKey::ED25519KeyPair(
|
|
|
|
Ed25519KeyPair::from_seed_and_public_key(&private, &public).unwrap(),
|
|
|
|
)))
|
2020-11-03 19:55:03 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-11-04 12:09:41 +00:00
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
2020-11-03 19:55:03 +00:00
|
|
|
pub struct Token {
|
|
|
|
pub jti: String,
|
|
|
|
pub sub: String,
|
|
|
|
pub aud: String,
|
2020-11-04 12:09:41 +00:00
|
|
|
pub iss: String,
|
2020-11-03 19:55:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2020-11-04 12:09:41 +00:00
|
|
|
info!(id = &tok.jti[..], "token used");
|
2020-11-03 19:55:03 +00:00
|
|
|
Outcome::Success(tok)
|
|
|
|
}
|
|
|
|
Err(why) => {
|
|
|
|
error!("paseto error: {}", why);
|
|
|
|
Outcome::Failure((Status::Unauthorized, ()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Outcome::Failure((Status::Unauthorized, ())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|