use std::{env, sync::Arc}; use axum::{extract::{FromRequest, Extension}, routing::get, Json, Router, http::{Request, request::Parts}, body::Body}; use openidconnect::{ core::{CoreClient, CoreProviderMetadata, CoreResponseType}, reqwest::async_http_client, AccessTokenHash, AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, url::Url, }; use protocol::UserInfo; use tower_http::trace::TraceLayer; use tower_cookies::{Cookie, CookieManagerLayer, Cookies}; use tracing::{info, trace}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; mod auth; use crate::auth::Authenticator; struct ServerContext { pub app_url: String, pub authenticator: Authenticator, } type ContextExtension = Extension>; async fn keycloak_client( issuer_url: IssuerUrl, client_id: ClientId, client_secret: ClientSecret, redirect_uri: RedirectUrl, ) -> CoreClient { // // 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 ); client } #[tokio::main] async fn main() { dotenv::dotenv().ok(); tracing_subscriber::registry() .with(tracing_subscriber::EnvFilter::new( std::env::var("RUST_LOG").unwrap_or_else(|_| "".into()), )) .with(tracing_subscriber::fmt::layer()) .init(); let bind_address = env::var("BIND_ADDRESS").unwrap(); info!("Starting server on {}", bind_address); let app_url = env::var("APP_URL").unwrap(); let state = Arc::new(ServerContext { app_url: app_url, authenticator: Authenticator::from_env().await, }); let app = Router::new() .route("/api/user/info", get(user_info)) .route("/api/get_login_url", get(get_login_url)) .route(auth::LOGIN_CALLBACK, get(login_callback)) .layer(CookieManagerLayer::new()) .layer(Extension(state)) .layer(TraceLayer::new_for_http()); axum::Server::bind(&bind_address.parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); } async fn user_info() -> Json> { Json(None) } async fn login_callback(mut req: Parts) -> &'static str { info!("{req:?}"); "hello" } async fn get_login_url(extension: ContextExtension) -> Json { let (user_id, auth_url) = extension.authenticator.get_login_url().await; trace!("Creating auth url for {user_id:?}"); // cookies.add(Cookie::new("user-id", serde_json::to_string(user_id))); Json(auth_url) }