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 | |
parent | 3418ebf4db2375e0dfe2343da57d674e1f4fd57f (diff) |
`cargo fmt`
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/auth.rs | 96 | ||||
-rw-r--r-- | server/src/error.rs | 11 | ||||
-rw-r--r-- | server/src/fake_auth.rs | 14 | ||||
-rw-r--r-- | server/src/main.rs | 2 | ||||
-rw-r--r-- | server/src/play.rs | 19 |
5 files changed, 90 insertions, 52 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, diff --git a/server/src/error.rs b/server/src/error.rs index b6a7c4d..7eb5fa2 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -2,10 +2,13 @@ use axum::{ http::{self, StatusCode}, response::IntoResponse, }; -use openidconnect::{core::CoreErrorResponseType, ClaimsVerificationError, StandardErrorResponse}; +use openidconnect::{ + core::CoreErrorResponseType, ClaimsVerificationError, StandardErrorResponse, +}; use tracing::error; -type UserInfoError = openidconnect::UserInfoError<openidconnect::reqwest::Error<reqwest::Error>>; +type UserInfoError = + openidconnect::UserInfoError<openidconnect::reqwest::Error<reqwest::Error>>; type RequestTokenError = openidconnect::RequestTokenError< openidconnect::reqwest::Error<reqwest::Error>, @@ -36,7 +39,7 @@ pub enum BridgeError { NotLoggedIn, #[error("Anyhow error")] - AnyhowError(#[from]anyhow::Error), + AnyhowError(#[from] anyhow::Error), #[error("Authentication error")] SigningFailed(#[from] openidconnect::SigningError), @@ -68,7 +71,7 @@ impl BridgeError { match self { BridgeError::NotLoggedIn => { (StatusCode::UNAUTHORIZED, format!("Must be logged in")) - }, + } BridgeError::OpenidRequestTokenError(_) => { (StatusCode::UNAUTHORIZED, format!("Error fetching token")) } diff --git a/server/src/fake_auth.rs b/server/src/fake_auth.rs index c0574af..6a3ff2c 100644 --- a/server/src/fake_auth.rs +++ b/server/src/fake_auth.rs @@ -6,11 +6,14 @@ use std::{ use async_trait::async_trait; use chrono::Utc; -use openidconnect::{RefreshToken, AccessToken}; +use openidconnect::{AccessToken, RefreshToken}; use reqwest::Url; use crate::{ - auth::{AuthenticatedSession, Authenticator, SessionId, store_authenticated_session}, + auth::{ + store_authenticated_session, AuthenticatedSession, Authenticator, + SessionId, + }, error::{self, BridgeError}, }; @@ -70,8 +73,11 @@ impl Authenticator for FakeAuthenticator { } async fn get_login_url(&self) -> (SessionId, reqwest::Url) { - let auth_url = - Url::parse(&format!("{}/api/fake_login", env::var("APP_URL").unwrap())).unwrap(); + let auth_url = Url::parse(&format!( + "{}/api/fake_login", + env::var("APP_URL").unwrap() + )) + .unwrap(); let user_id = SessionId::new(); self.login_cache .lock() diff --git a/server/src/main.rs b/server/src/main.rs index c0ec4cb..9034b67 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -61,7 +61,7 @@ async fn create_authenticator( async fn create_authenticator( db_pool: &PgPool, ) -> Box<dyn Authenticator + Send + Sync> { - create_default_authenticator(db_pool) + create_default_authenticator(db_pool).await } #[tokio::main] diff --git a/server/src/play.rs b/server/src/play.rs index 68ea94b..d15d64c 100644 --- a/server/src/play.rs +++ b/server/src/play.rs @@ -157,9 +157,7 @@ impl<J: Journal<TableUpdate>> Table<J> { pub fn result(&self) -> Result<&GameResult, BridgeError> { match &self.state { TableState::Result(r) => Ok(r), - _ => Err(BridgeError::InvalidRequest( - "no result".to_string(), - )), + _ => Err(BridgeError::InvalidRequest("no result".to_string())), } } @@ -183,9 +181,13 @@ impl<J: Journal<TableUpdate>> Table<J> { let dealer = match &self.state { TableState::Unknown => random(), TableState::Game(g) => g.dealer(), - TableState::Result(_) => random(), // TODO: We should know the dealer here. + TableState::Result(_) => random(), // TODO: We should know the dealer here. }; - self.insert_and_apply(TableUpdate::NewDeal { deal: random(), dealer: dealer.next() }).await + self.insert_and_apply(TableUpdate::NewDeal { + deal: random(), + dealer: dealer.next(), + }) + .await } async fn insert_and_apply( @@ -216,7 +218,7 @@ impl<J: Journal<TableUpdate>> Table<J> { TableUpdate::Play(card) => { self.state = self.game()?.clone().play(card)?.into(); Ok(()) - }, + } } } @@ -292,7 +294,10 @@ pub async fn advance_play<J: Journal<TableUpdate>>( #[cfg(test)] mod test { - use protocol::{bridge_engine::{Raise, ContractLevel}, card::Suit}; + use protocol::{ + bridge_engine::{ContractLevel, Raise}, + card::Suit, + }; use serde_json::json; use tracing::info; |