![](/img/trans.png)
[英]Blazor WebAssembly App with Individual Accounts and ASP.NET Core Hosted - Disable user registration
[英]Blazor WebAssembly App with Individual Accounts and ASP.NET Core Hosted - Token request - "error": "unauthorized_client"
使用具有以下規范的Microsoft Visual Studio 2019 Version 16.9.4
創建新的Blazor WebAssembly App
: Target Framework .NET 5.0
, Authentication Type Individual Accounts
和ASP.NET Core Hosted
:
在版本5.0.5
中提供具有這些NuGet
的服務器項目:
Startup.cs 包含以下代碼:
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
閱讀博客文章ASP.NET Core Authentication with IdentityServer4
from Microsoft 我應該能夠使用如下所示的示例請求檢索令牌:
POST /connect/token HTTP/1.1
Host: localhost:5000
Cache-Control: no-cache
Postman-Token: 958df72b-663c-5638-052a-aed41ba0dbd1
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=Mike%40Contoso.com&password=MikesPassword1!&client_id=myClient&scope=myAPIs
https://devblogs.microsoft.com/aspnet/asp-net-core-authentication-with-identityserver4/
創建一個看起來像這樣的請求,但針對創建的解決方案:
POST /connect/token HTTP/1.1
Host: localhost:44388
Content-Type: application/x-www-form-urlencoded
Content-Length: 153
grant_type=password&username=example%40example.com&password=Password1&client_id=WebApplication4.Client&scope=WebApplication4.ServerAPI%20openid%20profile
此請求返回 HTTP 狀態 400 錯誤請求,正文:
{
"error": "unauthorized_client"
}
我很確定這些值是正確的,因為我從用於登錄 web 應用程序的請求中獲得了client_id
和scope
。 不過,該流程不使用grant_type=password
。 來自登錄的示例請求:
https://localhost:44388/Identity/Account/Login?ReturnUrl=/connect/authorize/callback?client_id=WebApplication4.Client&redirect_uri=https%3A%2F%2Flocalhost%3A44388%2Fauthentication%2Flogin-callback&response_type=code&scope=WebApplication4.ServerAPI%20openid%20profile&state=12345&code_challenge=12345&code_challenge_method=S256&response_mode=query
確認用戶存在並工作:
我錯過了什么?
TLDR:
從appsettings.json
刪除它:
"Clients": {
"WebApplication4.Client": {
"Profile": "IdentityServerSPA"
}
}
編輯Startup.cs
:
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddIdentityServerSPA("WebApplication4.Client", builder =>
{
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");
});
options.Clients.Add(new IdentityServer4.Models.Client
{
ClientId = "WebApplication4.Integration",
AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
//Use Configuration.GetSection("MySecretValue").Value; to get a value from appsettings.json
ClientSecrets = { new Secret("MySecretValue".Sha256()) },
AllowedScopes = { "WebApplication4.ServerAPI", "openid", "profile" }
});
});
此請求將起作用:
POST /connect/token HTTP/1.1
Host: localhost:44388
Content-Type: application/x-www-form-urlencoded
Content-Length: 168
grant_type=password&username=example%40example.com&password=Password1!&client_id=WebApplication4.Integration&scope=WebApplication4.ServerAPI&client_secret=MySecretValue
長答案:
我開始嘗試使用 Logging 獲得更好的錯誤消息。
我將以下代碼添加到Program.cs
中的public static IHostBuilder CreateHostBuilder(string[] args)
:
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0
在調試時,我可以在發出請求時從服務器應用程序中顯示 output。 它看起來像這樣:
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
info: IdentityServer4.Events.DefaultEventService[0]
{
"ClientId": "WebApplication4.Client",
"AuthenticationMethod": "NoSecret",
"Category": "Authentication",
"Name": "Client Authentication Success",
"EventType": "Success",
"Id": 1010,
"ActivityId": "8000000a-0000-8f00-b63f-84710c7967bb",
"TimeStamp": "2021-04-29T11:47:07Z",
"ProcessId": 8436,
"LocalIpAddress": "::1:44388",
"RemoteIpAddress": "::1"
}
fail: IdentityServer4.Validation.TokenRequestValidator[0]
Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = WebApplication4.Client }, details: {
"ClientId": "WebApplication4.Client",
"ClientName": "WebApplication4.Client",
"GrantType": "password",
"Raw": {
"grant_type": "password",
"username": "example@example.com",
"password": "***REDACTED***",
"client_id": "WebApplication4.Client",
"scope": "WebApplication4.ServerAPI"
}
}
info: IdentityServer4.Events.DefaultEventService[0]
{
"ClientId": "WebApplication4.Client",
"ClientName": "WebApplication4.Client",
"Endpoint": "Token",
"GrantType": "password",
"Error": "unauthorized_client",
"Category": "Token",
"Name": "Token Issued Failure",
"EventType": "Failure",
"Id": 2001,
"ActivityId": "8000000a-0000-8f00-b63f-84710c7967bb",
"TimeStamp": "2021-04-29T11:47:07Z",
"ProcessId": 8436,
"LocalIpAddress": "::1:44388",
"RemoteIpAddress": "::1"
}
要查看的錯誤消息是Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = WebApplication4.Client }
。
有了這個錯誤消息,我發現了這個問題:
關於 ASP.NET Core 3 Identity / Identity Server / SPA 對資源所有者密碼授予類型的支持的問題
在那里我可以閱讀
發現當配置文件設置為 IdentityServerSPA 時,未添加允許的密碼授予類型。
查看appsettings.json
應用程序使用該配置文件:
"IdentityServer": {
"Clients": {
"WebApplication4.Client": {
"Profile": "IdentityServerSPA"
}
}
},
查看Microsoft Application profiles
它的實際作用是:
在開始修改之前,我訪問了 URL https://localhost:44388/.well-known/openid-configuration
以獲取當前配置。 它看起來像這樣,特別是grant_types_supported: ...password
:
{
"issuer": "https://localhost:44388",
"jwks_uri": "https://localhost:44388/.well-known/openid-configuration/jwks",
"authorization_endpoint": "https://localhost:44388/connect/authorize",
"token_endpoint": "https://localhost:44388/connect/token",
"userinfo_endpoint": "https://localhost:44388/connect/userinfo",
"end_session_endpoint": "https://localhost:44388/connect/endsession",
"check_session_iframe": "https://localhost:44388/connect/checksession",
"revocation_endpoint": "https://localhost:44388/connect/revocation",
"introspection_endpoint": "https://localhost:44388/connect/introspect",
"device_authorization_endpoint": "https://localhost:44388/connect/deviceauthorization",
"frontchannel_logout_supported": true,
"frontchannel_logout_session_supported": true,
"backchannel_logout_supported": true,
"backchannel_logout_session_supported": true,
"scopes_supported": [
"openid",
"profile",
"WebApplication4.ServerAPI",
"offline_access"
],
"claims_supported": [
"sub",
"name",
"family_name",
"given_name",
"middle_name",
"nickname",
"preferred_username",
"profile",
"picture",
"website",
"gender",
"birthdate",
"zoneinfo",
"locale",
"updated_at"
],
"grant_types_supported": [
"authorization_code",
"client_credentials",
"refresh_token",
"implicit",
"password",
"urn:ietf:params:oauth:grant-type:device_code"
],
"response_types_supported": [
"code",
"token",
"id_token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"response_modes_supported": [
"form_post",
"query",
"fragment"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"subject_types_supported": [
"public"
],
"code_challenge_methods_supported": [
"plain",
"S256"
],
"request_parameter_supported": true
}
由於某種原因,無法在代碼和appsettings.json
中配置IdentityServer
Clients
。 因此,我從appsettings.json
中刪除了Clients
並將其添加到 Startup.cs:
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddIdentityServerSPA("WebApplication4.Client", builder =>
{
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");
});
options.Clients.Add(new IdentityServer4.Models.Client
{
ClientId = "WebApplication4.Integration",
AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
AllowedScopes = { "WebApplication4.ServerAPI", "openid", "profile" }
});
});
沒有WithRedirectUri
和WithLogoutRedirectUri
它不起作用, OidcConfigurationController
得到了ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId);
with System.InvalidOperationException: 'Sequence contains no elements'
。 由於某種原因,使用appsettings.json
時會自動修復此問題。
我現在在發布到/connect/token
時收到錯誤消息:
{
"error": "invalid_client"
}
但是我在日志中得到了一個更好的錯誤:
Invalid client configuration for client WebApplication4.Integration: Client secret is required for password, but no client secret is configured.
向Startup.cs
添加了一個秘密:
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddIdentityServerSPA("WebApplication4.Client", builder =>
{
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");
});
options.Clients.Add(new IdentityServer4.Models.Client
{
ClientId = "WebApplication4.Integration",
AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
//Use Configuration.GetSection("MySecretValue").Value; to get a value from appsettings.json
ClientSecrets = { new Secret("MySecretValue".Sha256()) },
AllowedScopes = { "WebApplication4.ServerAPI", "openid", "profile" }
});
});
和請求:
POST /connect/token HTTP/1.1
Host: localhost:44388
Content-Type: application/x-www-form-urlencoded
Content-Length: 168
grant_type=password&username=example%40example.com&password=Password1!&client_id=WebApplication4.Integration&scope=WebApplication4.ServerAPI&client_secret=MySecretValue
它終於奏效了,正常的登錄流程也奏效了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.