22

I get the error below when performing a GET using IdentityModel's DiscoveryClient as follows:

var discoveryResponse = await DiscoveryClient.GetAsync("https://localhost/IdentityServer");

Issuer name does not match authority: https://localhost/identityserver

The target URL is an ASP.NET Core web application running on IIS enabled with IdentityServer4. The client application is a classic ASP.NET web application running on the same machine.

Apparently, the GET did manage to retrieve values from the IdentityServer as evidenced by the contents of discoveryResponse.Raw:

{
  "issuer": "https://localhost/identityserver",
  "jwks_uri": "https://localhost/IdentityServer/.well-known/openid-configuration/jwks",
  "authorization_endpoint": "https://localhost/IdentityServer/connect/authorize",
  "token_endpoint": "https://localhost/IdentityServer/connect/token",
  "userinfo_endpoint": "https://localhost/IdentityServer/connect/userinfo",
  "end_session_endpoint": "https://localhost/IdentityServer/connect/endsession",
  "check_session_iframe": "https://localhost/IdentityServer/connect/checksession",
  "revocation_endpoint": "https://localhost/IdentityServer/connect/revocation",
  "introspection_endpoint": "https://localhost/IdentityServer/connect/introspect",
  "frontchannel_logout_supported": true,
  "frontchannel_logout_session_supported": true,
  "scopes_supported": [ "CustomIdentityResources", "profile", "openid", "MyAPI.full_access", "offline_access" ],
  "claims_supported": [],
  "grant_types_supported": [ "authorization_code", "client_credentials", "refresh_token", "implicit" ],
  "response_types_supported": [ "code", "token", "id_token", "id_token token", "code id_token", "code token", "code id_token token" ],
  "response_modes_supported": [ "form_post", "query", "fragment" ],
  "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ],
  "subject_types_supported": [ "public" ],
  "id_token_signing_alg_values_supported": [ "RS256" ],
  "code_challenge_methods_supported": [ "plain", "S256" ]
}
Sigurd Garshol
  • 1,376
  • 3
  • 15
  • 36

4 Answers4

31

authority: https://localhost/IdentityServer issuer: https://localhost/identityserver

They do not match - it's case sensitive.

leastprivilege
  • 18,196
  • 1
  • 34
  • 50
  • Interesting. I'm having trouble tracking down the source of `issuer` field. Is this derived from the context of the hosting application? E.g. if I hosted the IdenityServer endpoints in IIS in an application called "IdentityProvider", the issuer would be `https://localhost/identityprovider` (lowercase)? – Sigurd Garshol Apr 26 '17 at 08:30
  • 1
    IIRC - the issuer name is always all lowercase (to avoid exactly these problems). – leastprivilege Apr 26 '17 at 12:10
  • Using lowercase certainly resolved the issue. Thanks! – Sigurd Garshol Apr 27 '17 at 08:39
  • 1
    @SigurdGarshol can you share how you got your `https` endpoint working with IS4? I can't get `RequestClientCredentialsAsync` working with `https` – Ruskin Jul 04 '17 at 02:50
  • @Ruskin: It's tough to answer without knowing what sort of errors you are experiencing. If it's a matter of "how did you enable https", then this is what we did: We tell the WebHostBuilder to use Kestrel with Https and provide a self-signed certificate read from a file. This only applies when we run the IS4 endpoints as a console host - when running under "proper" IIS we leve the https and certificates to the web server. – Sigurd Garshol Jul 12 '17 at 08:45
19

In the case when you are unable to change the server code to suit the policy, you can change the policy settings to allow name mismatches.

For example, I am attempting to use DiscoveryClient on the Azure Rest API, and the issuer is https://sts.windows.net/{{ tenant_id }} while the endpoints all start with https://login.microsoft.com/{{ tenant_id }}.

Simply set the fields ValidateIssuerName and ValidateEndpoints to false.

var tenant_id = "8481D2AC-893F-4454-8A3B-A0297D301278"; // Made up for this example
var authority = $"https://login.microsoftonline.com/{tenant_id}";
DiscoveryClient discoveryClient = new DiscoveryClient(authority);

// Accept the configuration even if the issuer and endpoints don't match
discoveryClient.Policy.ValidateIssuerName = false;
discoveryClient.Policy.ValidateEndpoints = false;

var discoResponse = await discoveryClient.GetAsync();


Later Edit

Since this message was posted the DiscoveryClient class has been deprecated.

Here is the new calling syntax:

var client = new HttpClient();
var discoResponse = await client.GetDiscoveryDocumentAsync(
    new DiscoveryDocumentRequest
    {
        Address = authority,
        Policy =
        {
            ValidateIssuerName = false,
            ValidateEndpoints = false,
        },
    }
);
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
  • 1
    This solved my problem. Thanks a lot! In my case, for issuer we use the external https URL and for authority we use the internal http URL. – devC Jun 08 '22 at 03:32
2

Other answers address the client - making it accept the lowercase issuer.

This changes the case of the issuer in the discovery document:

By default Identity Server seems to change the issuer Uri to lowercase. This leads to the discovery document having lower case for the issuer; and the case you typed in code/publishing for everything else.

I fixed this in my Identity Server app, Startup, ConfigureServices method

            var builder = services.AddIdentityServer(options => { options.LowerCaseIssuerUri = false; })

Using this means the case of the issuer in the discovery document is the same as for all the other Uris

TomFp
  • 469
  • 1
  • 5
  • 13
0

This error also happens if the URL of the request to the Discovery Client (or in my case the URL used for introspection of the access tokens during validation) contains escaped spaces (i.e., "%20" rather than " "), which kind of makes sense if the URLs are being compared exactly within Identity Server.

BobT
  • 66
  • 1
  • 1
  • 5