Search code examples
iisasp.net-coreidentityserver4

I cannot get Identity Server 4 to authenticate a client. Server and Client are running Core 2.0


I have this running in IIS, if that makes any impact. The deployment environment will be IIS, with the future possibility to redeploy to Linux.

When I try to authenticate using the tokenclient, I get a 401.1 response.

Update: When I run this from console, it works. When I deploy to IIS and run it, under default deployment I get a 503, which then I end up putting the web.config back in, and the 401. comes back.

I grabbed the sample code, once I followed this step by step, and discovered that the step by step missed a step. I didn't see where it was stating that I needed app.UseIdentityServer();, but the well-known config didn't come up, so I figured that was critical.

However, now that my startup has the following:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddInMemoryApiResources(SeedData.GetApiResources())
            .AddInMemoryClients(SeedData.GetClients());
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseIdentityServer();
    }

Using the following code I can get the discovery and endpoint:

    var disco = DiscoveryClient.GetAsync(URL.ToLower()).Result;
    if (disco.IsError)
        Assert.Fail($"Discovery: {disco.Error}");
    else
        Assert.IsTrue(true, "Auth: Passed"); 

However, I cannot get an authentication with: var disco = DiscoveryClient.GetAsync(URL.ToLower()).Result;

        if (disco.IsError)
            Assert.Fail($"Discovery: {disco.Error}");

        var client = new TokenClient(
            disco.TokenEndpoint,
            "client",
            "secret");

        var token =  client
            .RequestClientCredentialsAsync(scope: "api1")
            .Result;

        Assert.IsTrue(
            !token.IsError,
            $"Auth: \"{token.Error}\"\n"
            + $"Token: \"{token.IdentityToken}\"\n"
            + $"StatusCode: \"{token.HttpStatusCode}\"\n"
            + $"Raw: \n{token.Raw}.");

        Assert.IsFalse(string.IsNullOrEmpty(token.IdentityToken));

This is my seed data: (Except for the class rename, I kept it the same as the sample code.) public static class SeedData { public static IEnumerable GetApiResources() { return new List { new ApiResource("api1", "My API") }; }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "client",
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = { "api1" }
            }
        };
    }
}

Also my Main function in the program.cs file is the default. I decided to not modify.

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

Here is my IIS log

|date|time|s-sitename|s-computername|s-ip|cs-method|cs-uri-stem|cs-uri-query|s-port|cs-username|c-ip|cs-version|cs(User-Agent)|cs(Cookie)|cs(Referer)|cs-host|sc-status|sc-substatus|sc-win32-status|sc-bytes|cs-bytes|time-taken|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|2018-03-28|11:05:19|W3SVC1|DESKTOP-TUNIQJE|::1|GET|/myurl/.well-known/openid-configuration|-|80|-|::1|HTTP/1.1|-|-|-|localhost|200|0|0|1606|111|3|
|2018-03-28|11:05:19|W3SVC1|DESKTOP-TUNIQJE|::1|GET|/myurl/.well-known/openid-configuration/jwks|-|80|-|::1|HTTP/1.1|-|-|-|localhost|200|0|0|640|116|3|
|2018-03-28|11:05:19|W3SVC1|DESKTOP-TUNIQJE|::1|POST|/myurl/connect/token|-|80|client|::1|HTTP/1.1|-|-|-|localhost|401|1|1326|6485|231|1|

Since the log dump isn't formatting into table here, the summary

  • /myurl/.well-known/openid-configuration gives me a 200, and a proper json file for discovery (get)
  • /myurl/.well-known/openid-configuration/jwks is generating proper json response (get)
  • '/myurl/connect/token' is producing a 401.1 (post)

Here is my serilog dump, from running the site on a console, rather than IIS. It seems to work this way.

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\me\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: IdentityServer4.Startup[0]
      You are using the in-memory version of the persisted grant store. This will store consent decisions, authorization codes, refresh and reference tokens in memory only. If you are using any of those features in production, you want to switch to a different store implementation.
dbug: IdentityServer4.Startup[0]
      Using idsrv as default scheme for authentication
dbug: IdentityServer4.Startup[0]
      Using idsrv as default scheme for sign-in
dbug: IdentityServer4.Startup[0]
      Using idsrv as default scheme for sign-out
dbug: IdentityServer4.Startup[0]
      Using idsrv as default scheme for challenge
dbug: IdentityServer4.Startup[0]
      Using idsrv as default scheme for forbid
Hosting environment: Development
Content root path: C:\rep\application
Now listening on: http://localhost:63656
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:63656/
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 170.4696ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:63656/.well-known/openid-configuration
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
dbug: IdentityServer4.Endpoints.DiscoveryEndpoint[0]
      Start discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 403.6945ms 200 application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:63656/.well-known/openid-configuration/jwks
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
dbug: IdentityServer4.Endpoints.DiscoveryKeyEndpoint[0]
      Start key discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 147.2603ms 200 application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:63656/.well-known/openid-configuration
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
dbug: IdentityServer4.Endpoints.DiscoveryEndpoint[0]
      Start discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 84.5783ms 200 application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:63656/.well-known/openid-configuration/jwks
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
dbug: IdentityServer4.Endpoints.DiscoveryKeyEndpoint[0]
      Start key discovery request
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 64.7313ms 200 application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://localhost:63656/connect/token application/x-www-form-urlencoded 40
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /connect/token matched to endpoint type Token
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Token, successfully created handler: IdentityServer4.Endpoints.TokenEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
dbug: IdentityServer4.Endpoints.TokenEndpoint[0]
      Start token request.
dbug: IdentityServer4.Validation.ClientSecretValidator[0]
      Start client validation
dbug: IdentityServer4.Validation.BasicAuthenticationSecretParser[0]
      Start parsing Basic Authentication secret
dbug: IdentityServer4.Validation.SecretParser[0]
      Parser found secret: BasicAuthenticationSecretParser
dbug: IdentityServer4.Validation.SecretParser[0]
      Secret id found: client
dbug: IdentityServer4.Validation.SecretValidator[0]
      Secret validator success: HashedSharedSecretValidator
dbug: IdentityServer4.Validation.ClientSecretValidator[0]
      Client validation success
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      Start token request validation
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      Start client credentials token request validation
dbug: IdentityServer4.Validation.TokenRequestValidator[0]
      client credentials token request validation success
info: IdentityServer4.Validation.TokenRequestValidator[0]
      Token request validation success
{
        "ClientId": "client",
        "GrantType": "client_credentials",
        "Scopes": "api1",
        "Raw": {
          "grant_type": "client_credentials",
          "scope": "api1"
        }
      }
dbug: IdentityServer4.Services.DefaultClaimsService[0]
      Getting claims for access token for client: client
dbug: IdentityServer4.Endpoints.TokenEndpoint[0]
      Token request success.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 745.8062ms 200 application/json; charset=UTF-8

UPDATE: I have added Serlog, and it is reporting nothing. Also the failed request tracing is returning nothing.


Solution

  • It turns out that there is a serious problem with my computer. When I pushed the code to Azure, it worked perfectly.

    For now I am considering this closed, but I will add to my comment once I figure out what went wrong with IIS.

    For the record m3n7alsnak3 should be the one getting the answer credit, since it was his time invested that got me to this solution.