//! Delegated login ("Sign in with Makenot.work") — login page mode + the //! authorize redirect. The full token exchange needs a live provider, so it's //! exercised against prod manually; here we verify the client-side wiring. use crate::harness::{BuildOptions, TestHarness}; use makenotwork::config::SsoConfig; fn sso_opts() -> BuildOptions { BuildOptions { sso: Some(SsoConfig { provider_url: "https://provider.example".to_string(), client_id: "test-client-id".to_string(), key: "test-sso-key".to_string(), }), ..Default::default() } } #[tokio::test] async fn sso_login_page_shows_provider_button() { let mut h = TestHarness::build(sso_opts()).await; let resp = h.client.get("/login").await; assert_eq!(resp.status.as_u16(), 200, "login page should render"); assert!( resp.text.contains("Sign in with Makenot"), "SSO mode should show the provider button" ); assert!( !resp.text.contains(r#"name="password""#), "SSO mode should not render the local password form" ); } #[tokio::test] async fn sso_login_redirects_to_provider_authorize() { let mut h = TestHarness::build(sso_opts()).await; let resp = h.client.get("/sso/login").await; assert!(resp.status.is_redirection(), "/sso/login should redirect, got {}", resp.status); let loc = resp.headers.get("location").and_then(|v| v.to_str().ok()).unwrap_or(""); assert!( loc.starts_with("https://provider.example/oauth/authorize"), "should redirect to the provider authorize endpoint, got {loc}" ); assert!(loc.contains("client_id=test-client-id"), "carries client_id: {loc}"); assert!(loc.contains("code_challenge_method=S256"), "uses PKCE S256: {loc}"); assert!(loc.contains("response_type=code"), "auth-code flow: {loc}"); assert!(loc.contains("redirect_uri="), "carries redirect_uri: {loc}"); } #[tokio::test] async fn login_page_default_uses_password_form() { // Without SSO configured, the normal username/password form renders. let mut h = TestHarness::new().await; let resp = h.client.get("/login").await; assert_eq!(resp.status.as_u16(), 200); assert!(resp.text.contains(r#"name="password""#), "default mode shows password form"); assert!(!resp.text.contains("Sign in with Makenot"), "no SSO button by default"); }