Skip to main content

max / makenotwork

2.5 KB · 81 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!(
41 resp.status.is_redirection(),
42 "/sso/login should redirect, got {}",
43 resp.status
44 );
45 let loc = resp
46 .headers
47 .get("location")
48 .and_then(|v| v.to_str().ok())
49 .unwrap_or("");
50 assert!(
51 loc.starts_with("https://provider.example/oauth/authorize"),
52 "should redirect to the provider authorize endpoint, got {loc}"
53 );
54 assert!(
55 loc.contains("client_id=test-client-id"),
56 "carries client_id: {loc}"
57 );
58 assert!(
59 loc.contains("code_challenge_method=S256"),
60 "uses PKCE S256: {loc}"
61 );
62 assert!(loc.contains("response_type=code"), "auth-code flow: {loc}");
63 assert!(loc.contains("redirect_uri="), "carries redirect_uri: {loc}");
64 }
65
66 #[tokio::test]
67 async fn login_page_default_uses_password_form() {
68 // Without SSO configured, the normal username/password form renders.
69 let mut h = TestHarness::new().await;
70 let resp = h.client.get("/login").await;
71 assert_eq!(resp.status.as_u16(), 200);
72 assert!(
73 resp.text.contains(r#"name="password""#),
74 "default mode shows password form"
75 );
76 assert!(
77 !resp.text.contains("Sign in with Makenot"),
78 "no SSO button by default"
79 );
80 }
81