wasmcloud/src/jwt.rs

61 lines
1.7 KiB
Rust

use crate::{models, schema, MainDatabase};
use color_eyre::eyre::{eyre, Result};
use diesel::prelude::*;
use hmac::{Hmac, NewMac};
use jwt::{SignWithKey, VerifyWithKey};
use lazy_static::lazy_static;
use sha2::Sha256;
use std::collections::BTreeMap;
use std::env;
lazy_static! {
pub static ref SECRET: String = env::var("JWT_SECRET")
.expect("JWT_SECRET to be populated")
.to_string();
}
#[instrument]
pub fn make(user_id: uuid::Uuid, token_id: uuid::Uuid) -> Result<String> {
let key: Hmac<Sha256> = Hmac::new_varkey(&*SECRET.as_bytes()).unwrap();
let mut claims = BTreeMap::new();
claims.insert("sub", user_id.to_string());
claims.insert("jti", token_id.to_string());
let token_str = claims.sign_with_key(&key)?;
tracing::debug!("token: {}", token_str);
Ok(token_str)
}
#[instrument(skip(token, conn))]
pub fn verify(token: String, conn: MainDatabase) -> Result<models::User> {
use schema::{tokens::dsl::tokens, users::dsl::users};
let key: Hmac<Sha256> = Hmac::new_varkey(&*SECRET.as_bytes()).unwrap();
let claims: BTreeMap<String, String> = token.verify_with_key(&key)?;
let uid = uuid::Uuid::parse_str(
&claims
.get("sub")
.ok_or(eyre!("can't get subscriber from JWT"))?,
)?;
let jti = claims
.get("jti")
.ok_or(eyre!("can't get token ID from JWT"))?;
let tok = tokens
.find(uuid::Uuid::parse_str(&jti)?)
.get_result::<models::Token>(&*conn)?;
if tok.deleted_at.is_some() {
return Err(eyre!("token was deleted at {}", tok.deleted_at.unwrap()));
}
if tok.user_id != uid {
return Err(eyre!("token and user mismatch"));
}
let user = users.find(uid).get_result::<models::User>(&*conn)?;
Ok(user)
}