From 2f35026022827cd86615135c6397f03b74fe1b46 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Fri, 25 Nov 2022 14:09:09 -0500 Subject: Hook up fake authenticator backend for testing --- server/src/auth.rs | 20 +++++++++++++++- server/src/error.rs | 3 +++ server/src/fake_auth.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++----- server/src/main.rs | 33 ++++++++++++++++++++++---- 4 files changed, 107 insertions(+), 11 deletions(-) (limited to 'server/src') diff --git a/server/src/auth.rs b/server/src/auth.rs index 7222199..fc0de62 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -42,6 +42,24 @@ pub struct AuthenticatedSession { refresh_token: RefreshToken, } +impl AuthenticatedSession { + pub fn new( + player_id: String, + session_id: SessionId, + expiration: DateTime, + access_token: AccessToken, + refresh_token: RefreshToken, + ) -> Self { + Self { + player_id, + session_id, + expiration, + access_token, + refresh_token, + } + } +} + #[async_trait] pub trait Authenticator { async fn user_info(&self, session: &mut AuthenticatedSession) -> Result; @@ -273,7 +291,7 @@ impl Authenticator for OauthAuthenticator { } } -async fn store_authenticated_session( +pub async fn store_authenticated_session( pool: &PgPool, session: &mut AuthenticatedSession, ) -> Result<(), BridgeError> { diff --git a/server/src/error.rs b/server/src/error.rs index 611d8e4..344624c 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -63,6 +63,9 @@ pub enum BridgeError { impl BridgeError { pub fn as_rejection(&self) -> (http::StatusCode, String) { 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 5ef9cc8..d19d858 100644 --- a/server/src/fake_auth.rs +++ b/server/src/fake_auth.rs @@ -1,13 +1,31 @@ -use std::collections::HashMap; +use std::{ + collections::HashMap, + env, + sync::{Arc, Mutex}, +}; use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use openidconnect::{RefreshToken, AccessToken}; +use reqwest::Url; +use tracing::info; use crate::{ - auth::{AuthenticatedSession, Authenticator, SessionId}, + auth::{AuthenticatedSession, Authenticator, SessionId, store_authenticated_session}, error::{self, BridgeError}, }; -pub struct FakeAuthenticator {} +pub struct FakeAuthenticator { + login_cache: Arc>>>, +} + +impl FakeAuthenticator { + pub fn new() -> Self { + Self { + login_cache: Arc::new(Mutex::new(HashMap::new())), + } + } +} #[async_trait] impl Authenticator for FakeAuthenticator { @@ -15,7 +33,15 @@ impl Authenticator for FakeAuthenticator { &self, session: &mut AuthenticatedSession, ) -> Result { - Err(BridgeError::NotLoggedIn) + let user: String = self + .login_cache + .lock() + .unwrap() + .get(&session.session_id) + .and_then(|u| u.as_ref()) + .ok_or(BridgeError::NotLoggedIn)? + .clone(); + Ok(user) } async fn authenticate( @@ -24,10 +50,34 @@ impl Authenticator for FakeAuthenticator { session_id: SessionId, auth_params: HashMap, ) -> Result { - Err(BridgeError::Internal("not implemented".to_string())) + let user = auth_params + .get("user") + .ok_or(BridgeError::Internal("missing 'user' param".to_string()))?; + self.login_cache + .lock() + .unwrap() + .insert(session_id.clone(), Some(user.clone())); + + let mut session = AuthenticatedSession::new( + user.clone(), + session_id, + Utc::now() + chrono::Duration::days(10000), + AccessToken::new("fake".to_string()), + RefreshToken::new("fake".to_string()), + ); + + store_authenticated_session(pool, &mut session).await?; + Ok(session) } async fn get_login_url(&self) -> (SessionId, reqwest::Url) { - todo!() + let auth_url = + Url::parse(&format!("{}/api/fake_login", env::var("APP_URL").unwrap())).unwrap(); + let user_id = SessionId::new(); + self.login_cache + .lock() + .unwrap() + .insert(user_id.clone(), None); + (user_id, auth_url) } } diff --git a/server/src/main.rs b/server/src/main.rs index 39425d6..ca65d86 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,11 +5,12 @@ use uuid::Uuid; use auth::AuthenticatedSession; use axum::{ extract::{Extension, Path, Query}, - response::Redirect, + response::{Html, Redirect}, routing::{delete, get, post}, Json, Router, }; -use protocol::{bridge_engine::{self, TableView, Player}, Table, UserInfo}; +use protocol::{Table, UserInfo}; +use protocol::bridge_engine::{TableView, Player}; use server::ContextExtension; use tower_cookies::{Cookie, CookieManagerLayer, Cookies}; use tower_http::trace::TraceLayer; @@ -19,6 +20,7 @@ mod auth; mod error; mod play; mod server; +#[cfg(debug_assertions)] mod fake_auth; use crate::{ auth::{OauthAuthenticator, SessionId}, @@ -39,7 +41,7 @@ async fn create_default_authenticator(db_pool: &PgPool) -> Box Box { const FAKE_AUTHENTICATOR: &str = "fake"; if std::env::var("AUTHENTICATOR").unwrap_or("".to_string()) == FAKE_AUTHENTICATOR { - Box::new(fake_auth::FakeAuthenticator {}) + Box::new(fake_auth::FakeAuthenticator::new()) } else { create_default_authenticator(db_pool).await } @@ -91,7 +93,13 @@ async fn main() { db: db_pool, }); - let app = Router::new() + let app = Router::new(); + + #[cfg(debug_assertions)] + let app = app + .route("/api/fake_login", get(fake_login)); + + let app = app .route("/api/user/info", get(user_info)) .route("/api/table", post(create_table)) .route("/api/table", delete(leave_table)) @@ -109,6 +117,23 @@ async fn main() { .unwrap(); } +#[cfg(debug_assertions)] +async fn fake_login() -> Html<&'static str> { + use axum::response::Html; + + Html(r#" + + + +

Log in as:

+ + + + "#) +} + async fn get_table_view( _session: AuthenticatedSession, extension: ContextExtension, -- cgit v1.2.3