14

I'm developing an ASP.NET Core 2 app using Identity and Sustainsys.Saml2 (for SAML auth). I've made the necessary configurations in the Startup.cs file. Now when I run the project and try to login using the SAML2 (as an external login), I get the following error after enter my credentials:

SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'. Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable audiences, SecurityToken securityToken, TokenValidationParameters validationParameters) Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateConditions(Saml2SecurityToken samlToken, TokenValidationParameters validationParameters) Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateToken(string token, TokenValidationParameters validationParameters, out SecurityToken validatedToken) Sustainsys.Saml2.Saml2P.Saml2Response+d__60.MoveNext() System.Collections.Generic.List..ctor(IEnumerable collection) System.Linq.Enumerable.ToList(IEnumerable source) Sustainsys.Saml2.Saml2P.Saml2Response.GetClaims(IOptions options, IDictionary relayData) Sustainsys.Saml2.WebSso.AcsCommand.ProcessResponse(IOptions options, Saml2Response samlResponse, StoredRequestState storedRequestState) Sustainsys.Saml2.WebSso.AcsCommand.Run(HttpRequestData request, IOptions options) Sustainsys.Saml2.AspNetCore2.Saml2Handler+d__12.MoveNext() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+d__6.MoveNext() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware+d__4.MoveNext() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+d__6.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+d__6.MoveNext() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+d__7.MoveNext()

I'm not understanding what does this mean. Am I missing something?

Here's what I have in the Startup file

services.AddAuthentication()
        .AddSaml2(options => 
        {
            var spOptions = new SPOptions
            {
                EntityId = new EntityId("https://localhost:44373/Saml2"),
                ReturnUrl = new Uri("https://localhost:44373"),
                MinIncomingSigningAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1",                  
            };                

            options.SPOptions = spOptions;
            options.IdentityProviders.Add(new IdentityProvider(new EntityId("https://www.example.com/SSO/SAML/App"), options.SPOptions)
            {
                AllowUnsolicitedAuthnResponse = false,                  
                MetadataLocation = "https://www.example.com/SSO/SAMLMetadata/App",                  
                LoadMetadata = true,                  
            }); 
        });

Thanks in advance...

OnlyOneEA
  • 193
  • 1
  • 1
  • 9
  • 1
    Hello, this comment doesn't directly impact this question, but I got here with the same issue (JWT Token, IS4 (4.2.0), Audience failed).How I fixed it was by adding a scope to the API Resource that was the same name as the API Resource name in the IS4 app and that solved the issue. Just FYI for anyone coming here in hopes of fixing their audience validation issue. `new ApiResource("testAPI","API",new List{"role"}) {ApiSecrets = {new Secret("secret".Sha256())}, Scopes = new List() {"testAPI"}}` – Rushman Jul 07 '20 at 22:24

3 Answers3

18

As far as I know, this error clearly states that audience that came in your SAML-token is different from the value in your Startup configuration. It might be helpful to compare these values. Sometimes the validation fails due to case-sensitive comparison, so you should pay attention in which case your audiencies are in token and configuration.

According to the source code (Saml2Response) and as Anders Abel pointed out, ValidAudience property is initialized from SPOptions.EntityId that you configure here:

var spOptions = new SPOptions
{
    EntityId = new EntityId("https://localhost:44373/Saml2"),
    ReturnUrl = new Uri("https://localhost:44373"),
    MinIncomingSigningAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1",                  
};

So you should compare the EntityId value, that you have configured with the value in your saml-token, which might look like this:

