Skip to main content

arc_auth_jwt/
lib.rs

1use actix_web::{post, web, HttpResponse};
2use arc_auth_core::IdentityStore;
3use arc_core::session::{SessionRecord, SessionStore};
4use arc_web::{ArcAppBuilder, ArcPlugin};
5use serde::Deserialize;
6
7pub use arc_web::http::middlewares::jwt_middleware::JwtMiddleware as RequireJwt;
8
9#[derive(Deserialize)]
10struct SignIn {
11    email: String,
12    password: String,
13}
14#[post("/api/session")]
15async fn signin(
16    body: web::Json<SignIn>,
17    identities: web::Data<dyn IdentityStore>,
18    sessions: web::Data<dyn SessionStore>,
19) -> HttpResponse {
20    let user = match identities.authenticate(&body.email, &body.password).await {
21        Ok(user) => user,
22        Err(_) => {
23            return HttpResponse::Unauthorized()
24                .json(serde_json::json!({"error":"invalid credentials"}))
25        }
26    };
27    let (token, jti) = match arc_web::helpers::jwt::create_token(&user.id) {
28        Ok(pair) => pair,
29        Err(_) => return HttpResponse::InternalServerError().finish(),
30    };
31    let now = std::time::SystemTime::now()
32        .duration_since(std::time::UNIX_EPOCH)
33        .unwrap_or_default()
34        .as_micros() as i64;
35    let expires = now + (arc_web::helpers::jwt::get_jwt_expiry() as i64 * 3_600_000_000);
36    if sessions
37        .record_session(SessionRecord {
38            jti,
39            actor_id: user.id,
40            created_at_us: now,
41            expires_at_us: expires,
42            revoked_at_us: None,
43        })
44        .await
45        .is_err()
46    {
47        return HttpResponse::ServiceUnavailable().finish();
48    }
49    HttpResponse::Ok().json(serde_json::json!({"token":token,"token_type":"Bearer"}))
50}
51fn routes(cfg: &mut web::ServiceConfig) {
52    cfg.service(signin);
53}
54pub struct JwtAuthPlugin;
55#[async_trait::async_trait]
56impl ArcPlugin for JwtAuthPlugin {
57    fn name(&self) -> &'static str {
58        "auth-jwt"
59    }
60    fn register(&self, builder: ArcAppBuilder) -> ArcAppBuilder {
61        builder.register_routes(routes)
62    }
63}