"No token validator was found for the given token" when handling encrypted SAML in AuthenticationBuilder

41 views Asked by At

I maintain a .NET 6 web application that uses a federated IDP and SAML. Our IDP is now forcing the SAML to be encrypted (not just SSL) which is causing some headaches. The following is the relevant part of the current implementation:

 Builder.Services.AddAuthentication(sharedOptions =>
 {
     sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
     sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
     sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

 }).AddWsFederation(options =>
 {
     options.AllowUnsolicitedLogins = true;
     options.Wtrealm = Builder.Configuration["wsfed:realm"];
     options.SignOutWreply = Builder.Configuration["wsfed:signout"];
     options.MetadataAddress = Builder.Configuration["wsfed:metadata"];
     options.RemoteSignOutPath = Builder.Configuration["wsfed:signoutpath"];
     options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
     options.TokenValidationParameters = new TokenValidationParameters { SaveSigninToken = true };
     options.Events.OnSecurityTokenReceived = n => SecurityTokenReceived(n);
 })

I am leveraging AddWsFederation from Microsoft.AspNetCore.Authentication.WsFederation namespace which has been working smoothly with a not-encrypted SAML. Once the app receives the encrypted token "SecurityTokenException: No token validator was found for the given token." is thrown. From a couple of days of research it seems as if the pipeline cant work out what the token type is because it is encrypted.

Any help would be greatly appreciated!

I can see a valid payload being posted to the app inside the SecurityTokenReceived callback. There are properties on the TokenValidationParameters object such as 'TokenDecryptionKey' but after some experimentation the app never gets that far.

1

There are 1 answers

0
joltra On

We've had this problem and adding:

options.TokenHandlers.Add(new CustomSamlSecurityTokenHandler());

To the AddWsFederation method and this class:

public class CustomSamlSecurityTokenHandler : SamlSecurityTokenHandler
{
    public override async Task<TokenValidationResult> ValidateTokenAsync(string token, TokenValidationParameters validationParameters)
    {
        var configuration = await validationParameters.ConfigurationManager.GetBaseConfigurationAsync(CancellationToken.None).ConfigureAwait(false);
        var issuers = new[] { configuration.Issuer };
        validationParameters.ValidIssuers = (validationParameters.ValidIssuers == null ? issuers : validationParameters.ValidIssuers.Concat(issuers));
        validationParameters.IssuerSigningKeys = (validationParameters.IssuerSigningKeys == null ? configuration.SigningKeys : validationParameters.IssuerSigningKeys.Concat(configuration.SigningKeys));

        return await base.ValidateTokenAsync(token, validationParameters).ConfigureAwait(false);
    }
}

Solved it. Give it a try, we got it from here: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2406