<saml:Audience>The value here should be the same as in your startup configuration</saml:Audience>
NamiraJV
  • 658
  • 1
  • 7
  • 11
  • 1
    where and how would I set the ValidAudience in the Startup config? – OnlyOneEA Oct 16 '18 at 20:10
  • It would be very helpful if you posted that configuration piece in your question. It is hard to tell without knowing what exactly you are using. – NamiraJV Oct 16 '18 at 20:25
  • I've updated my post to include the configuration piece – OnlyOneEA Oct 16 '18 at 20:54
  • The audience settings is not directly configurable in 2.0.0 (which this must be). It is assumed that the audience will match the spOptions EntityId. Enable PII logging to see actual values. (Google can help on how to do that) – Anders Abel Oct 17 '18 at 05:21
  • @UWPDeveloper, I updated my answer according to your question changes. – NamiraJV Oct 17 '18 at 12:46
  • 8
    Hi @AndersAbel, I was able to get the PII to be displayed in the error message by inserting this line of code `IdentityModelEventSource.ShowPII = true;` and the error now shows this `Audiences: 'https://localhost:44373/Saml2/Acs'. Did not match: validationParameters.ValidAudience: 'https://localhost:44373/Saml2' or validationParameters.ValidAudiences: 'null'` – OnlyOneEA Oct 17 '18 at 12:48
  • So it means that you have https://localhost:44373/Saml2/Acs url in your saml token. Try to set `EntityId = new EntityId("https://localhost:44373/Saml2/Acs")` in your configuration. – NamiraJV Oct 17 '18 at 12:57
  • @NamiraJV, when I made the change to the EntityId, I no longer got that error message but no I received a new error stating that the header was too long. Going to figure out why I'm getting this error now. Thanks for the help! :) – OnlyOneEA Oct 17 '18 at 13:40
  • 2
    Hi @OnlyOneEA Thank you for the code snippet `IdentityModelEventSource.ShowPII = true;` that can be added to the service being added to the the program in the Startup.cs. I was initially confused as to where it would go but then figured out. Finally figured out even I had a miss match problem. – Yashash Gaurav Mar 15 '19 at 13:27
  • I have also faced the same issue. In my case, the audience URL was not matched due to the case- sensitive. Once it is corrected in the configuration, its work fine. – Mukesh Arora Jun 03 '19 at 04:59
  • I had similar issue it was telling "'https://localhost:44360/' not matching with 'https://localhost:44360'. I was using ADFS and under Relying Party Trust I added the URL as https://localhost:44360/'. But application URL was just 'https://localhost:44360' i.e without that last slash "\". Once I removed that slash in ADFS Relying Party Trust URL, both URL matched and error gone. – Jaish Mathews Jun 05 '19 at 18:43
3

IDX10214: Check this section if you are using Microsoft.Identity.Web version 1.4.1 or similar and you get this exception (literally copied, and you have to change the log levels in appsettings.json to get to see this):

info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
      Failed to validate the token.
      Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: 'System.String'. Did not match: validationParameters.ValidAudience: 'System.String' or validationParameters.ValidAudiences: 'System.String'.
         at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
         at Microsoft.Identity.Web.Resource.RegisterValidAudience.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
         at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
         at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()

Would be so much more helpful to actually see the value of those System.String's. And if it didn't matter whether you use a GUID or something memorizable and readable.

Essentially you have to add the Audience property to appsettings.json and that must be equal to the Application ID URI in the Azure portal. I had no luck whatsoever hacking the ClientId and have that match the Application ID URI. That isn't the final solution to this - AFAIK that must still be equal to the Application (client) ID in the Azure portal, i.e. a GUID without any prefixes or suffixes.

Eric
  • 2,797
  • 2
  • 20
  • 19
  • 5
    If you need to see the PII contained in the `System.String`s, you can add this line in e.g. the `Configure` method of `Startup.cs`: `Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;` – RasmusW Dec 29 '20 at 14:56
  • This is amazing! I can't believe I need to set Audience as well as ClientID in my appsettings.json. Audience kept on being api://myValue instead of the myValue which was what was being supplied by my token. – Ed HP May 04 '23 at 10:26
0

in my case the issuer and audience for the JwtSecurityToken were omitted. In my derived class UserService: IUserService I defined the issuer and audience variables in the function generateJwtToken. They variables must match services.AddJwtBearer variables in the startup.csv for ValidIssuer and ValidAudience. see(https://dotnetcoretutorials.com/2020/01/15/creating-and-validating-jwt-tokens-in-asp-net-core/).

quote:

The Issuer and Audience are funny things because realistically, you probably won’t have a lot of use for them. Issuer is “who” created this token, for example your website, and Audience is “who” the token is supposed to be read by. So a good example might be that when a user logs in, your authentication api (auth.mywebsite.com) would be the issuer, but your general purposes API is the expected audience (api.mywebsite.com). These are actually free text fields so they don’t have to be anything in particular, but later on when we validate the issuer/audience, we will need to know what they are.

public class UserService : IUserService {

private string generateJwtToken(long userId)
            {
                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Secret));
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
                var tokenOptions = new JwtSecurityToken(
                    issuer: "http://localhost:5000",
                    audience: "http://localhost:5000",
                    claims: new List<Claim> {
                        new Claim(ClaimTypes.Name, userId.ToString()),
                        new Claim(ClaimTypes.Role, "Operator")
                    },
                    expires: DateTime.UtcNow.AddDays(7),
                    signingCredentials: signinCredentials
                );
                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);
                return tokenString;

            }

}

startup.cs

public void ConfigureServices(IServiceCollection services)
        {

services.AddAuthentication(opt =>
            {
                opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(opt =>
            {
                opt.RequireHttpsMetadata = false;
                opt.SaveToken = true;
                opt.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidIssuer = "http://localhost:5000",
                    ValidAudience = "http://localhost:5000"
                };
            });

}
Golden Lion
  • 3,840
  • 2
  • 26
  • 35