Merge pull request #16 from fLotte-meets-HWR-DB/develop

Fix new-token rejecting after request token expiration
leon_tries_rust
Trivernis 4 years ago committed by GitHub
commit 6247ddb8ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,7 +2,7 @@
// Copyright (C) 2020 trivernis
// See LICENSE for more information
use std::cmp::{max, min};
use std::cmp::max;
use std::collections::HashMap;
use std::time::Instant;
@ -48,8 +48,9 @@ impl SessionTokens {
/// Creates a new session tokens instance from a token store
/// entry
pub fn from_entry(other: &TokenStoreEntry) -> Option<Self> {
let request_token = other.request_token()?;
let request_token = other.request_token().unwrap_or("".to_string());
let refresh_token = other.refresh_token()?;
Some(Self {
refresh_token,
request_token,
@ -61,6 +62,8 @@ impl SessionTokens {
/// Refreshes the request token
pub fn refresh(&mut self) {
self.request_token = base64::encode(create_user_token(self.get_user_id()));
self.request_ttl = REQUEST_TOKEN_EXPIRE_SECONDS as i32;
log::trace!("Request token refreshed.")
}
/// Returns the user id that is stored in the first four bytes of the refresh token
@ -70,7 +73,13 @@ impl SessionTokens {
/// Saves the tokens into the database
pub fn store(&self, token_store: &mut TokenStore) -> Result<(), String> {
token_store.insert(&self.request_token, &self.refresh_token)
if let Some(tokens) = token_store.get_by_refresh_token(&self.refresh_token) {
tokens.set_request_token(self.request_token.clone());
} else {
token_store.insert(&self.request_token, &self.refresh_token)?;
}
Ok(())
}
}
@ -156,6 +165,7 @@ impl TokenStoreEntry {
self.reset_timer();
self.request_ttl = REQUEST_TOKEN_EXPIRE_SECONDS;
self.refresh_ttl = REFRESH_TOKEN_EXPIRE_SECONDS;
log::trace!("TTLs reset");
self.request_ttl as i32
}
@ -164,9 +174,20 @@ impl TokenStoreEntry {
/// before resetting the current expiration times are stored so the ttl
/// for both tokens won't reset
fn reset_timer(&mut self) {
self.request_ttl = min(self.request_ttl(), 0) as u32;
self.refresh_ttl = min(self.refresh_ttl(), 0) as u32;
log::trace!("Resetting timer...");
log::trace!(
"req_ttl: {}, ref_ttl: {}",
self.request_ttl,
self.refresh_ttl
);
self.request_ttl = max(self.request_ttl(), 0) as u32;
self.refresh_ttl = max(self.refresh_ttl(), 0) as u32;
self.ttl_start = Instant::now();
log::trace!(
"req_ttl: {}, ref_ttl: {}",
self.request_ttl,
self.refresh_ttl
);
}
/// Invalidates the token entry which causes it to be deleted with the next
@ -174,6 +195,7 @@ impl TokenStoreEntry {
pub(crate) fn invalidate(&mut self) {
self.request_ttl = 0;
self.refresh_ttl = 0;
log::trace!("Tokens invalidated.");
}
}
@ -192,6 +214,7 @@ impl TokenStore {
/// Returns the token store entry for a given request token
pub fn get_by_request_token(&mut self, request_token: &String) -> Option<&mut TokenStoreEntry> {
let user_id = get_user_id_from_token(&request_token)?;
if let Some(user_tokens) = self.tokens.get_mut(&user_id) {
user_tokens.iter_mut().find(|e| {
if let Some(token) = e.request_token() {
@ -207,16 +230,20 @@ impl TokenStore {
/// Returns the token store entry by the given refresh token
pub fn get_by_refresh_token(&mut self, refresh_token: &String) -> Option<&mut TokenStoreEntry> {
log::trace!("Retrieving user by refresh token.");
let user_id = get_user_id_from_token(&refresh_token)?;
log::trace!("UserID is {}", user_id);
if let Some(user_tokens) = self.tokens.get_mut(&user_id) {
user_tokens.iter_mut().find(|e| {
if let Some(token) = e.refresh_token() {
&token == refresh_token
token.eq(refresh_token)
} else {
false
}
})
} else {
log::trace!("No tokens found for user");
None
}
}
@ -231,6 +258,7 @@ impl TokenStore {
if let Some(ref_token) = &e.refresh_token() {
if ref_token == refresh_token {
e.set_request_token(request_token.to_string());
log::debug!("New request token set for userId {}", user_id);
}
}
});
@ -266,7 +294,9 @@ impl TokenStore {
/// Deletes all expired tokens from the store
pub fn clear_expired(&mut self) {
log::trace!("Clearing expired tokens...");
for (key, entry) in &self.tokens.clone() {
log::trace!("Before: {} tokens for user {}", entry.len(), key);
self.tokens.insert(
*key,
entry
@ -275,6 +305,12 @@ impl TokenStore {
.filter(|e| e.refresh_ttl() > 0)
.collect(),
);
log::trace!(
"After: {} tokens for user {}",
self.tokens.get(key).unwrap().len(),
key
);
}
log::trace!("Clearing expired tokens cleared");
}
}

@ -229,12 +229,16 @@ impl Users {
pub fn refresh_tokens(&self, refresh_token: &String) -> DatabaseResult<SessionTokens> {
let mut token_store = self.token_store.lock();
let tokens = token_store.get_by_refresh_token(refresh_token);
if let Some(mut tokens) = tokens.and_then(|t| SessionTokens::from_entry(t)) {
log::trace!("Tokens found. Refreshing...");
tokens.refresh();
tokens.store(&mut token_store)?;
log::trace!("Tokens successfully refreshed.");
Ok(tokens)
} else {
log::trace!("No token store found for user");
Err(DBError::GenericError("Invalid refresh token!".to_string()))
}
}

@ -9,7 +9,7 @@ use chrono::Local;
use colored::Colorize;
use crossbeam_utils::sync::WaitGroup;
use env_logger::Env;
use log::Level;
use log::{Level, LevelFilter};
use flotte_user_management::database::Database;
use flotte_user_management::server::http_server::UserHttpServer;
@ -58,6 +58,8 @@ fn main() {
/// that also logs the thread names
fn init_logger() {
env_logger::Builder::from_env(Env::default().default_filter_or("info"))
.filter_module("tokio_postgres", LevelFilter::Info)
.filter_module("tokio_util", LevelFilter::Info)
.format(|buf, record| {
use std::io::Write;
let color = get_level_style(record.level());

Loading…
Cancel
Save