JWT's for login and signup
This commit is contained in:
28
Cargo.lock
generated
28
Cargo.lock
generated
@@ -74,8 +74,11 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"hmac",
|
||||||
|
"jwt",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower",
|
||||||
@@ -214,6 +217,12 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
@@ -835,6 +844,21 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jwt"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"crypto-common",
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -1649,7 +1673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a"
|
checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1693,7 +1717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8"
|
checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.22.1",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
@@ -24,3 +24,6 @@ uuid = "1.11.0"
|
|||||||
chrono = "0.4.39"
|
chrono = "0.4.39"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
argon2 = "0.5.3"
|
argon2 = "0.5.3"
|
||||||
|
jwt = "0.16.0"
|
||||||
|
hmac = "0.12.1"
|
||||||
|
sha2 = "0.10.8"
|
||||||
|
|||||||
@@ -56,10 +56,11 @@ async fn index() -> &'static str {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
let db = db::db().await?;
|
|
||||||
let state = state::AppState { db: Arc::new(db) };
|
|
||||||
|
|
||||||
let port: u16 = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string()).parse()?;
|
let port: u16 = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string()).parse()?;
|
||||||
|
let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "secret".to_string());
|
||||||
|
|
||||||
|
let db = db::db().await?;
|
||||||
|
let state = state::AppState { db: Arc::new(db), jwt_secret };
|
||||||
|
|
||||||
let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
|
let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
|
||||||
.routes(routes!(health_check))
|
.routes(routes!(health_check))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::sync::Arc;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub db: DB,
|
pub db: DB,
|
||||||
|
pub jwt_secret: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DB = Arc<sqlx::Pool<sqlx::Postgres>>;
|
pub type DB = Arc<sqlx::Pool<sqlx::Postgres>>;
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ use argon2::{
|
|||||||
password_hash::{PasswordHash, PasswordVerifier},
|
password_hash::{PasswordHash, PasswordVerifier},
|
||||||
Argon2,
|
Argon2,
|
||||||
};
|
};
|
||||||
|
use hmac::{Hmac, Mac};
|
||||||
|
use jwt::SignWithKey;
|
||||||
|
use sha2::Sha256;
|
||||||
use sqlx::query;
|
use sqlx::query;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, ToSchema)]
|
#[derive(Serialize, Deserialize, ToSchema)]
|
||||||
pub struct LoginBody {
|
pub struct LoginBody {
|
||||||
@@ -36,10 +40,14 @@ pub async fn login(
|
|||||||
return Err(AppError::Error(Errors::Unauthorized));
|
return Err(AppError::Error(Errors::Unauthorized));
|
||||||
}
|
}
|
||||||
|
|
||||||
// technically I should be using a JWT and returning it to the client
|
let key: Hmac<Sha256> =
|
||||||
// since this will be a mobile app.
|
Hmac::new_from_slice(state.jwt_secret.as_bytes()).context("Failed to create HMAC")?;
|
||||||
|
let mut claims = BTreeMap::new();
|
||||||
|
claims.insert("id", user.id.to_string());
|
||||||
|
claims.insert("username", user.username);
|
||||||
|
claims.insert("real_name", user.real_name);
|
||||||
|
claims.insert("email", user.email);
|
||||||
|
let token_str = claims.sign_with_key(&key).context("Failed to sign JWT")?;
|
||||||
|
|
||||||
// let jwt = ...
|
Ok(token_str)
|
||||||
|
|
||||||
Ok(user.id.to_string())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ use argon2::{
|
|||||||
Argon2,
|
Argon2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use hmac::{Hmac, Mac};
|
||||||
|
use jwt::SignWithKey;
|
||||||
|
use sha2::Sha256;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, ToSchema)]
|
#[derive(Serialize, Deserialize, ToSchema)]
|
||||||
pub struct SignupBody {
|
pub struct SignupBody {
|
||||||
real_name: String,
|
real_name: String,
|
||||||
@@ -40,5 +45,14 @@ pub async fn signup(
|
|||||||
.fetch_one(&*state.db)
|
.fetch_one(&*state.db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(user.id.to_string())
|
let key: Hmac<Sha256> =
|
||||||
|
Hmac::new_from_slice(state.jwt_secret.as_bytes()).context("Failed to create HMAC")?;
|
||||||
|
let mut claims = BTreeMap::new();
|
||||||
|
claims.insert("id", user.id.to_string());
|
||||||
|
claims.insert("username", user.username);
|
||||||
|
claims.insert("real_name", user.real_name);
|
||||||
|
claims.insert("email", user.email);
|
||||||
|
let token_str = claims.sign_with_key(&key).context("Failed to sign JWT")?;
|
||||||
|
|
||||||
|
Ok(token_str)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user