Skip to content

fix(auth): bypass OIDC challenge when placeholder Auth0 config is active (#396)#397

Merged
mpaulosky merged 3 commits into
devfrom
squad/396-fix-local-login-placeholder-auth0
May 25, 2026
Merged

fix(auth): bypass OIDC challenge when placeholder Auth0 config is active (#396)#397
mpaulosky merged 3 commits into
devfrom
squad/396-fix-local-login-placeholder-auth0

Conversation

@mpaulosky

Copy link
Copy Markdown
Owner

Summary

Closes #396

Working as Gandalf (Security Officer)

Problem

In Development/Testing with no real Auth0 credentials configured, Program.cs falls back to the placeholder domain test.auth0.com. Navigating to /Account/Login then triggers a real OIDC discovery call against that non-existent domain, producing IDX20803: Unable to obtain configuration from … test.auth0.com after a full timeout.

Fix

isPlaceholderAuth0Config flag — set to true only when placeholder values are active. Developers with real user-secrets configured are completely unaffected; the flag stays false and the Auth0 Universal Login flow is preserved.

/Account/Login short-circuit — when the flag is true, the endpoint redirects immediately to /test/login (the existing cookie-based test login) instead of issuing a ChallengeAsync to the placeholder domain.

existingOnTokenValidated null guard — added if (existingOnTokenValidated != null) before invoking the captured delegate (PR #2 audit finding — latent NullReferenceException on every real login when Auth0 SDK leaves the delegate null).

Files changed

File Change
src/Web/Program.cs Flag, null-guard, /Account/Login short-circuit
docs/AUTH0_SETUP.md New troubleshooting entry: IDX20803 timeout pattern
.squad/agents/gandalf/history.md Key learnings appended

Security test scenarios for Gimli

  1. GET /Account/Login when isPlaceholderAuth0Config = true → assert 302 to /test/login, no OIDC challenge issued.
  2. GET /Account/Login when real Auth0 credentials are configured → assert OIDC challenge (302 to Auth0 domain), /test/login NOT called.
  3. Production startup without credentials → assert InvalidOperationException is thrown.
  4. GET /test/login in Development → assert cookie set, redirect to /, user authenticated.
  5. GET /test/login in Production → assert 404 (endpoint not registered).
  6. OnTokenValidated with null prior handler → assert no NullReferenceException; role claims added normally.

Pre-push gates

All 7 gates passed locally (build Release ✅, 420 unit tests ✅, 56 integration/E2E tests ✅).

In Development/Testing with no real Auth0 credentials configured, the
placeholder domain (test.auth0.com) would cause /Account/Login to hang
with IDX20803 until timeout.

Changes:
- Add isPlaceholderAuth0Config flag (true only when placeholder values
  are used); /Account/Login redirects to /test/login when set, avoiding
  any real OIDC discovery call.
- Developers with real user-secrets configured are unaffected — flag
  stays false and Auth0 Universal Login flow is preserved.
- Guard existingOnTokenValidated against null before invoking it,
  preventing a latent NullReferenceException on token validation.
- Update docs/AUTH0_SETUP.md with IDX20803 troubleshooting entry.

Closes #396

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 25, 2026 15:28
@mpaulosky mpaulosky added the squad:gandalf Assigned to Gandalf (Security / Auth) label May 25, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the local Development/Testing login experience when Auth0 configuration is missing by avoiding an OIDC discovery call to the placeholder test.auth0.com domain, while keeping the real Auth0 flow unchanged for developers who have configured credentials.

Changes:

  • Introduces an isPlaceholderAuth0Config flag and uses it to short-circuit /Account/Login to the existing /test/login endpoint in Development/Testing.
  • Adds a null-guard when invoking a captured OnTokenValidated delegate to prevent NullReferenceException.
  • Documents the IDX20803 timeout pattern and the intended fallback behavior in Auth0 setup docs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Web/Program.cs Adds placeholder-config detection, bypasses OIDC challenge in placeholder mode, and guards OnTokenValidated delegate invocation.
docs/AUTH0_SETUP.md Adds troubleshooting guidance for IDX20803 timeouts when placeholder Auth0 config is used locally.
.squad/agents/gandalf/history.md Records the issue context, fix details, and suggested test scenarios for the squad security agent history.
Comments suppressed due to low confidence (1)

src/Web/Program.cs:63

  • Production/staging config validation uses string.IsNullOrEmpty for Auth0:Domain and Auth0:ClientId, so whitespace-only values would pass startup checks but still break OIDC later. Using string.IsNullOrWhiteSpace here (to match the Dev/Testing branch) would fail fast on clearly invalid configuration.
if (!builder.Environment.IsDevelopment() && !builder.Environment.IsEnvironment("Testing"))
{
	if (string.IsNullOrEmpty(auth0Domain) || string.IsNullOrEmpty(auth0ClientId))
	{
		throw new InvalidOperationException(
				"Auth0 configuration is missing or incomplete. Set these user secrets for the Web project:\n" +
				"  dotnet user-secrets set \"Auth0:Domain\" \"<your-tenant>.auth0.com\" --project src/Web\n" +
				"  dotnet user-secrets set \"Auth0:ClientId\" \"<your-client-id>\" --project src/Web\n" +
				"  dotnet user-secrets set \"Auth0:ClientSecret\" \"<your-client-secret>\" --project src/Web");
	}

Comment thread src/Web/Program.cs
Comment on lines +185 to +192
// In Development/Testing with no real Auth0 credentials configured, bypass the OIDC
// discovery call — which would time out against the placeholder domain — and redirect
// straight to the test login endpoint instead.
if (isPlaceholderAuth0Config)
{
ctx.Response.Redirect("/test/login");
return;
}
Comment thread src/Web/Program.cs
Comment on lines 177 to +192
// Auth0 login/logout endpoints
app.MapGet("/Account/Login", async (HttpContext ctx, string? returnUrl) =>
{
var safeReturn = !string.IsNullOrEmpty(returnUrl)
&& Uri.IsWellFormedUriString(returnUrl, UriKind.Relative)
? returnUrl
: "/";

// In Development/Testing with no real Auth0 credentials configured, bypass the OIDC
// discovery call — which would time out against the placeholder domain — and redirect
// straight to the test login endpoint instead.
if (isPlaceholderAuth0Config)
{
ctx.Response.Redirect("/test/login");
return;
}
@github-actions

github-actions Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Test Results Summary

514 tests  +2   512 ✅ +1   37s ⏱️ ±0s
  6 suites ±0     1 💤 ±0 
  6 files   ±0     1 ❌ +1 

For more details on these failures, see this check.

Results for commit b5bf7e8. ± Comparison against base commit 7107862.

♻️ This comment has been updated with latest results.

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.46%. Comparing base (7107862) to head (c687b53).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev     #397   +/-   ##
=======================================
  Coverage   85.46%   85.46%           
=======================================
  Files          70       70           
  Lines        1693     1693           
  Branches      207      207           
=======================================
  Hits         1447     1447           
  Misses        166      166           
  Partials       80       80           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mpaulosky

Copy link
Copy Markdown
Owner Author

Gimli update: added AppHost coverage for /Account/Login in Testing to prove it redirects locally to /test/login (never test.auth0.com), plus an Architecture contract test that pins the placeholder short-circuit before ChallengeAsync while preserving the real Auth0 path. Local validation passed: Architecture.Tests 17/17, AppHost.Tests 56 passed with 1 existing skip, and Release build succeeded.

@mpaulosky
mpaulosky enabled auto-merge (squash) May 25, 2026 15:54
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mpaulosky
mpaulosky merged commit 3dac6f1 into dev May 25, 2026
15 checks passed
@mpaulosky
mpaulosky deleted the squad/396-fix-local-login-placeholder-auth0 branch May 25, 2026 16:05
mpaulosky added a commit that referenced this pull request May 25, 2026
## Summary
- preserve the validated `returnUrl` when placeholder Auth0 config
redirects `/Account/Login` to `/test/login`
- teach the local test-login endpoint to honor the same safe relative
return path
- strengthen AppHost and architecture coverage for the fallback redirect
contract

## Context
- follow-up to merged PR #397

Closes #398
Working as Gandalf (Security / Auth)

Co-authored-by: mpaulosky <mpaulosky@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

squad:gandalf Assigned to Gandalf (Security / Auth)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Sprint 20] Fix local login failure with placeholder Auth0 configuration

2 participants