summaryrefslogtreecommitdiffstats
path: root/src/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/auth.rs')
-rw-r--r--src/auth.rs40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/auth.rs b/src/auth.rs
index 09494fb..6bf0ddf 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -1,5 +1,10 @@
use argon2::{Argon2, PasswordHash, PasswordVerifier};
-use axum::extract::State;
+use axum::{
+ async_trait,
+ extract::{FromRequestParts, State},
+ http::request::Parts,
+ RequestPartsExt,
+};
use axum_extra::{
headers::{authorization::Basic, Authorization},
TypedHeader,
@@ -28,18 +33,16 @@ pub fn router() -> axum::Router<AppState> {
pub async fn issue(
State(state): State<AppState>,
- TypedHeader(Authorization(basic)): TypedHeader<Authorization<Basic>>,
+ Account { id, password }: Account,
) -> Result<(AccessClaims, RefreshClaims), Error> {
- let uuid = Uuid::try_parse(basic.username())?;
-
- let p: String = sqlx::query_scalar!("SELECT password_hash FROM credential WHERE id = $1", uuid)
+ let p: String = sqlx::query_scalar!("SELECT password_hash FROM credential WHERE id = $1", id)
.fetch_optional(&state.pool)
.await?
.ok_or(Error::LoginInvalid)?;
- Argon2::default().verify_password(basic.password().as_bytes(), &PasswordHash::new(&p)?)?;
+ Argon2::default().verify_password(password.as_bytes(), &PasswordHash::new(&p)?)?;
- let refresh = RefreshClaims::issue(uuid);
+ let refresh = RefreshClaims::issue(id);
let access = refresh.refresh();
Ok((access, refresh))
}
@@ -48,6 +51,27 @@ pub async fn refresh(claims: RefreshClaims) -> AccessClaims {
claims.refresh()
}
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Account {
+ pub id: Uuid,
+ pub password: String,
+}
+
+#[async_trait]
+impl FromRequestParts<AppState> for Account {
+ type Rejection = Error;
+
+ async fn from_request_parts(parts: &mut Parts, _: &AppState) -> Result<Self, Self::Rejection> {
+ let TypedHeader(Authorization(basic)) =
+ parts.extract::<TypedHeader<Authorization<Basic>>>().await?;
+
+ Ok(Self {
+ id: Uuid::try_parse(basic.username())?,
+ password: basic.password().to_string(),
+ })
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -57,7 +81,7 @@ mod tests {
http::{header::AUTHORIZATION, Request, StatusCode},
Router,
};
- use axum_extra::headers::authorization::Credentials;
+ use axum_extra::headers::{authorization::Credentials, Authorization};
use sqlx::PgPool;
use tower::ServiceExt;