diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-12-27 19:55:10 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-12-27 19:58:45 -0500 |
commit | 21b7b57336cd3bf7bd328ada38c6069a48504f85 (patch) | |
tree | c0d47337f584403febcfc9ec365ea1ea810e782e /server/src/auth.rs | |
parent | 3418ebf4db2375e0dfe2343da57d674e1f4fd57f (diff) |
`cargo fmt`
Diffstat (limited to 'server/src/auth.rs')
-rw-r--r-- | server/src/auth.rs | 96 |
1 files changed, 60 insertions, 36 deletions
diff --git a/server/src/auth.rs b/server/src/auth.rs index a924f44..2831929 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -6,21 +6,27 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::{error::BridgeError, server::{ServerState, ServerContext}}; +use crate::{ + error::BridgeError, + server::{ServerContext, ServerState}, +}; use async_trait::async_trait; use axum::{ - extract::{FromRequestParts, State, FromRef}, - response::{IntoResponse, Response}, http::request::Parts, + extract::{FromRef, FromRequestParts, State}, + http::request::Parts, + response::{IntoResponse, Response}, }; use chrono::{DateTime, Utc}; use lru::LruCache; use openidconnect::{ - core::{CoreClient, CoreProviderMetadata, CoreResponseType, CoreUserInfoClaims}, + core::{ + CoreClient, CoreProviderMetadata, CoreResponseType, CoreUserInfoClaims, + }, reqwest::async_http_client, url::Url, - AccessToken, AccessTokenHash, AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, - CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse, RedirectUrl, RefreshToken, Scope, - TokenResponse, + AccessToken, AccessTokenHash, AuthenticationFlow, AuthorizationCode, + ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse, + RedirectUrl, RefreshToken, Scope, TokenResponse, }; use serde::{Deserialize, Serialize}; use sqlx::PgPool; @@ -62,7 +68,10 @@ impl AuthenticatedSession { #[async_trait] pub trait Authenticator { - async fn user_info(&self, session: &mut AuthenticatedSession) -> Result<String, BridgeError>; + async fn user_info( + &self, + session: &mut AuthenticatedSession, + ) -> Result<String, BridgeError>; async fn authenticate( &self, pool: &PgPool, @@ -121,14 +130,18 @@ impl OauthAuthenticator { redirect_uri: RedirectUrl, ) -> Self { // Use OpenID Connect Discovery to fetch the provider metadata. - let provider_metadata = CoreProviderMetadata::discover_async(issuer_url, async_http_client) - .await - .unwrap(); - - let client = - CoreClient::from_provider_metadata(provider_metadata, client_id, Some(client_secret)) - // Set the URL the user will be redirected to after the authorization process. - .set_redirect_uri(redirect_uri); + let provider_metadata = + CoreProviderMetadata::discover_async(issuer_url, async_http_client) + .await + .unwrap(); + + let client = CoreClient::from_provider_metadata( + provider_metadata, + client_id, + Some(client_secret), + ) + // Set the URL the user will be redirected to after the authorization process. + .set_redirect_uri(redirect_uri); Self { db, @@ -168,9 +181,12 @@ impl OauthAuthenticator { debug!("Got new token: {new_token:#?}"); // TODO: Validate token? if let Some(expires_in) = new_token.expires_in() { - session.expiration = refresh_start + chrono::Duration::from_std(expires_in)?; + session.expiration = + refresh_start + chrono::Duration::from_std(expires_in)?; } else { - error!("Token is missing expiration! Will refresh token every time."); + error!( + "Token is missing expiration! Will refresh token every time." + ); } if let Some(refresh_token) = new_token.refresh_token() { session.refresh_token = refresh_token.clone(); @@ -202,7 +218,10 @@ impl Authenticator for OauthAuthenticator { (user_id, auth_url) } - async fn user_info(&self, session: &mut AuthenticatedSession) -> Result<String, BridgeError> { + async fn user_info( + &self, + session: &mut AuthenticatedSession, + ) -> Result<String, BridgeError> { self.maybe_refresh_token(session).await?; let user_info: CoreUserInfoClaims = self .client @@ -225,12 +244,10 @@ impl Authenticator for OauthAuthenticator { auth_params: HashMap<String, String>, ) -> Result<AuthenticatedSession, BridgeError> { // TODO: If the token is missing from the cache, client should retry logging in. - let state = self - .login_cache - .lock() - .unwrap() - .pop(&session_id) - .ok_or(BridgeError::InvalidRequest("token missing".to_string()))?; + let state = + self.login_cache.lock().unwrap().pop(&session_id).ok_or( + BridgeError::InvalidRequest("token missing".to_string()), + )?; if Some(state.csrf_token.secret()) != auth_params.get("state") { return Err(BridgeError::InvalidRequest( "token validation failed".to_string(), @@ -254,12 +271,15 @@ impl Authenticator for OauthAuthenticator { let id_token = token.id_token().ok_or(BridgeError::InvalidRequest( "Server did not return an IdToken".to_string(), ))?; - let claims = id_token.claims(&self.client.id_token_verifier(), &state.nonce)?; + let claims = + id_token.claims(&self.client.id_token_verifier(), &state.nonce)?; // Verify access token hash. if let Some(expected_access_token_hash) = claims.access_token_hash() { - let actual_access_token_hash = - AccessTokenHash::from_token(token.access_token(), &id_token.signing_alg()?)?; + let actual_access_token_hash = AccessTokenHash::from_token( + token.access_token(), + &id_token.signing_alg()?, + )?; if actual_access_token_hash != *expected_access_token_hash { return Err(BridgeError::InvalidRequest( "Invalid access token".to_string(), @@ -274,9 +294,9 @@ impl Authenticator for OauthAuthenticator { ))); } - let refresh_token = token - .refresh_token() - .ok_or(BridgeError::Internal("Expected refresh token".to_string()))?; + let refresh_token = token.refresh_token().ok_or( + BridgeError::Internal("Expected refresh token".to_string()), + )?; let mut session = AuthenticatedSession { player_id: claims.subject().to_string(), @@ -371,12 +391,13 @@ pub async fn fetch_authenticated_session( impl<S> FromRequestParts<S> for AuthenticatedSession where S: Send + Sync, - Arc<ServerContext>: FromRef<S> + Arc<ServerContext>: FromRef<S>, { type Rejection = Response; async fn from_request_parts( - parts: &mut Parts, state: &S + parts: &mut Parts, + state: &S, ) -> Result<Self, Self::Rejection> { let cookies = Cookies::from_request_parts(parts, state) .await @@ -395,9 +416,12 @@ where } Ok(s) => s, }; - let session = match crate::auth::fetch_authenticated_session(&state.db, &session_id) - .await - .map_err(|e| e.into_response())? + let session = match crate::auth::fetch_authenticated_session( + &state.db, + &session_id, + ) + .await + .map_err(|e| e.into_response())? { None => return Err(BridgeError::NotLoggedIn.into_response()), Some(v) => v, |