Skip to main content

max / makenotwork

2.3 KB · 61 lines History Blame Raw
1 //! Delegated login ("Sign in with Makenot.work") — login page mode + the
2 //! authorize redirect. The full token exchange needs a live provider, so it's
3 //! exercised against prod manually; here we verify the client-side wiring.
4
5 use crate::harness::{BuildOptions, TestHarness};
6 use makenotwork::config::SsoConfig;
7
8 fn sso_opts() -> BuildOptions {
9 BuildOptions {
10 sso: Some(SsoConfig {
11 provider_url: "https://provider.example".to_string(),
12 client_id: "test-client-id".to_string(),
13 key: "test-sso-key".to_string(),
14 }),
15 ..Default::default()
16 }
17 }
18
19 #[tokio::test]
20 async fn sso_login_page_shows_provider_button() {
21 let mut h = TestHarness::build(sso_opts()).await;
22
23 let resp = h.client.get("/login").await;
24 assert_eq!(resp.status.as_u16(), 200, "login page should render");
25 assert!(
26 resp.text.contains("Sign in with Makenot"),
27 "SSO mode should show the provider button"
28 );
29 assert!(
30 !resp.text.contains(r#"name="password""#),
31 "SSO mode should not render the local password form"
32 );
33 }
34
35 #[tokio::test]
36 async fn sso_login_redirects_to_provider_authorize() {
37 let mut h = TestHarness::build(sso_opts()).await;
38
39 let resp = h.client.get("/sso/login").await;
40 assert!(resp.status.is_redirection(), "/sso/login should redirect, got {}", resp.status);
41 let loc = resp.headers.get("location").and_then(|v| v.to_str().ok()).unwrap_or("");
42 assert!(
43 loc.starts_with("https://provider.example/oauth/authorize"),
44 "should redirect to the provider authorize endpoint, got {loc}"
45 );
46 assert!(loc.contains("client_id=test-client-id"), "carries client_id: {loc}");
47 assert!(loc.contains("code_challenge_method=S256"), "uses PKCE S256: {loc}");
48 assert!(loc.contains("response_type=code"), "auth-code flow: {loc}");
49 assert!(loc.contains("redirect_uri="), "carries redirect_uri: {loc}");
50 }
51
52 #[tokio::test]
53 async fn login_page_default_uses_password_form() {
54 // Without SSO configured, the normal username/password form renders.
55 let mut h = TestHarness::new().await;
56 let resp = h.client.get("/login").await;
57 assert_eq!(resp.status.as_u16(), 200);
58 assert!(resp.text.contains(r#"name="password""#), "default mode shows password form");
59 assert!(!resp.text.contains("Sign in with Makenot"), "no SSO button by default");
60 }
61