fix session authentication
This commit is contained in:
parent
75ab376ebd
commit
e79ee4c6c5
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
|
@ -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 {},
|
||||||
|
|
|
@ -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>> {
|
||||||
|
|
Loading…
Reference in New Issue