Improve security
This commit is contained in:
+55
-24
@@ -1,22 +1,33 @@
|
||||
use super::jwt;
|
||||
use crate::database::establish_connection;
|
||||
use crate::models::user::rss_user::User;
|
||||
use crate::schema::users;
|
||||
use actix_web::dev::ServiceRequest;
|
||||
use diesel::prelude::*;
|
||||
|
||||
pub fn check_password(password: String) -> Result<i32, &'static str> {
|
||||
match jwt::JwtToken::decode(password) {
|
||||
Ok(token) => Ok(token.user_id),
|
||||
Err(message) => Err(message),
|
||||
/// Decodes the token and confirms it hasn't been revoked, i.e. its `token_version`
|
||||
/// still matches the one stored on the user (bumped on logout / password change).
|
||||
pub fn check_token(token: String) -> Result<i32, &'static str> {
|
||||
let decoded = jwt::JwtToken::decode(token)?;
|
||||
|
||||
let mut connection = establish_connection();
|
||||
let user: User = users::table
|
||||
.find(decoded.user_id)
|
||||
.first(&mut connection)
|
||||
.map_err(|_| "could not decode token")?;
|
||||
|
||||
if user.token_version != decoded.token_version {
|
||||
return Err("token has been revoked");
|
||||
}
|
||||
|
||||
Ok(decoded.user_id)
|
||||
}
|
||||
|
||||
pub fn extract_header_token(request: &ServiceRequest) -> Result<String, &'static str> {
|
||||
log::info!("Request: {:?}", request);
|
||||
match request.headers().get("user-token") {
|
||||
Some(token) => match token.to_str() {
|
||||
Ok(processed_password) => {
|
||||
log::info!("Token provided: {}", processed_password);
|
||||
Ok(String::from(processed_password))
|
||||
}
|
||||
Err(_processed_password) => Err("there was an error processing token"),
|
||||
Ok(processed_token) => Ok(String::from(processed_token)),
|
||||
Err(_) => Err("there was an error processing token"),
|
||||
},
|
||||
None => Err("there is no token"),
|
||||
}
|
||||
@@ -25,31 +36,51 @@ pub fn extract_header_token(request: &ServiceRequest) -> Result<String, &'static
|
||||
#[cfg(test)]
|
||||
mod processes_test {
|
||||
use actix_web::test::TestRequest;
|
||||
use diesel::prelude::*;
|
||||
|
||||
use crate::auth::jwt::JwtToken;
|
||||
use crate::database::establish_connection;
|
||||
use crate::test_helpers::{delete_user, insert_user};
|
||||
|
||||
use super::check_password;
|
||||
use super::check_token;
|
||||
|
||||
#[test]
|
||||
fn check_correct_password() {
|
||||
let password_string: String = JwtToken::encode(32);
|
||||
fn check_correct_token() {
|
||||
let mut connection = establish_connection();
|
||||
let user = insert_user(&mut connection, "secret");
|
||||
|
||||
let result = check_password(password_string);
|
||||
let token: String = JwtToken::encode(user.id, user.token_version);
|
||||
|
||||
match result {
|
||||
Ok(user_id) => assert_eq!(32, user_id),
|
||||
_ => panic!("Check correct password failed."),
|
||||
}
|
||||
let result = check_token(token);
|
||||
|
||||
assert_eq!(Ok(user.id), result);
|
||||
|
||||
delete_user(&mut connection, user.id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incorrect_check_password() {
|
||||
let password: String = String::from("test");
|
||||
fn revoked_token_is_rejected() {
|
||||
let mut connection = establish_connection();
|
||||
let user = insert_user(&mut connection, "secret");
|
||||
|
||||
match check_password(password) {
|
||||
Err(message) => assert_eq!("could not decode token", message),
|
||||
_ => panic!("check password should not be able to be decoded"),
|
||||
}
|
||||
// Token signed with the user's current version, then the version is bumped
|
||||
// (as logout would do), which must invalidate the previously issued token.
|
||||
let token: String = JwtToken::encode(user.id, user.token_version);
|
||||
diesel::update(crate::schema::users::table.find(user.id))
|
||||
.set(crate::schema::users::token_version.eq(user.token_version + 1))
|
||||
.execute(&mut connection)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(Err("token has been revoked"), check_token(token));
|
||||
|
||||
delete_user(&mut connection, user.id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incorrect_check_token() {
|
||||
let token: String = String::from("test");
|
||||
|
||||
assert_eq!(Err("could not decode token"), check_token(token));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user