Skip to content

Commit 5b4d4b5

Browse files
authored
Merge pull request #4 from sharpninja/claude/magical-ritchie
OIDC strategy pattern, federation auth bypass, and namespace normalization
2 parents 2912973 + 33b521f commit 5b4d4b5

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

lib/McpServer

Submodule McpServer updated 45 files

src/McpServer.Web/Pages/Auth/Login.cshtml.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.AspNetCore.Mvc;
44
using Microsoft.AspNetCore.Mvc.RazorPages;
55
using Microsoft.Extensions.Logging;
6+
using Microsoft.Extensions.Options;
67

78
namespace McpServerManager.Web.Pages.Auth;
89

@@ -14,21 +15,23 @@ namespace McpServerManager.Web.Pages.Auth;
1415
public sealed class LoginModel : PageModel
1516
{
1617
private readonly IAuthenticationSchemeProvider _schemeProvider;
18+
private readonly IOptionsMonitor<OpenIdConnectOptions> _oidcOptions;
1719
private readonly ILogger<LoginModel> _logger;
1820

19-
/// <summary>
20-
/// Initializes a new instance of the <see cref="LoginModel"/> class.
21-
/// </summary>
22-
/// <param name="schemeProvider">Authentication scheme provider used to verify OIDC availability.</param>
23-
/// <param name="logger">Logger.</param>
24-
public LoginModel(IAuthenticationSchemeProvider schemeProvider, ILogger<LoginModel> logger)
21+
public LoginModel(
22+
IAuthenticationSchemeProvider schemeProvider,
23+
IOptionsMonitor<OpenIdConnectOptions> oidcOptions,
24+
ILogger<LoginModel> logger)
2525
{
2626
_schemeProvider = schemeProvider;
27+
_oidcOptions = oidcOptions;
2728
_logger = logger;
2829
}
2930

3031
/// <summary>
3132
/// Issues an OpenID Connect challenge when configured, redirecting the browser to the OIDC provider's authorization endpoint.
33+
/// Before issuing the challenge, verifies that the OIDC discovery endpoint is reachable so that
34+
/// a downed identity provider surfaces a friendly redirect instead of an unhandled exception.
3235
/// </summary>
3336
/// <param name="returnUrl">Optional local URL to return to after login. Non-local URLs are ignored.</param>
3437
public async Task<IActionResult> OnGetAsync(string? returnUrl)
@@ -40,6 +43,23 @@ public async Task<IActionResult> OnGetAsync(string? returnUrl)
4043
return Redirect("/access-denied");
4144
}
4245

46+
// Pre-flight: verify the OIDC discovery endpoint is reachable before issuing the challenge.
47+
// Challenge() returns a deferred ChallengeResult; if the provider is unreachable the exception
48+
// fires deep inside the middleware pipeline where we can't catch it from the page handler.
49+
var options = _oidcOptions.Get(OpenIdConnectDefaults.AuthenticationScheme);
50+
if (options.ConfigurationManager is not null)
51+
{
52+
try
53+
{
54+
await options.ConfigurationManager.GetConfigurationAsync(HttpContext.RequestAborted).ConfigureAwait(true);
55+
}
56+
catch (Exception ex)
57+
{
58+
_logger.LogError(ex, "OIDC discovery endpoint is unreachable. The identity provider at {Authority} may be down.", options.Authority);
59+
return Redirect("/access-denied");
60+
}
61+
}
62+
4363
var redirectUri = !string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl)
4464
? returnUrl
4565
: "/";

0 commit comments

Comments
 (0)