I'm using IdentityServer4, following the documentation at https://identityserver4.readthedocs.io/en/latest/quickstarts/1_client_credentials.html
But I am getting an invalid_scope
error in the client that uses IdentityModel
when requesting a token with client credentials.
It's possible I missed some step, but I've reviewed it several times.
The strange thing is that the identity server endpoint shows the following logs:
Invalid scopes requested, {"ClientId": "client", "ClientName": null, "GrantType": "client_credentials", "Scopes": null, "AuthorizationCode": null, "RefreshToken": null, "UserName": null, "AuthenticationContextReferenceClasses": null, "Tenant": null, "IdP": null, "Raw": {"grant_type": "client_credentials", "scope": "api1", "client_id": "client", "client_secret": "***REDACTED***"}, "$type": "TokenRequestValidationLog"}
Isn't strange that Scopes
is null
and later on scope
has the api1
value?
I am using in memory values.
public static class Config
{
public static IEnumerable<IdentityResource> Ids =>
new IdentityResource[]
{
new IdentityResources.OpenId()
};
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>
{
new ApiResource("api1", "My Api")
};
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
}
};
}
and
public void ConfigureServices(IServiceCollection services)
{
// uncomment, if you want to add an MVC-based UI
//services.AddControllersWithViews();
var builder =
services
.AddIdentityServer()
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddInMemoryIdentityResources(Config.Ids);
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// uncomment if you want to add MVC
//app.UseStaticFiles();
//app.UseRouting();
app.UseIdentityServer();
// uncomment, if you want to add MVC
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapDefaultControllerRoute();
//});
}
I can see the well known configuration, although it does not mention api1 as supported scopes.
This is the client
var client = new HttpClient();
var discovery =
await client.GetDiscoveryDocumentAsync("https://localhost:5001");
if (discovery.IsError)
{
await Console.Out.WriteLineAsync("Discovery error");
return;
}
// request token
var clientCredentialsTokenRequest =
new ClientCredentialsTokenRequest
{
Address = discovery.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
};
var tokenResponse =
await client.RequestClientCredentialsTokenAsync(clientCredentialsTokenRequest);
Am I missing any additional thing to have the most basic sample work?
UPDATE 1:
Ok, I have downgraded Identity Server to 3.1.3 and it works as it is. For the version Identity Server 4.0.0 something must have changed. Will investigate there.
Found an issue that pointed me in the right direction. Fixed it by replacing ApiResources with ApiScopes:
public static IEnumerable<ApiScope> Apis =>
new List<ApiScope>
{
new ApiScope("api1", "My Api")
};
and
var builder =
services
.AddIdentityServer()
.AddInMemoryApiScopes(Config.Apis)
//.AddInMemoryApiResources(Config.Apis) //OLD?
.AddInMemoryClients(Config.Clients)
.AddInMemoryIdentityResources(Config.Ids);
I supposed the docs are not yet updated.
I'm still getting an unauthorized when trying to access the protected Api, but that is something else.