Search code examples
c#asp.net-core.net-coreidentityserver4ws-federation

IdentityServer4 as WSFederation-client with .Net Core WSFederation preview2


I am trying to add an WSFederation authentication-provider to IdentityServer4. Recently the Microsoft.AspNetCore.Authentication.WsFederation Preview 2 was released and I was able to add this to a normal Asp.NetCore-Application.

But I am having a hard time adding it to the IdentityServer4 EntityFramework-Quickstart-Example.

This is how I added the AuthenticationProvider in my Startup.cs/ConfigureServices-method:

services.AddAuthentication()
                .AddWsFederation("WsFederation", options =>
                {
                    options.Wtrealm = realm;
                    options.MetadataAddress = metadata;
                })

I got the button for WSFederation in the Frontend and I can also sign in. But after the callback I get this error:

InvalidOperationException: sub claim is missing IdentityServer4.Hosting.IdentityServerAuthenticationService.AssertRequiredClaims(ClaimsPrincipal principal)

I can understand where this comes from, it's this line in the IdentityServerAuthenticationService.cs of IdentityServer4, it expects a "sub"-claim - WSFed does not return such a claim:

if (principal.FindFirst(JwtClaimTypes.Subject) == null) throw new InvalidOperationException("sub claim is missing");

As far as I can see, I can't configure this claim, although there are some tables in the quickstart-project that seem like they could be used for this, especially those 2: dbo.IdentityResources-table dbo.IdentityClaims-table

I already tried adding the claim I want to use instead of the subject-claim to the table, but It doesn't seem to have any influence, also I don't know how the database maps to the identity providers I add in the code. I'd be happy for any hints about the next steps or if you know of any examples it would be even better.

P.S.: There are already some questions regarding this topic, but they are all either from before the .Net Core-implementation of WSFederation was available or refer to a sample for a WSFederation-server, but not the client.


Solution

  • Thanks to @leastprivilege I implemented the following workaround to provide the sub-claim:

    services.AddAuthentication()
                    .AddWsFederation("WsFederation", options =>
                    {
                        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                        options.Wtrealm = realm;
                        options.MetadataAddress = metadata;
                        options.Events.OnTicketReceived += OnTicketReceived;
                    })
    
    /* some more code inbetween */
    
        /// <summary>
        /// Transform the UPN-claim to the sub-claim to be compatible with IdentityServer4
        /// </summary>
        private async Task OnTicketReceived(TicketReceivedContext ticketReceivedContext)
        {
            var identity = ticketReceivedContext.Principal.Identities.First();
            identity.AddClaim(new Claim("sub", ticketReceivedContext.Principal.FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")));
    
        }