diff --git a/src/api/mod.rs b/src/api/mod.rs index 80dc442..b79c824 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,2 +1,11 @@ -pub mod v1; -pub mod versions; +use actix_web::Scope; +use actix_web::web; + +mod v1; +mod versions; + +pub fn web() -> Scope { + web::scope("/api") + .service(v1::web()) + .service(versions::res) +} diff --git a/src/api/v1/auth/login.rs b/src/api/v1/auth/login.rs index 1bd781f..0ea3d83 100644 --- a/src/api/v1/auth/login.rs +++ b/src/api/v1/auth/login.rs @@ -1,17 +1,17 @@ use std::time::{SystemTime, UNIX_EPOCH}; -use actix_web::{Error, HttpResponse, error, post, web}; +use actix_web::{error, post, web, Error, HttpResponse}; use argon2::{PasswordHash, PasswordVerifier}; use futures::StreamExt; use log::error; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use crate::{ - Data, - api::v1::auth::{EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX}, - crypto::{generate_access_token, generate_refresh_token}, + api::v1::auth::{EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX}, crypto::{generate_access_token, generate_refresh_token}, utils::refresh_token_cookie, Data }; +use super::Response; + #[derive(Deserialize)] struct LoginInformation { username: String, @@ -19,12 +19,6 @@ struct LoginInformation { device_name: String, } -#[derive(Serialize)] -pub struct Response { - pub access_token: String, - pub refresh_token: String, -} - const MAX_SIZE: usize = 262_144; #[post("/login")] @@ -187,8 +181,7 @@ async fn login( return HttpResponse::InternalServerError().finish() } - HttpResponse::Ok().json(Response { + HttpResponse::Ok().cookie(refresh_token_cookie(refresh_token)).json(Response { access_token, - refresh_token, }) } diff --git a/src/api/v1/auth/mod.rs b/src/api/v1/auth/mod.rs index e9b29d1..bfd32af 100644 --- a/src/api/v1/auth/mod.rs +++ b/src/api/v1/auth/mod.rs @@ -7,6 +7,7 @@ use std::{ use actix_web::{HttpResponse, Scope, web}; use log::error; use regex::Regex; +use serde::Serialize; use sqlx::Postgres; use uuid::Uuid; @@ -15,6 +16,11 @@ mod refresh; mod register; mod revoke; +#[derive(Serialize)] +struct Response { + access_token: String, +} + static EMAIL_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?").unwrap() }); diff --git a/src/api/v1/auth/refresh.rs b/src/api/v1/auth/refresh.rs index e17ecc7..7e331a2 100644 --- a/src/api/v1/auth/refresh.rs +++ b/src/api/v1/auth/refresh.rs @@ -1,28 +1,22 @@ use actix_web::{post, web, Error, HttpRequest, HttpResponse}; use log::error; -use serde::Serialize; use std::time::{SystemTime, UNIX_EPOCH}; use crate::{ - Data, - crypto::{generate_access_token, generate_refresh_token}, + crypto::{generate_access_token, generate_refresh_token}, utils::refresh_token_cookie, Data }; -#[derive(Serialize)] -struct Response { - refresh_token: String, - access_token: String, -} +use super::Response; #[post("/refresh")] pub async fn res(req: HttpRequest, data: web::Data) -> Result { - let refresh_token_cookie = req.cookie("refresh_token"); + let recv_refresh_token_cookie = req.cookie("refresh_token"); - if let None = refresh_token_cookie { + if let None = recv_refresh_token_cookie { return Ok(HttpResponse::Unauthorized().finish()) } - let mut refresh_token = String::from(refresh_token_cookie.unwrap().value()); + let mut refresh_token = String::from(recv_refresh_token_cookie.unwrap().value()); let current_time = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -101,8 +95,7 @@ pub async fn res(req: HttpRequest, data: web::Data) -> Result) -> Result { diff --git a/src/main.rs b/src/main.rs index fbde53b..e967021 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,8 +89,7 @@ async fn main() -> Result<(), Error> { HttpServer::new(move || { App::new() .app_data(web::Data::new(data.clone())) - .service(api::versions::res) - .service(api::v1::web()) + .service(api::web()) }) .bind((web.url, web.port))? .run() diff --git a/src/utils.rs b/src/utils.rs index d80bed4..b432d19 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use actix_web::{HttpResponse, http::header::HeaderMap}; +use actix_web::{cookie::{time::Duration, Cookie, SameSite}, http::header::HeaderMap, HttpResponse}; pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, HttpResponse> { let auth_token = headers.get(actix_web::http::header::AUTHORIZATION); @@ -21,3 +21,13 @@ pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, HttpResponse> { Ok(auth_value.unwrap()) } + +pub fn refresh_token_cookie(refresh_token: String) -> Cookie<'static> { + Cookie::build("refresh_token", refresh_token) + .http_only(true) + .secure(true) + .same_site(SameSite::None) + .path("/api") + .max_age(Duration::days(30)) + .finish() +}