diff options
author | Toby Vincent <tobyv@tobyvin.dev> | 2024-04-06 02:09:26 -0500 |
---|---|---|
committer | Toby Vincent <tobyv@tobyvin.dev> | 2024-04-06 02:10:32 -0500 |
commit | 9822bc18bb0cb5e13104376ecefc6ec99d93b016 (patch) | |
tree | 0137399c270a69a2c09e7c0e4c41f64cad5dbbfe /src/routes/login.rs | |
parent | f7dd456941dbc5f926a04935d3aaaa198741608e (diff) |
feat: impl jwt auth middleware and user route
Diffstat (limited to 'src/routes/login.rs')
-rw-r--r-- | src/routes/login.rs | 80 |
1 files changed, 14 insertions, 66 deletions
diff --git a/src/routes/login.rs b/src/routes/login.rs index a580873..67f8422 100644 --- a/src/routes/login.rs +++ b/src/routes/login.rs @@ -1,17 +1,14 @@ use std::sync::Arc; use argon2::{Argon2, PasswordHash, PasswordVerifier}; -use axum::{extract::State, http::header::SET_COOKIE, response::IntoResponse, Json}; -use axum_extra::{ - extract::cookie::{Cookie, SameSite}, - routing::TypedPath, -}; -use jsonwebtoken::{EncodingKey, Header}; +use axum::{extract::State, response::IntoResponse, Json}; +use axum_extra::{headers::Authorization, routing::TypedPath, TypedHeader}; use serde::Deserialize; -use serde_json::json; use crate::{ - model::{LoginSchema, TokenClaims, User}, + error::AuthError, + jwt::Claims, + model::{LoginSchema, UserSchema}, state::AppState, Error, }; @@ -27,42 +24,27 @@ impl Login { State(state): State<Arc<AppState>>, Json(LoginSchema { email, password }): Json<LoginSchema>, ) -> Result<impl IntoResponse, Error> { - let User { + let UserSchema { uuid, password_hash, .. } = sqlx::query_as!( - User, + UserSchema, "SELECT * FROM users WHERE email = $1", email.to_ascii_lowercase() ) .fetch_optional(&state.pool) .await? - .ok_or(Error::LoginInvalid)?; + .ok_or(AuthError::LoginInvalid)?; Argon2::default() .verify_password(password.as_bytes(), &PasswordHash::new(&password_hash)?)?; - let token = jsonwebtoken::encode( - &Header::default(), - &TokenClaims::new(uuid, state.jwt_max_age), - &EncodingKey::from_secret(state.jwt_secret.as_ref()), - )?; - - let cookie = Cookie::build(("token", token.to_owned())) - .path("/") - .max_age(state.jwt_max_age) - .same_site(SameSite::Lax) - .http_only(true) - .build(); - - let mut response = Json(token).into_response(); + let token = Claims::new(uuid, state.jwt_max_age).encode(state.jwt_secret.as_ref())?; - response - .headers_mut() - .insert(SET_COOKIE, cookie.to_string().parse()?); - - Ok(response) + Authorization::bearer(&token) + .map(TypedHeader) + .map_err(Into::into) } } @@ -72,21 +54,8 @@ pub struct Logout; impl Logout { #[tracing::instrument] - pub async fn get(self) -> Result<impl IntoResponse, Error> { - let cookie = Cookie::build(("token", "")) - .path("/") - .max_age(time::Duration::hours(-1)) - .same_site(SameSite::Lax) - .http_only(true) - .build(); - - let mut response = Json(json!({"status": "success"})).into_response(); - - response - .headers_mut() - .insert(SET_COOKIE, cookie.to_string().parse()?); - - Ok(response) + pub async fn get(self) -> impl IntoResponse { + todo!("Invalidate jwt somehow..."); } } @@ -161,25 +130,4 @@ mod tests { Ok(()) } - - #[sqlx::test] - async fn test_logout(pool: PgPool) -> TestResult { - let state = Arc::new(AppState { - pool, - jwt_secret: JWT_SECRET.to_string(), - jwt_max_age: JWT_MAX_AGE, - }); - let router = init_router(state.clone()); - - let request = Request::builder() - .uri("/api/logout") - .method("GET") - .body(Body::empty())?; - - let response = router.oneshot(request).await?; - - assert_eq!(StatusCode::OK, response.status()); - - Ok(()) - } } |