-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initialize JWT and protected routes (#4)
* Add jwt module * Add axum_extras and jsonwebtoken packages * Return user_id when inserting user * Add new middleware modules * Add new user route * Return JWT when registering user * Add protected /user/me route * Fix error conversion for bad encoding
- Loading branch information
1 parent
ca10c87
commit 9fb85d6
Showing
10 changed files
with
498 additions
and
40 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use chrono::{Duration, Utc}; | ||
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Serialize)] | ||
pub enum JWTError { | ||
DecodingError, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct Claims { | ||
pub exp: usize, // Expiry time of the token | ||
pub iat: usize, // Issued at time of the token | ||
pub user_id: String, // User ID associated with the token | ||
} | ||
|
||
/// Gets the JWT_SECRET from the environment variables and converts to bytes | ||
fn get_secret() -> Vec<u8> { | ||
std::env::var("JWT_SECRET") | ||
.expect("JWT_SECRET must be set") | ||
.into_bytes() | ||
} | ||
|
||
/// Creates a JWT token containing the given user_id | ||
pub fn encode_jwt(user_id: &str) -> Result<String, jsonwebtoken::errors::Error> { | ||
let jwt_secret = get_secret(); | ||
let now = Utc::now(); | ||
let expire: chrono::TimeDelta = Duration::hours(24); | ||
let exp: usize = (now + expire).timestamp() as usize; | ||
let iat: usize = now.timestamp() as usize; | ||
let claim = Claims { | ||
iat, | ||
exp, | ||
user_id: user_id.to_owned(), | ||
}; | ||
|
||
encode( | ||
&Header::default(), | ||
&claim, | ||
&EncodingKey::from_secret(&jwt_secret), | ||
) | ||
} | ||
|
||
/// Decodes a JWT token | ||
pub fn decode_jwt(jwt_token: String) -> Result<TokenData<Claims>, JWTError> { | ||
let jwt_secret = get_secret(); | ||
decode( | ||
&jwt_token, | ||
&DecodingKey::from_secret(&jwt_secret), | ||
&Validation::default(), | ||
) | ||
.map_err(|_| JWTError::DecodingError) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use crate::jwt::decode_jwt; | ||
use axum::{ | ||
body::Body, | ||
extract::Request, | ||
http::{self, Response, StatusCode}, | ||
middleware::Next, | ||
}; | ||
|
||
/// A middleware for checking the validity of the JWT token | ||
pub async fn auth_middleware(mut req: Request, next: Next) -> Result<Response<Body>, StatusCode> { | ||
// Get the auth header from the request | ||
let raw_auth_header = req.headers_mut().get(http::header::AUTHORIZATION); | ||
// Pull the full header string out of the header | ||
let auth_header = match raw_auth_header { | ||
Some(header) => header.to_str().map_err(|_| StatusCode::BAD_REQUEST), | ||
None => return Err(StatusCode::BAD_REQUEST), | ||
}?; | ||
// Full header is expected to be `Bearer token`, split by whitespace | ||
let mut split_header = auth_header.split_whitespace(); | ||
// It _should_ only be two values, we care about the token value | ||
let (_bearer, token) = (split_header.next(), split_header.next()); | ||
let jwt_token = token.expect("Could not parse token").to_owned(); | ||
let token_claims = match decode_jwt(jwt_token) { | ||
Ok(token) => token, | ||
Err(jwt_err) => return Err(StatusCode::UNAUTHORIZED), | ||
}; | ||
// TODO: Using the token_claims, get the User and add it to the request for downstream usage | ||
Ok(next.run(req).await) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod auth; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
pub mod auth; | ||
pub mod user; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/// Gets a user by their ID | ||
pub async fn get_user() { | ||
todo!("Fetch user information") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters