Working on access/refresh tokens
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
use actix_web::{get, post, web, HttpResponse, ResponseError};
|
||||
use actix_web_httpauth::middleware::HttpAuthentication;
|
||||
use std::env;
|
||||
|
||||
use actix_web::{get, post, web, HttpResponse, ResponseError, cookie::{Cookie, time::Duration}, HttpRequest};
|
||||
use log::error;
|
||||
use redis::AsyncCommands;
|
||||
use siren::ServiceError;
|
||||
|
||||
use crate::auth::{LoginRequest, RegisterUser, InsertUser, QueryUser, verify_password, create_token, LoginResponse};
|
||||
|
||||
use super::validator;
|
||||
use crate::{auth::{LoginRequest, RegisterUser, InsertUser, QueryUser, verify_password, generate_token, JwtAuth}, db};
|
||||
|
||||
#[post("/register")]
|
||||
async fn register(user: web::Json<RegisterUser>) -> HttpResponse {
|
||||
@@ -40,8 +41,80 @@ async fn login(request: web::Json<LoginRequest>) -> HttpResponse {
|
||||
let password = request.password.as_bytes();
|
||||
match verify_password(&hash, password) {
|
||||
Ok(_) => {
|
||||
let token = create_token(&email);
|
||||
HttpResponse::Ok().json(LoginResponse { token })
|
||||
let access_token_max_age = env::var("ACCESS_TOKEN_MAXAGE")
|
||||
.expect("ACCESS_TOKEN_MAXAGE must be set")
|
||||
.parse::<i64>()
|
||||
.expect("ACCESS_TOKEN_MAXAGE must be an integer");
|
||||
let access_private_key = env::var("ACCESS_TOKEN_PRIVATE_KEY")
|
||||
.expect("ACCESS_TOKEN_PRIVATE_KEY must be set");
|
||||
let access_token_details = match generate_token(&email, access_token_max_age, &access_private_key) {
|
||||
Ok(token_details) => token_details,
|
||||
Err(err) => {
|
||||
error!("Failed to generate access token: {}", err);
|
||||
return ResponseError::error_response(&err)
|
||||
}
|
||||
};
|
||||
let refresh_token_max_age = env::var("REFRESH_TOKEN_MAXAGE")
|
||||
.expect("REFRESH_TOKEN_MAXAGE must be set")
|
||||
.parse::<i64>()
|
||||
.expect("REFRESH_TOKEN_MAXAGE must be an integer");
|
||||
let refresh_private_key = env::var("REFRESH_TOKEN_PRIVATE_KEY")
|
||||
.expect("REFRESH_TOKEN_PRIVATE_KEY must be set");
|
||||
let refresh_token_details = match generate_token(&email, refresh_token_max_age, &refresh_private_key) {
|
||||
Ok(token_details) => token_details,
|
||||
Err(err) => {
|
||||
error!("Failed to generate refresh token: {}", err);
|
||||
return ResponseError::error_response(&err)
|
||||
}
|
||||
};
|
||||
|
||||
let mut conn = match db::redis_async_connection().await {
|
||||
Ok(conn) => conn,
|
||||
Err(err) => {
|
||||
error!("Failed to get redis connection: {}", err);
|
||||
return ResponseError::error_response(&err)
|
||||
}
|
||||
};
|
||||
|
||||
let access_result: redis::RedisResult<()> = conn.set_ex(access_token_details.token_uuid.to_string(), &email, (access_token_max_age * 60) as usize).await;
|
||||
if let Err(err) = access_result {
|
||||
error!("Failed to set access token in redis: {}", err);
|
||||
return ResponseError::error_response(&ServiceError {
|
||||
status: 500,
|
||||
message: format!("Failed to set access token in redis: {}", err)
|
||||
})
|
||||
};
|
||||
|
||||
let refresh_result: redis::RedisResult<()> = conn.set_ex(refresh_token_details.token_uuid.to_string(), &email, (refresh_token_max_age * 60) as usize).await;
|
||||
if let Err(err) = refresh_result {
|
||||
error!("Failed to set refresh token in redis: {}", err);
|
||||
return ResponseError::error_response(&ServiceError {
|
||||
status: 500,
|
||||
message: format!("Failed to set refresh token in redis: {}", err)
|
||||
})
|
||||
};
|
||||
|
||||
let access_cookie = Cookie::build("access_token", access_token_details.token.clone().unwrap())
|
||||
.path("/")
|
||||
.max_age(Duration::new(access_token_max_age, 0))
|
||||
.http_only(true)
|
||||
.finish();
|
||||
let refresh_cookie = Cookie::build("refresh_token", refresh_token_details.token.clone().unwrap())
|
||||
.path("/")
|
||||
.max_age(Duration::new(refresh_token_max_age, 0))
|
||||
.http_only(true)
|
||||
.finish();
|
||||
let logged_in_cookie = Cookie::build("logged_in", "true")
|
||||
.path("/")
|
||||
.max_age(Duration::new(access_token_max_age, 0))
|
||||
.http_only(false)
|
||||
.finish();
|
||||
|
||||
HttpResponse::Ok()
|
||||
.cookie(access_cookie)
|
||||
.cookie(refresh_cookie)
|
||||
.cookie(logged_in_cookie)
|
||||
.json(access_token_details.token.unwrap())
|
||||
},
|
||||
Err(err) => ResponseError::error_response(&ServiceError {
|
||||
status: 401,
|
||||
@@ -50,24 +123,27 @@ async fn login(request: web::Json<LoginRequest>) -> HttpResponse {
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/logout")]
|
||||
async fn logout() -> HttpResponse {
|
||||
#[get("/refresh")]
|
||||
async fn refresh(req: HttpRequest) -> HttpResponse {
|
||||
HttpResponse::Ok().finish()
|
||||
}
|
||||
|
||||
#[get("/ping")]
|
||||
async fn ping() -> HttpResponse {
|
||||
#[post("/logout")]
|
||||
async fn logout(req: HttpRequest, auth: JwtAuth) -> HttpResponse {
|
||||
HttpResponse::Ok().finish()
|
||||
}
|
||||
|
||||
#[get("/me")]
|
||||
async fn me(auth: JwtAuth) -> HttpResponse {
|
||||
HttpResponse::Ok().json(auth)
|
||||
}
|
||||
|
||||
pub fn init_routes(config: &mut web::ServiceConfig) {
|
||||
let auth = HttpAuthentication::bearer(validator);
|
||||
config.service(web::scope("auth")
|
||||
.service(register)
|
||||
.service(login)
|
||||
.service(web::scope("")
|
||||
.wrap(auth)
|
||||
.service(logout)
|
||||
.service(ping)
|
||||
));
|
||||
.service(refresh)
|
||||
.service(logout)
|
||||
.service(me)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user