use actix_web::{web, HttpResponse, Scope}; use chrono::{Duration, Utc}; use jsonwebtoken::{ decode, encode, errors::Error as JwtError, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation, }; use serde::{Deserialize, Serialize}; use crate::AppState; use crate::extractors::auth_token::AuthenticationToken; pub fn auth_scope() -> Scope { web::scope("/auth") .route("/encode-token/{id}", web::get().to(encode_token)) .route("/decode-token", web::post().to(decode_token)) .route("/protected", web::get().to(protected)) } #[derive(Serialize, Deserialize)] pub struct Claims { pub id: usize, pub exp: usize, } #[derive(Serialize, Deserialize)] struct Response { message: String, } #[derive(Serialize, Deserialize)] struct EncodeResponse { message: String, token: String, } #[derive(Serialize, Deserialize)] struct DecodeResponse { message: String, id: usize, } #[derive(Serialize, Deserialize)] struct DecodeBody { token: String, } async fn encode_token(path: web::Path, data: web::Data) -> HttpResponse { let id: usize = path.into_inner(); let exp: usize = (Utc::now() + Duration::days(365)).timestamp() as usize; let claims: Claims = Claims { id, exp }; let token: String = match encode( &Header::default(), &claims, &EncodingKey::from_secret(data.secret.as_str().as_ref()), ) { Ok(res) => res, Err(_) => return HttpResponse::Ok().body("Token encoding didn't work\n"), }; HttpResponse::Ok().json(EncodeResponse { message: "success".to_owned(), token: token.to_owned(), }) } async fn decode_token(body: web::Json, data: web::Data) -> HttpResponse { let decoded: Result, JwtError> = decode::( &body.token, &DecodingKey::from_secret(data.secret.as_str().as_ref()), &Validation::new(Algorithm::HS256), ); match decoded { Ok(token) => HttpResponse::Ok().json(DecodeResponse { message: "Authorized".to_string(), id: token.claims.id, }), Err(e) => HttpResponse::BadRequest().json(Response { message: e.to_string(), }), } } async fn protected(auth_token: AuthenticationToken) -> HttpResponse { println!("{:#?}", auth_token); HttpResponse::Ok().json(Response { message: "Authorized".to_owned() }) }