dotnet / dotnet/aspnetcore

Duende.IdentityServer from Blazor WebAssembly App protecting ASP.NET Core API using Client Credentials with custom allowed scope - invalid_scope

Open
#44,122 8 comments 0 reactions 0 assignees View on GitHub
area-identity External feature-blazor-wasm
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Is your feature request related to a problem? Please describe the problem.

I have a `Blazor WebAssembly App` created with `Microsoft Visual Studio` with these specifications: `Target Framework .NET 6.0`, `Authentication Type Individual Accounts` and `ASP.NET Core Hosted`:

Using this answer I have been able to add Client Credentials flow

https://stackoverflow.com/a/67324222/3850405

I removed this from `appsettings.json`:

"Clients": {
"WebApplication4.Client": {
"Profile": "IdentityServerSPA"
}
}

Edit `Startup.cs` or `Program.cs`:

services.AddIdentityServer()
.AddApiAuthorization(options =>
{
options.Clients.AddIdentityServerSPA("WebApplication4.Client", builder =>
{
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");
});
options.Clients.Add(new Duende.IdentityServer.Models.Client
{
ClientId = "WebApplication4.Integration",
AllowedGrantTypes = { GrantType.ClientCredentials },
ClientSecrets = { new Secret("MySecretValue".Sha256()) },
AllowedScopes = { "WebApplication4.ServerAPI"}
});
});

This request will work:

POST /connect/token HTTP/1.1
Host: localhost:44397
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=WebApplication4.Integration&client_secret=MySecretValue&scope=WebApplication4.ServerAPI

However I want this client to have its own `AllowedScopes`. If I then change `AllowedScopes = { "WebApplication4.ServerAPI"}` to `AllowedScopes = { "WebApplication4.IntegrationAPI"}` and of course modifying the request.

Server then responds with:

{
"error": "invalid_scope"
}

If I look at logging I get the following history:

info: Duende.IdentityServer.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: Duende.IdentityServer.Endpoints.TokenEndpoint for /connect/token
info: Duende.IdentityServer.Events.DefaultEventService[0]
{
"ClientId": "WebApplication4.Integration",
"AuthenticationMethod": "SharedSecret",
"Category": "Authentication",
"Name": "Client Authentication Success",
"EventType": "Success",
"Id": 1010,
"ActivityId": "80000009-0014-d600-b63f-84710c7967bb",
"TimeStamp": "2022-09-22T09:30:31Z",
"ProcessId": 17768,
"LocalIpAddress": "::1:44397",
"RemoteIpAddress": "::1"
}
fail: Duende.IdentityServer.Validation.DefaultResourceValidator[0]
Scope WebApplication4.IntegrationAPI not found in store or not supported by requested resource indicators.
fail: Duende.IdentityServer.Validation.TokenRequestValidator[0]
Invalid scopes requested, {
"ClientId": "WebApplication4.Integration",
"GrantType": "client_credentials",
"AuthorizationCode": "********",
"RefreshToken": "********",
"Raw": {
"grant_type": "client_credentials",
"client_id": "WebApplication4.Integration",
"client_secret": "***REDACTED***",
"scope": "WebApplication4.IntegrationAPI"
}
}
info: Duende.IdentityServer.Events.DefaultEventService[0]
{
"ClientId": "WebApplication4.Integration",
"Endpoint": "Token",
"GrantType": "client_credentials",
"Error": "invalid_scope",
"Category": "Token",
"Name": "Token Issued Failure",
"EventType": "Failure",
"Id": 2001,
"ActivityId": "80000009-0014-d600-b63f-84710c7967bb",
"TimeStamp": "2022-09-22T09:30:31Z",
"ProcessId": 17768,
"LocalIpAddress": "::1:44397",
"RemoteIpAddress": "::1"
}

What I take with me is this:

Scope WebApplication4.IntegrationAPI not found in store or not supported by requested resource indicators.

I then looked at these guides:

https://github.com/IdentityServer/IdentityServer4/issues/4632#issuecomment-654685880

https://docs.duendesoftware.com/identityserver/v5/quickstarts/1_client_credentials/

I therefore added this code:

public static class Config
{
public static IEnumerable ApiScopes =>
new List
{
new ApiScope("WebApplication4.IntegrationAPI", "Integration API")
};
}

and

services.AddIdentityServer()
.AddInMemoryApiScopes(Config.ApiScopes)
.AddApiAuthorization(options =>...

This still gave me the same error.

I then added a new list with clients:

public static IEnumerable Clients =>
new List
{
new Duende.IdentityServer.Models.Client
{
ClientId = "WebApplication4.Integration",
AllowedGrantTypes = { GrantType.ClientCredentials },
ClientSecrets = { new Secret("MySecretValue".Sha256()) },
AllowedScopes = { "WebApplication4.IntegrationAPI" },
}
};

Removed the old client from `AddApiAuthorization` and used this code instead:

services.AddIdentityServer()
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddApiAuthorization(options => ...

This gave me a new error when requesting a token:

{
"error": "invalid_client"
}

Logs:

info: Duende.IdentityServer.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: Duende.IdentityServer.Endpoints.TokenEndpoint for /connect/token
info: Duende.IdentityServer.Events.DefaultEventService[0]
{
"ClientId": "WebApplication4.Integration",
"Category": "Authentication",
"Name": "Client Authentication Failure",
"EventType": "Failure",
"Id": 1011,
"Message": "Unknown client",
"ActivityId": "8000000a-0016-e700-b63f-84710c7967bb",
"TimeStamp": "2022-09-22T09:54:08Z",
"ProcessId": 10676,
"LocalIpAddress": "::1:44397",
"RemoteIpAddress": "::1"
}
fail: Duende.IdentityServer.Validation.ClientSecretValidator[0]
No client with id 'WebApplication4.Integration' found. aborting

If I look at https://localhost:44397/.well-known/openid-configuration I only see `WebApplication4.ServerAPI` in `scopes_supported` no matter the configuration.

### Describe the solution you'd like

I want to do it like this so that I can add a policy like this later:

services.AddAuthorization(options =>
{
options.AddPolicy("IntegrationApiScope", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "WebApplication4.IntegrationAPI");
});
});

Meaning that I only want Client Credentials flow to get the scope `WebApplication4.IntegrationAPI` and I don't want Authorization Code Grant, normal login flow via `authorization_code`, to have this scope or be able to request this scope.

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.