Search code examples
asp.net-coreoauth-2.0.net-coreidentityserver4

Identity Server 4 Client Credentials for custom endpoint on token Server


I implemented a token server using Identity Server 4.

I added a custom API endpoint to the token server and struggle with the authentication. The custom endpoint is inherited from ControllerBase and has 3 methods (GET, POST, DELETE).

I intend to call the custom endpoint from within another API using a dedicated client with credentials (server to server) implemented as HttpClient in .NET Core. There is no user involved into this.

For getting the access token I use the IdentityModel DiscoveryClient and TokenEndpoint.

So in sum I did the following so far:

  1. setup "regular" identity server and validate it works -> it works
  2. implement custom endpoint and test it without authorizatio -> it works
  3. add another api resource ("api.auth") with a custom scope "api.auth.endpoint1"
  4. setup a client with client credentials allowing access to scope "api.auth.endpoint1".
  5. implement the HttpClient and test setup -> I get an access token via the Identity Model Token Endpoint.

Now, when I call the endpoint using the HttpClient with the access token I received I get response code 200 (OK) but the content is the login page of the identity server.

The documentation of Identity Server 4 state the use of

   services.AddAuthentication()
    .AddIdentityServerAuthentication("token", isAuth =>
    {
        isAuth.Authority = "base_address_of_identityserver";
        isAuth.ApiName = "name_of_api";
    });

as well as the use of

   [Authorize(AuthenticationSchemes = "token")]

Unfortunatly the compiler state that .AddIdentityServerAuthentication can't be found. Do I miss a special nuget?

The nugets I use on the token server so far are:

  • IdentityServer4 (v2.2.0)
  • IdentityServer4.AspNetIdentity (v2.1.0)
  • IdentityServer4.EntityFramework (v2.1.1)

Figured out that part. The missing nuget for AddIdentityServerAuthentication is:

  • IdentityServer4.AccessTokenValidation

Struggling with the authorization based on the custom scope.

Does anyone know how the security has to be configured?


Solution

  • Configure a client with ClientGrantTypes = client_credentials and your api like this:

    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "http://localhost:5000";
            options.ApiName = "api.auth";
        });
    

    Where ApiName is the name of the resource. Please note that resource != scope. In most samples the resource name is equal to the scope name. But not in your case, where resource name is api.auth and scope name is api.auth.endpoint1.

    Configure the client to request the scope.

    var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, secret);
    var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api.auth.endpoint1");
    

    IdentityServer will lookup the Resource name and add that to the token as audience (aud) while the scope is added as claim with type scope.

    This should be enough to make it work. Also check the sample project.