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:
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.
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")));
}