Search code examples
asp.net-coreoauth-2.0jwtopeniddictasp.net-core-security

Validating issuer fails when site is reached under different alias as configured in the jwt bearer handler


I have web api which uses jwt bearer authentication. The implementation (openiddict) which creates the jwt uses the the current url as issuer.

services
    .AddOpenIddict()
    .UseJsonWebTokens();

I configured the jwt authentication handler to use a valid issuer.

services
    .AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://test/";
        ...
    });

When I reach the site under http://test/ I get an access token with the issuer set to http://test/. As the Authority matches the issuer the requests will be authenticated.

When I reach the site under http://125.124.35.21/ I get an access token with the issuer set to http://125.124.35.21/. As the Authority doesn't match the issuer the request won't be authenticated.

I want in both cases to be able to authenticate the request.

Now I saw that according to the jwt rfc the iss claim is optional.

My question is if I can set ValidateIssuer to false for this purpose, if I open a security hole when I do that and if there is an more recommended alternative?

services
    .AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.Authority = "http://test/";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ...
        }
    });

Which configuration is used to resolve the .well-known/openid-configuration?The Authority? Hopefully not the issuer because that would mean that everybody can issue a token and use it with my api.


Solution

  • I've looked into the code which generates my access token and found out that it only takes the current uri when no configuration value was set.

    https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/120a7ea9a14a33fad292cf4a11b4077118fab21f/src/AspNet.Security.OpenIdConnect.Server/OpenIdConnectServerHelpers.cs#L198

    public static string GetIssuer(this HttpContext context, OpenIdConnectServerOptions options)
    {
        var issuer = options.Issuer;
        if (issuer == null)
        {
            if (!Uri.TryCreate(context.Request.Scheme + "://" + context.Request.Host +
                                   context.Request.PathBase, UriKind.Absolute, out issuer))
            {
                throw new InvalidOperationException("The issuer address cannot be inferred from the current request");
            }
        }
    
        return issuer.AbsoluteUri;
    }
    

    So when I configure openiddict I can just set the Issuer property.

    services.AddOpenIddict()
        ...
        .Configure(options =>
        {
            options.Issuer = "http://test/";
            ...
        });
    

    And when I add the authentication services I can also just set the Authority property.

    services
        .AddAuthentication()
        .AddJwtBearer(options =>
        {
            options.Authority = "http://test/";
            ...
        });
    

    It seems like that when no valid issuer is configured the Authority is taken to validate the issuer. But I've found no code to support that claim.

    Maybe its hidden in Microsoft.IdentityModel.Protocols.OpenIdConnect.dll