use axum::{Json, http::StatusCode}; use serde_json::{Value, json}; use std::str::FromStr; use axum::{ Router, error_handling::HandleErrorLayer, http::Uri, response::IntoResponse, routing::{any, get}, }; use axum_oidc::handle_oidc_redirect; use axum_oidc::{ EmptyAdditionalClaims, OidcAuthLayer, OidcClaims, OidcClient, OidcLoginLayer, OidcRpInitiatedLogout, error::MiddlewareError, }; use base64::{ Engine, alphabet::STANDARD, engine::{GeneralPurpose, GeneralPurposeConfig}, }; use clap::Command; use dioxus::prelude::*; use mize::Mize; use mize::MizeResult; use openidconnect::Scope; use openidconnect::{ClientId, ClientSecret, IssuerUrl}; use tower::ServiceBuilder; use tower_sessions::{ Expiry, MemoryStore, SessionManagerLayer, cookie::{SameSite, time::Duration}, }; pub async fn server(mize: &mut Mize) -> MizeResult<()> { dioxus::logger::initialize_default(); let listen_addr = mize.get_config("server.listen_addr")?.value_string()?; let port = mize.get_config("server.port")?.value_string()?; let issuer = mize.get_config("auth.issuer")?.value_string()?; let client_id = mize.get_config("auth.client_id")?.value_string()?; let client_secret = mize.get_config("auth.client_secret")?.value_string()?; let url = mize.get_config("web.url")?.value_string()?; let redirect_url = format!("{url}/oidc"); let session_store = MemoryStore::default(); let session_layer = SessionManagerLayer::new(session_store) .with_secure(false) .with_same_site(SameSite::Lax) .with_expiry(Expiry::OnInactivity(Duration::seconds(120))); let oidc_login_service = ServiceBuilder::new() .layer(HandleErrorLayer::new(|e: MiddlewareError| async { dbg!(&e); e.into_response() })) .layer(OidcLoginLayer::::new()); let oidc_client = OidcClient::::builder() .with_default_http_client() .with_redirect_url(Uri::from_str(redirect_url.as_str())?) .with_client_id(ClientId::new(client_id)) .add_scope(Scope::new("profile".into())) .add_scope(Scope::new("email".into())) // Optional: add untrusted audiences. If the `aud` claim contains any of these audiences, the token is rejected. //.add_untrusted_audience(Audience::new("123456789".to_string())) .with_client_secret(ClientSecret::new(client_secret)) .discover(IssuerUrl::new(issuer.into()).expect("Invalid IssuerUrl")) .await .unwrap() .build(); let oidc_auth_service = ServiceBuilder::new() .layer(HandleErrorLayer::new(|e: MiddlewareError| async { dbg!(&e); e.into_response() })) .layer(OidcAuthLayer::new(oidc_client)); let app = Router::new() // private routes .route("/foo", get(authenticated)) .route("/logout", get(logout)) .layer(oidc_login_service) .route("/bar", get(maybe_authenticated)) .route("/oidc", any(handle_oidc_redirect::)) .layer(oidc_auth_service) .layer(session_layer) .layer(tower_http::trace::TraceLayer::new_for_http()) // // not authenticated routes .route("/", get(mize_main_page)) .route("/oidc_display_code_and_state", get(display_code_and_state)) tracing::info!("Running on http://{listen_addr}:{port}"); let listener = tokio::net::TcpListener::bind(format!("{listen_addr}:{port}")) .await .unwrap(); axum::serve(listener, app.into_make_service()) .await .unwrap(); Ok(()) } fn mize_main_page() -> impl IntoResponse { }