dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.22k stars 9.95k forks source link

WS-Federation 500 error over get requests /signin-wsfed #31276

Closed adrilmorell closed 3 years ago

adrilmorell commented 3 years ago

Describe the bug

Hi guys, I'm using the Ws-Federation package with .net core and the integration process has been very good, mainly thanks to this documentation entry https://docs.microsoft.com/en-us/aspnet/core/security/authentication/ws-federation?view=aspnetcore-3.1. I'm opening this issue becasue I'm not sure if it's normal that requesting the /signin-wsfed directly in the browser should throw a 500 exception, I would expect a Bad Request response. Exception down below in the Exception section.

To Reproduce

I'm registering the Ws-Federation dynamically by using the IAuthenticationSchemeProvider since I'm required to add new External Authentication Providers without changing the code or restarting the server. These are the most relevant parts of the code: 1- At Startup time I call this method to register the IPostConfigureOptions like this:

public static void AddExternalProvidersServices(AuthenticationBuilder authenticationBuilder)
{
    authenticationBuilder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<
            IPostConfigureOptions<WsFederationOptions>,
            WsFederationPostConfigureOptions>());
}

2- I call the method AddWsFederationProvider from a background service to register new providers like this:

public class ExternalProviderSyncService : IExternalProviderSyncService
{
    private readonly ILogger<ExternalProviderSyncService> _logger;
    private readonly IAuthenticationSchemeProvider _schemeProvider;
    private readonly IPostConfigureOptions<WsFederationOptions> _wsFederationOptionsConfigure;
    private readonly IOptionsMonitorCache<WsFederationOptions> _wsFederationOptionsCache;

    public ExternalProviderSyncService(
        ILogger<ExternalProviderSyncService> logger,
        IAuthenticationSchemeProvider schemeProvider,
        IPostConfigureOptions<WsFederationOptions> wsFederationOptionsConfigure,
        IOptionsMonitorCache<WsFederationOptions> wsFederationOptionsCache)
    {
        _logger = logger;
        _schemeProvider = schemeProvider;
        _wsFederationOptionsConfigure = wsFederationOptionsConfigure;
        _wsFederationOptionsCache = wsFederationOptionsCache;
    }

    ...

    private void AddWsFederationProvider(WsFederationProvider provider)
    {
        var schemeName = provider.GetProviderScheme();

        _schemeProvider.AddScheme(new AuthenticationScheme(schemeName, provider.DisplayName, typeof(WsFederationHandler)));

        var options = new WsFederationOptions
        {
            MetadataAddress = provider.MetadataAddress,
            Wtrealm = provider.Wtrealm,
            RequireHttpsMetadata = true,
        };

        _wsFederationOptionsConfigure.PostConfigure(schemeName, options);
        _wsFederationOptionsCache.TryAdd(schemeName, options);

        _logger.LogInformation($"External Provider with scheme '{schemeName}' has been configured correctly.");
    }
}

Exceptions (if any)

image

Further technical details

Host (useful for support): Version: 3.1.13 Commit: 64df28ec4a

.NET Core SDKs installed: No SDKs were found.

.NET Core runtimes installed: Microsoft.AspNetCore.App 3.1.13 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.13 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs: https://aka.ms/dotnet-download

blowdart commented 3 years ago

What's in your logs? 500 indicates a server error, and your logs around that time would be the first place to look for more details

adrilmorell commented 3 years ago

Thanks for the quick response, this is what I get from the logs:

[2021-03-26T13:45:59.5664793+00:00][INFO][5][Microsoft.AspNetCore.Hosting.Diagnostics] Request starting HTTP/1.1 GET http://localhost:33001/signin-wsfed  
[2021-03-26T13:45:59.6080857+00:00][INFO][5][Microsoft.AspNetCore.Authentication.WsFederation.WsFederationHandler] Error from RemoteAuthentication: "No message.".
[2021-03-26T13:45:59.6125856+00:00][EROR][5][Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware] An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
 ---> System.Exception: No message.
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at IdentityServer4.Hosting.FederatedSignOut.AuthenticationRequestHandlerWrapper.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
   at NWebsec.AspNetCore.Middleware.Middleware.MiddlewareBase.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
[2021-03-26T13:45:59.8984756+00:00][INFO][5][Microsoft.AspNetCore.Hosting.Diagnostics] Request finished in 331.4146ms 500 text/html; charset=utf-8

Just to make myself clear: The authentication process works fine for me. I get the error when I go to the browser and type that URL directly.

blowdart commented 3 years ago

Oh! Well don't do that :)

I'll demure to @Tratcher on if he thinks he wants to change it to be a bad request error.

blowdart commented 3 years ago

OK, what's happening is we're throwing an exception, because of a correlation error and the stack is mapping that to a 500.

As it's been this way for 10+ years now, we won't change it now. You could do it yourself by hooking into the AuthenticationFailed event, mark the failure as handled (so it doesn't get rethrown), and then send the 400 yourself.

adrilmorell commented 3 years ago

Thank you so much for your reply. I will give it a try.