Project compiles now

pull/2/head
Jef Roosens 2021-11-23 12:18:14 +01:00
parent 4c07e18787
commit 7afb44bfa9
Signed by: Jef Roosens
GPG Key ID: 955C0660072F691F
4 changed files with 78 additions and 99 deletions

View File

@ -1,19 +1,12 @@
use chrono::Utc;
use hmac::{Hmac, NewMac};
use jwt::SignWithKey;
use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct JwtConf {
key: String,
pub key: String,
refresh_token_size: usize,
refresh_token_expire: i64,
}
use crate::errors::{RbError, RbResult};
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct JWTResponse {
@ -29,79 +22,79 @@ pub struct Claims {
pub exp: i64,
}
pub fn generate_jwt_token(
jwt: &JwtConf,
id: uuid::Uuid,
username: String,
is_admin: bool,
) -> RbResult<JWTResponse> {
let key: Hmac<Sha256> = Hmac::new_from_slice(jwt.key.as_bytes())
.map_err(|_| RbError::Custom("Couldn't create Hmac key."))?;
// pub fn generate_jwt_token(
// jwt: &JwtConf,
// id: uuid::Uuid,
// username: String,
// is_admin: bool,
// ) -> RbResult<JWTResponse> {
// let key: Hmac<Sha256> = Hmac::new_from_slice(jwt.key.as_bytes())
// .map_err(|_| RbError::Custom("Couldn't create Hmac key."))?;
let current_time = Utc::now();
// let current_time = Utc::now();
// Create the claims
let claims = Claims {
id,
username: username.clone(),
admin: is_admin,
exp: current_time.timestamp() + jwt.refresh_token_expire,
};
// // Create the claims
// let claims = Claims {
// id,
// username: username.clone(),
// admin: is_admin,
// exp: current_time.timestamp() + jwt.refresh_token_expire,
// };
// Sign the claims into a new token
let token = claims
.sign_with_key(&key)
.map_err(|_| RbError::Custom("Couldn't sign JWT."))?;
// // Sign the claims into a new token
// let token = claims
// .sign_with_key(&key)
// .map_err(|_| RbError::Custom("Couldn't sign JWT."))?;
// Generate a random refresh token
let mut refresh_token = vec![0u8; jwt.refresh_token_size];
thread_rng().fill(&mut refresh_token[..]);
// // Generate a random refresh token
// let mut refresh_token = vec![0u8; jwt.refresh_token_size];
// thread_rng().fill(&mut refresh_token[..]);
let refresh_expire =
(current_time + chrono::Duration::seconds(jwt.refresh_token_expire)).naive_utc();
// let refresh_expire =
// (current_time + chrono::Duration::seconds(jwt.refresh_token_expire)).naive_utc();
Ok(JWTResponse {
token,
refresh_token: base64::encode(refresh_token),
})
}
// Ok(JWTResponse {
// token,
// refresh_token: base64::encode(refresh_token),
// })
// }
pub fn refresh_token(
conn: &PgConnection,
jwt: &JwtConf,
refresh_token: &str,
) -> RbResult<JWTResponse> {
let token_bytes =
base64::decode(refresh_token).map_err(|_| RbError::AuthInvalidRefreshToken)?;
// pub fn refresh_token(
// conn: &PgConnection,
// jwt: &JwtConf,
// refresh_token: &str,
// ) -> RbResult<JWTResponse> {
// let token_bytes =
// base64::decode(refresh_token).map_err(|_| RbError::AuthInvalidRefreshToken)?;
// First, we request the token from the database to see if it's really a valid token
let (token_entry, user) =
db::tokens::find_with_user(conn, &token_bytes).ok_or(RbError::AuthInvalidRefreshToken)?;
// // First, we request the token from the database to see if it's really a valid token
// let (token_entry, user) =
// db::tokens::find_with_user(conn, &token_bytes).ok_or(RbError::AuthInvalidRefreshToken)?;
// If we see that the token has already been used before, we block the user.
if token_entry.last_used_at.is_some() {
// If we fail to block the user, the end user must know
if let Err(err) = db::users::block(conn, token_entry.user_id) {
return Err(err);
}
// // If we see that the token has already been used before, we block the user.
// if token_entry.last_used_at.is_some() {
// // If we fail to block the user, the end user must know
// if let Err(err) = db::users::block(conn, token_entry.user_id) {
// return Err(err);
// }
return Err(RbError::AuthDuplicateRefreshToken);
}
// return Err(RbError::AuthDuplicateRefreshToken);
// }
// Then we check if the user is blocked
if user.blocked {
return Err(RbError::AuthBlockedUser);
}
// // Then we check if the user is blocked
// if user.blocked {
// return Err(RbError::AuthBlockedUser);
// }
// Now we check if the token has already expired
let cur_time = Utc::now().naive_utc();
// // Now we check if the token has already expired
// let cur_time = Utc::now().naive_utc();
if token_entry.expires_at < cur_time {
return Err(RbError::AuthTokenExpired);
}
// if token_entry.expires_at < cur_time {
// return Err(RbError::AuthTokenExpired);
// }
// We update the last_used_at value for the refresh token
db::tokens::update_last_used_at(conn, &token_entry.token, cur_time)?;
// // We update the last_used_at value for the refresh token
// db::tokens::update_last_used_at(conn, &token_entry.token, cur_time)?;
generate_jwt_token(conn, jwt, &user)
}
// generate_jwt_token(conn, jwt, &user)
// }

View File

@ -1,8 +0,0 @@
use serde::{Serialize, Deserialize}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct RbJwtConf {
key: String,
refresh_token_size: usize,
refresh_token_expire: i64,
}

View File

@ -8,18 +8,19 @@ use rocket::{
};
use sha2::Sha256;
use crate::{auth::jwt::Claims, errors::RbError, RbConfig};
use crate::{
auth::jwt::{Claims, JwtConf},
errors::RbError,
};
/// Extracts an "Authorization: Bearer" string from the headers.
pub struct Bearer<'a>(&'a str);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Bearer<'r>
{
impl<'r> FromRequest<'r> for Bearer<'r> {
type Error = crate::errors::RbError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error>
{
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
// If the header isn't present, just forward to the next route
let header = match req.headers().get_one("Authorization") {
None => return Outcome::Forward(()),
@ -41,26 +42,24 @@ impl<'r> FromRequest<'r> for Bearer<'r>
pub struct Jwt(Claims);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Jwt
{
impl<'r> FromRequest<'r> for Jwt {
type Error = RbError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error>
{
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let bearer = try_outcome!(req.guard::<Bearer>().await).0;
let config = try_outcome!(req.guard::<&State<RbConfig>>().await.map_failure(|_| (
let config = try_outcome!(req.guard::<&State<JwtConf>>().await.map_failure(|_| (
Status::InternalServerError,
RbError::Custom("Couldn't get config guard.")
)));
let key: Hmac<Sha256> = match Hmac::new_from_slice(&config.jwt.key.as_bytes()) {
let key: Hmac<Sha256> = match Hmac::new_from_slice(&config.key.as_bytes()) {
Ok(key) => key,
Err(_) => {
return Outcome::Failure((
Status::InternalServerError,
Self::Error::Custom("Failed to do Hmac thing."),
))
},
}
};
// Verify token using key
@ -68,7 +67,7 @@ impl<'r> FromRequest<'r> for Jwt
Ok(claims) => Outcome::Success(Self(claims)),
Err(_) => {
return Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized))
},
}
}
}
}
@ -77,12 +76,10 @@ impl<'r> FromRequest<'r> for Jwt
pub struct User(Claims);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for User
{
impl<'r> FromRequest<'r> for User {
type Error = crate::errors::RbError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error>
{
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let claims = try_outcome!(req.guard::<Jwt>().await).0;
// Verify key hasn't yet expired
@ -98,12 +95,10 @@ impl<'r> FromRequest<'r> for User
pub struct Admin(Claims);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Admin
{
impl<'r> FromRequest<'r> for Admin {
type Error = crate::errors::RbError;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error>
{
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let user = try_outcome!(req.guard::<User>().await).0;
if user.admin {

View File

@ -1,4 +1,3 @@
pub mod auth;
pub mod config;
pub mod errors;
pub mod guards;