To Integrate Ws-Federation into .Net Core is straight forward although the documentation of this topic is really lacking. In the article below I have some code snippets showing how to do the integration.
Add the following NuGet packages. At the time of writing this article this Nuget packages required .net core 2.1.0.
- Microsoft.AspNetCore.Authentication.Cookies
- Microsoft.AspNetCore.Authentication.WsFederation
The following code needs to be added to the ConfigureServices method within the Startup.cs file. You can obviously break it out into its own method / class to keep the code cleaner but for example sake I am showing as part of the ConfigureServices method.
To Integrate with a IP-STS you need the following:
- Realm
- Issuer of the IP-STS certificate
- Metadata address to the IP-STS
Examples of IP-STS:
- Azure Active Directory
- ADFS
- Federated Ping
- Okta
- Site Minder
The implementation
public void ConfigureServices(IServiceCollection services) { services.Configure(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddAuthentication(sharedOptions => { sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme; }).AddWsFederation(wsFedOptions => { //RP realm - normally this is the client FQDN unless a realm is given to the RP by the STS wsFedOptions.Wtrealm = ""; //certificate issuer something like 'CN = COMODO RSA Domain Validation Secure Server CA O = COMODO CA Limited L = Salford S = Greater Manchester C = GB' wsFedOptions.TokenValidationParameters.ValidIssuer = ""; //url to sts metadata wsFedOptions.MetadataAddress = "https://server/FederationMetadata/2007-06/FederationMetadata.xml"; }).AddCookie(cookieOptions => { cookieOptions.Cookie.Name = "FedAuth"; //the name of the cookie you wish to use cookieOptions.Cookie.HttpOnly = true; //indicates the cookie can not be accessed by client scripts cookieOptions.Events = new CookieAuthenticationEvents { // event where you can hook in if you need to do aditional validation after the principal has been retrieved from the cookie. OnValidatePrincipal = AdditionalValidation }; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
The method below is where you can add validation or extend the principal once its received.
public static async Task AdditionalValidation(CookieValidatePrincipalContext context) { if (context != null && context.Request != null) { ClaimsPrincipal userPrincipal = context.Principal; // Add additional validation here or extend the identity of the claims principal here. } }
The WS-federation authentication handler will only kick in once access control has been implemented. As an example I added the authorize attribute to the home controller to force a redirect to the IP-STS.
[Authorize] public class HomeController : Controller {
Once authenticated the user details can be accessed via the ClaimsPrincipal class or via the HttpContext. Below is just some code as a example.
await WriteHtmlAsync(context.Response, async response => { await response.WriteAsync($"Hello Authenticated User {HtmlEncode(user.Identity.Name)} "); await response.WriteAsync("<a class="\"btn" href="\"/restricted\"">Restricted</a>"); await response.WriteAsync("<a class="\"btn" href="\"/signout\"">Sign Out</a>"); await response.WriteAsync("<a class="\"btn" href="\"/signout-remote\"">Sign Out Remote</a>"); await response.WriteAsync(" Claims: "); await WriteTableHeader(response, new string[] { "Claim Type", "Value" }, context.User.Claims.Select(c => new string[] { c.Type, c.Value })); });
Related.
Integrate Ws-Federation into Asp.Net
Integrate SAML2 into Asp.Net using Component Space
WS-Federation metadata generation tool
[…] Integrate Ws-Federation into Asp.Net Core WCF Security Token Service Troubleshoot WCF Security connectivity Asp.net security pipeline […]
[…] Integrate Ws-Federation into Asp.Net CoreIntegrate SAML2 into Asp.Net using Component Space […]
This helped me a fair amount in getting started with ws-federation with dotnet core. However, I don’t have a federation metadata file and I defined the token endpoint, wrealm, etc. After the security token from my federation provider gets validated, the updated claimsprincipal are not applied to my httpcontext. This causes a circular loop of having my client not be authenticated, requiring the federation server to send an updated security token, which gets validated, then lost. I see that a cookie is getting generated, but it doesn’t appear to get attached to the HttpContext. Any ideas what might be missing
The problem was not in the WS-Federation configuration, it was with the dotnet core Configure call. This link [https://stackoverflow.com/a/58585194/55913] pointed me in the right direction.