First successful JWT token request achieved
parent
0d4d96d761
commit
13259249fd
|
@ -155,6 +155,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
"time 0.1.44",
|
"time 0.1.44",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
@ -252,6 +253,7 @@ checksum = "bba51ca66f57261fd17cadf8b73e4775cc307d0521d855de3f5de91a8f074e0e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
"diesel_derives",
|
"diesel_derives",
|
||||||
"pq-sys",
|
"pq-sys",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
|
|
|
@ -16,7 +16,7 @@ path = "src/rbs/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# ORM
|
# ORM
|
||||||
diesel = { version = "1.4.7", features = ["postgres", "uuidv07"] }
|
diesel = { version = "1.4.7", features = ["postgres", "uuidv07", "chrono"] }
|
||||||
diesel_migrations = "1.4.0"
|
diesel_migrations = "1.4.0"
|
||||||
# To properly compile libpq statically
|
# To properly compile libpq statically
|
||||||
openssl = "0.10.36"
|
openssl = "0.10.36"
|
||||||
|
@ -27,7 +27,7 @@ uuid = { version = "0.8.2", features = ["serde"] }
|
||||||
jwt = "0.14.0"
|
jwt = "0.14.0"
|
||||||
hmac = "*"
|
hmac = "*"
|
||||||
sha2 = "*"
|
sha2 = "*"
|
||||||
chrono = "0.4.19"
|
chrono = { version = "*", features = [ "serde" ] }
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
|
|
||||||
# Backend web framework
|
# Backend web framework
|
||||||
|
|
|
@ -17,6 +17,14 @@ use std::collections::HashMap;
|
||||||
const JWT_EXP_SECONDS: i64 = 900;
|
const JWT_EXP_SECONDS: i64 = 900;
|
||||||
/// Amount of bytes the refresh tokens should consist of
|
/// Amount of bytes the refresh tokens should consist of
|
||||||
const REFRESH_TOKEN_N_BYTES: usize = 64;
|
const REFRESH_TOKEN_N_BYTES: usize = 64;
|
||||||
|
/// Expire time for refresh tokens; here: one week
|
||||||
|
const REFRESH_TOKEN_EXP_SECONDS: i64 = 36288000;
|
||||||
|
|
||||||
|
fn log<T>(message: &str, o: T) -> T {
|
||||||
|
println!("{}", message);
|
||||||
|
|
||||||
|
o
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<User> {
|
pub fn verify_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<User> {
|
||||||
// TODO handle non-"NotFound" Diesel errors accordingely
|
// TODO handle non-"NotFound" Diesel errors accordingely
|
||||||
|
@ -46,7 +54,9 @@ pub struct JWTResponse {
|
||||||
pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result<JWTResponse> {
|
pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result<JWTResponse> {
|
||||||
// TODO actually use proper secret here
|
// TODO actually use proper secret here
|
||||||
let key: Hmac<Sha256> =
|
let key: Hmac<Sha256> =
|
||||||
Hmac::new_from_slice(b"some-secret").map_err(|_| RBError::JWTCreationError)?;
|
Hmac::new_from_slice(b"some-secret").map_err(|_| log("Failed to create key", RBError::JWTCreationError))?;
|
||||||
|
|
||||||
|
let current_time = Utc::now();
|
||||||
|
|
||||||
// Create the claims
|
// Create the claims
|
||||||
let mut claims = HashMap::new();
|
let mut claims = HashMap::new();
|
||||||
|
@ -55,23 +65,27 @@ pub fn generate_jwt_token(conn: &PgConnection, user: &User) -> crate::Result<JWT
|
||||||
claims.insert("admin", user.admin.to_string());
|
claims.insert("admin", user.admin.to_string());
|
||||||
claims.insert(
|
claims.insert(
|
||||||
"exp",
|
"exp",
|
||||||
(Utc::now().timestamp() + JWT_EXP_SECONDS).to_string(),
|
(current_time.timestamp() + JWT_EXP_SECONDS).to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Sign the claims into a new token
|
// Sign the claims into a new token
|
||||||
let token = claims
|
let token = claims
|
||||||
.sign_with_key(&key)
|
.sign_with_key(&key)
|
||||||
.map_err(|_| RBError::JWTCreationError)?;
|
.map_err(|_| log("Failed to sign token", RBError::JWTCreationError))?;
|
||||||
|
|
||||||
// Generate a random refresh token
|
// Generate a random refresh token
|
||||||
let mut refresh_token = [0u8; REFRESH_TOKEN_N_BYTES];
|
let mut refresh_token = [0u8; REFRESH_TOKEN_N_BYTES];
|
||||||
thread_rng().fill(&mut refresh_token[..]);
|
thread_rng().fill(&mut refresh_token[..]);
|
||||||
|
|
||||||
|
let refresh_expire = (current_time + chrono::Duration::seconds(REFRESH_TOKEN_EXP_SECONDS)).naive_utc();
|
||||||
|
|
||||||
// Store refresh token in database
|
// Store refresh token in database
|
||||||
|
// TODO add expires_at here (it's what's causing the errors)
|
||||||
insert_into(refresh_tokens::refresh_tokens)
|
insert_into(refresh_tokens::refresh_tokens)
|
||||||
.values(NewRefreshToken {
|
.values(NewRefreshToken {
|
||||||
token: refresh_token.to_vec(),
|
token: refresh_token.to_vec(),
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
|
expires_at: refresh_expire
|
||||||
})
|
})
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.map_err(|_| RBError::JWTCreationError)?;
|
.map_err(|_| RBError::JWTCreationError)?;
|
||||||
|
@ -94,7 +108,6 @@ pub fn hash_password(password: &str) -> crate::Result<String> {
|
||||||
|
|
||||||
pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<bool> {
|
pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) -> crate::Result<bool> {
|
||||||
let pass_hashed = hash_password(password)?;
|
let pass_hashed = hash_password(password)?;
|
||||||
println!("{}", pass_hashed);
|
|
||||||
let new_user = NewUser {
|
let new_user = NewUser {
|
||||||
username: username.to_string(),
|
username: username.to_string(),
|
||||||
password: pass_hashed,
|
password: pass_hashed,
|
||||||
|
@ -103,9 +116,9 @@ pub fn create_admin_user(conn: &PgConnection, username: &str, password: &str) ->
|
||||||
|
|
||||||
insert_into(users::users)
|
insert_into(users::users)
|
||||||
.values(&new_user)
|
.values(&new_user)
|
||||||
// .on_conflict((users::username, users::password, users::admin))
|
.on_conflict(users::username)
|
||||||
// .do_update()
|
.do_update()
|
||||||
// .set(&new_user)
|
.set(&new_user)
|
||||||
.execute(conn).map_err(|_| RBError::AdminCreationError)?;
|
.execute(conn).map_err(|_| RBError::AdminCreationError)?;
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|
|
@ -27,4 +27,5 @@ pub struct NewUser {
|
||||||
pub struct NewRefreshToken {
|
pub struct NewRefreshToken {
|
||||||
pub token: Vec<u8>,
|
pub token: Vec<u8>,
|
||||||
pub user_id: Uuid,
|
pub user_id: Uuid,
|
||||||
|
pub expires_at: chrono::NaiveDateTime
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue