0
votes

I'm trying to setup and IdentiyServer4, but I am stuck at the authorize:calling the /connect/introspect endpoint gives me the error

IdentityServer4.Validation.ApiSecretValidator: Error: No API resource with that name found. aborting IdentityServer4.Endpoints.IntrospectionEndpoint: Error: API unauthorized to call introspection endpoint. aborting. The client is a net framework 4.7 MVc and uses the IdentityServer3.AccesTokenValidation package

Here's my Identity Server configuration

internal class Resources
{
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new[]
        {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResources.Email(),
        new IdentityResource
        {
            Name = "role",
            UserClaims = new List<string> {"role"}
        }
    };
    }

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new[]
        {
            new ApiResource
        {
            Name = "electronicinvoice",
            DisplayName = "electronicinvoice",
            Description = "electronicinvoice",
            Scopes = new List<string> { "electronicinvoice" },
            ApiSecrets = new List<Secret> {new Secret("XXXXX".Sha256())},
            UserClaims = new List<string> {"role"}
        }
    };
    }

    public static IEnumerable<ApiScope> GetApiScopes()
    {
        return new[]
        {
            new ApiScope("electronicinvoice", "Access to electronicinvoiceactive api"),
        };
    }
}

The Client:

internal class Clients
{
    public static IEnumerable<Client> Get()
    {

         ICollection<string> allowed = GrantTypes.ClientCredentials.Union(GrantTypes.ResourceOwnerPassword).ToList();
        return new List<Client>
    {
        new Client
        {
            ClientId = "SolutionUpdate",
            ClientName = "Legal SolutionDOC client",
            AllowedGrantTypes =allowed ,
            ClientSecrets = new List<Secret> {new Secret("XXXXX".Sha256())}, 
            AllowedScopes = new List<string> {"email","openid","profile","electronicinvoice" },
           

        }
    };
    }
}

the Startup method

 public void ConfigureServices(IServiceCollection services)
    {



        services.AddIdentityServer()
        .AddInMemoryClients(Clients.Get())

        .AddInMemoryIdentityResources(Resources.GetIdentityResources())
        .AddInMemoryApiResources(Resources.GetApiResources())
        .AddInMemoryApiScopes(Resources.GetApiScopes())
      
         .AddDeveloperSigningCredential()
         .AddProfileService<ProfileService>()
        .AddCustomTokenRequestValidator<TokenRequestValidator>();
     
        services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
        services.AddTransient<IProfileService, ProfileService>();

    }

And, ofc, the client configuration

  public void Configuration(IAppBuilder app)
    {
       
        JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
        app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions()
        {
            Authority = "https://localhost:44389",
            ClientId = "SolutionUpdate",
            ClientSecret = "XXXXXX",  
          
            ValidationMode = ValidationMode.ValidationEndpoint
        });
     
       
    }

Now, i can succesfully get a valid token using this method

   var client = new TokenClient("https://localhost:44389/connect/token", "SolutionUpdate", "XXXXX");
            
                var extra = new Dictionary<string, string> { { nameof(paramAuth.CustomerCode), paramAuth.ToJson() } };
                var response = client.RequestClientCredentialsAsync("electronicinvoice" , extra).Result;
                var token = response.AccessToken;
                return Content(new DTO.GetTokenResponse { Token = token }.ToJson(), "application/json");

but i can't access any method decorated with the Authorize attribute. I Also tried calling directly the introspection endpoint like this

var introspectionClient = new IntrospectionClient("https://localhost:44389/connect/introspect", "SolutionUpdate", "XXXXXX");

        var response = introspectionClient.SendAsync(new IntrospectionRequest { Token = accessToken }).Result;

        var isActive = response.IsActive;
        var claims = response.Claims;

or from postman,

POST /connect/introspect Authorization: basic (with username and password) and body Token = myaccesstoken

Any suggestion is welcome Nb: i doublecked the passwords i'm using and they are all correct

1

1 Answers

0
votes

Ok, i figured it out: The introspection endpoint wants a basic authentication with the Apiscope credentials. This behaviour was probabilly different in identityserver3, or i am missing a configuration somewhere.

So I have 2 workarounds: -Change the Apiscope name and password to be the same as the clientId and password -Implement my own AuthorizeAttribute, in wich i'll call the introspection endpoint and parse the the response. I'll probabilly go with the second, it feels less "hackish", and i fear the first workaround will give me problem when i'll setup the token encryption