fix session authentication

This commit is contained in:
c0repwn3r 2023-02-06 10:17:48 -05:00
parent 75ab376ebd
commit e79ee4c6c5
Signed by: core
GPG Key ID: FDBF740DADDCEECF
5 changed files with 24 additions and 11 deletions

View File

@ -14,7 +14,7 @@ pub struct PartialUserInfo {
#[derive(Debug)] #[derive(Debug)]
pub enum AuthenticationError { pub enum AuthenticationError {
MissingToken, MissingToken,
InvalidToken, InvalidToken(usize),
DatabaseError, DatabaseError,
RequiresTOTP RequiresTOTP
} }
@ -31,16 +31,16 @@ impl<'r> FromRequest<'r> for PartialUserInfo {
// parse bearer token // parse bearer token
let components = authorization.split(' ').collect::<Vec<&str>>(); let components = authorization.split(' ').collect::<Vec<&str>>();
if components.len() != 2 || components.len() != 3 { if components.len() != 2 && components.len() != 3 {
return Outcome::Failure((Status::Unauthorized, AuthenticationError::MissingToken)); return Outcome::Failure((Status::Unauthorized, AuthenticationError::MissingToken));
} }
if components[0] != "Bearer" { if components[0] != "Bearer" {
return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)); return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(0)));
} }
if components.len() == 2 && components[1].starts_with("st-") { if components.len() == 2 && !components[1].starts_with("st-") {
return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)); return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(1)));
} }
let st: String; let st: String;
@ -53,10 +53,10 @@ impl<'r> FromRequest<'r> for PartialUserInfo {
st = components[1].to_string(); st = components[1].to_string();
match validate_session_token(st.clone(), req.rocket().state().unwrap()).await { match validate_session_token(st.clone(), req.rocket().state().unwrap()).await {
Ok(uid) => user_id = uid, Ok(uid) => user_id = uid,
Err(_) => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)) Err(_) => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(2)))
} }
}, },
_ => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)) _ => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(3)))
} }
if components.len() == 3 { if components.len() == 3 {
@ -66,10 +66,10 @@ impl<'r> FromRequest<'r> for PartialUserInfo {
at = Some(components[2].to_string()); at = Some(components[2].to_string());
match validate_auth_token(at.clone().unwrap().clone(), st.clone(), req.rocket().state().unwrap()).await { match validate_auth_token(at.clone().unwrap().clone(), st.clone(), req.rocket().state().unwrap()).await {
Ok(_) => (), Ok(_) => (),
Err(_) => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)) Err(_) => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(4)))
} }
}, },
_ => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken)) _ => return Outcome::Failure((Status::Unauthorized, AuthenticationError::InvalidToken(5)))
} }
} else { } else {
at = None; at = None;

View File

@ -81,7 +81,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
.mount("/", routes![ .mount("/", routes![
crate::routes::v1::auth::magic_link::magiclink_request, crate::routes::v1::auth::magic_link::magiclink_request,
crate::routes::v1::signup::signup_request, crate::routes::v1::signup::signup_request,
crate::routes::v1::auth::verify_magic_link::verify_magic_link crate::routes::v1::auth::verify_magic_link::verify_magic_link,
crate::routes::v1::auth::check_auth,
]) ])
.register("/", catchers![ .register("/", catchers![
crate::routes::handler_400, crate::routes::handler_400,

View File

@ -1,2 +1,4 @@
use crate::auth::PartialUserInfo;
pub mod verify_magic_link; pub mod verify_magic_link;
pub mod magic_link; pub mod magic_link;

View File

@ -53,6 +53,14 @@ pub async fn verify_magic_link(req: Json<VerifyMagicLinkRequest>, db: &State<PgP
} }
}; };
// delete the token
match sqlx::query!("DELETE FROM magic_links WHERE id = $1", req.0.magic_link_token).execute(db.inner()).await {
Ok(_) => (),
Err(e) => {
return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"{}\",\"message\":\"{} - {}\"}}]}}", "ERR_UNABLE_TO_ISSUE", "an error occured trying to issue a session token, please try again later", e)))
}
}
Ok((ContentType::JSON, Json(VerifyMagicLinkResponse { Ok((ContentType::JSON, Json(VerifyMagicLinkResponse {
data: VerifyMagicLinkResponseData { session_token: token }, data: VerifyMagicLinkResponseData { session_token: token },
metadata: VerifyMagicLinkResponseMetadata {}, metadata: VerifyMagicLinkResponseMetadata {},

View File

@ -22,7 +22,7 @@ pub async fn generate_session_token(user_id: i64, db: &PgPool, config: &TFConfig
Ok(token) Ok(token)
} }
pub async fn validate_session_token(token: String, db: &PgPool) -> Result<i64, Box<dyn Error>> { pub async fn validate_session_token(token: String, db: &PgPool) -> Result<i64, Box<dyn Error>> {
Ok(sqlx::query!("SELECT user_id FROM session_tokens WHERE id = $1 AND expires_on < $2", token, SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i32).fetch_one(db).await?.user_id as i64) Ok(sqlx::query!("SELECT user_id FROM session_tokens WHERE id = $1 AND expires_on > $2", token, SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i32).fetch_one(db).await?.user_id as i64)
} }
pub async fn generate_auth_token(user_id: i64, session_id: String, db: &PgPool, config: &TFConfig) -> Result<String, Box<dyn Error>> { pub async fn generate_auth_token(user_id: i64, session_id: String, db: &PgPool, config: &TFConfig) -> Result<String, Box<dyn Error>> {