TestOIDCSkipIssuer verifies coderd can run without checking the issuer url in the OIDC exchange. This means the CODER_OIDC_ISSUER_URL does not need to match the id_token `iss` field, or the value returned in the well-known config. So this test has: - OIDC at http://localhost: - well-known con
(t *testing.T)
| 2609 | // TestOIDCDomainErrorMessage ensures that when a user with an unauthorized domain |
| 2610 | // attempts to login, the error message doesn't expose the list of authorized domains. |
| 2611 | func TestOIDCDomainErrorMessage(t *testing.T) { |
| 2612 | t.Parallel() |
| 2613 | |
| 2614 | allowedDomains := []string{"allowed1.com", "allowed2.org", "company.internal"} |
| 2615 | |
| 2616 | setup := func() (*oidctest.FakeIDP, *codersdk.Client) { |
| 2617 | fake := oidctest.NewFakeIDP(t, oidctest.WithServing()) |
| 2618 | |
| 2619 | cfg := fake.OIDCConfig(t, nil, func(cfg *coderd.OIDCConfig) { |
| 2620 | cfg.EmailDomain = allowedDomains |
| 2621 | cfg.AllowSignups = true |
| 2622 | }) |
| 2623 | |
| 2624 | client := coderdtest.New(t, &coderdtest.Options{ |
| 2625 | OIDCConfig: cfg, |
| 2626 | }) |
| 2627 | return fake, client |
| 2628 | } |
| 2629 | |
| 2630 | // Test case 1: Email domain not in allowed list |
| 2631 | t.Run("ErrorMessageOmitsDomains", func(t *testing.T) { |
| 2632 | t.Parallel() |
| 2633 | |
| 2634 | fake, client := setup() |
| 2635 | |
| 2636 | // Prepare claims with email from unauthorized domain |
| 2637 | claims := jwt.MapClaims{ |
| 2638 | "email": "user@unauthorized.com", |
| 2639 | "email_verified": true, |
| 2640 | "sub": uuid.NewString(), |
| 2641 | } |
| 2642 | |
| 2643 | _, resp := fake.AttemptLogin(t, client, claims) |
| 2644 | defer resp.Body.Close() |
| 2645 | |
| 2646 | require.Equal(t, http.StatusForbidden, resp.StatusCode) |
| 2647 | |
| 2648 | data, err := io.ReadAll(resp.Body) |
| 2649 | require.NoError(t, err) |
| 2650 | |
| 2651 | require.Contains(t, string(data), "is not from an authorized domain") |
| 2652 | require.Contains(t, string(data), "Please contact your administrator") |
| 2653 | // Verify the response is a rendered HTML error page, not raw JSON. |
| 2654 | require.Equal(t, "text/html; charset=utf-8", resp.Header.Get("Content-Type")) |
| 2655 | require.Contains(t, string(data), "<!doctype html>") |
| 2656 | require.Contains(t, string(data), "Unauthorized email") |
| 2657 | require.Contains(t, string(data), "Back to login") |
| 2658 | require.NotContains(t, string(data), `"message"`) |
| 2659 | |
| 2660 | for _, domain := range allowedDomains { |
| 2661 | require.NotContains(t, string(data), domain) |
| 2662 | } |
| 2663 | }) |
| 2664 | |
| 2665 | // Test case 2: Malformed email without @ symbol |
| 2666 | t.Run("MalformedEmailErrorOmitsDomains", func(t *testing.T) { |
| 2667 | t.Parallel() |
| 2668 |
nothing calls this directly
no test coverage detected