有关ASP.NET Core 3 Identity/Identity Server/SPA对资源所有者密码授予类型的支持的问题 [英] Question about ASP.NET Core 3 Identity / Identity Server / SPA support for Resource Owner Password Grant Type

查看:65
本文介绍了有关ASP.NET Core 3 Identity/Identity Server/SPA对资源所有者密码授予类型的支持的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照 SPA的身份验证和授权,我创建了一个支持API授权的新SPA.您可以在GitHub上查看此内容.

As per Authentication and authorization for SPAs, I have created a new SPA with support for API authorization. You can view this on GitHub.

为了支持集成测试,我添加了一个新客户端(请参见

In order to support integration tests, I have added a new client (see appsettings.json) that is allowed the resource owner password grant type:

"SecureSpa.IntegrationTests": {
  "Profile": "IdentityServerSPA",
  "AllowedGrantTypes": [ "password" ],
  "ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ],
  "AllowedScopes": [ "SecureSpaAPI", "openid", "profile" ]
}

然后在 WeatherForecastControllerTests.cs 中,尝试如下请求令牌:

Then within WeatherForecastControllerTests.cs, I attempt to request the token as follows:

var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
    Address = disco.TokenEndpoint,
    ClientId = "SecureSpa.IntegrationTests",
    ClientSecret = "secret",

    Scope = "SecureSpaAPI openid profile",
    UserName = "demouser@securespa",
    Password = "Pass@word1"
  });

运行测试时,我尝试了许多不同的组合,但是结果通常是相同的( unauthorized_client ).这是Identity Server的相关日志输出:

When running the test, I've tried many different combinations, however the results are usually the same (unauthorized_client). This is the relevant log output from Identity Server:

IdentityServer4.Endpoints.TokenEndpoint: Debug: Start token request.
IdentityServer4.Validation.ClientSecretValidator: Debug: Start client validation
IdentityServer4.Validation.BasicAuthenticationSecretParser: Debug: Start parsing Basic Authentication secret
IdentityServer4.Validation.PostBodySecretParser: Debug: Start parsing for secret in post body
IdentityServer4.Validation.SecretParser: Debug: Parser found secret: PostBodySecretParser
IdentityServer4.Validation.SecretParser: Debug: Secret id found: SecureSpa.IntegrationTests
IdentityServer4.Stores.ValidatingClientStore: Debug: client configuration validation for client SecureSpa.IntegrationTests succeeded.
IdentityServer4.Validation.ClientSecretValidator: Debug: Public Client - skipping secret validation success
IdentityServer4.Validation.ClientSecretValidator: Debug: Client validation success
IdentityServer4.Events.DefaultEventService: Information: {
  "Name": "Client Authentication Success",
  "Category": "Authentication",
  "EventType": "Success",
  "Id": 1010,
  "ClientId": "SecureSpa.IntegrationTests",
  "AuthenticationMethod": "SharedSecret",
  "ActivityId": "0HLPN4PPDDMCJ",
  "TimeStamp": "2019-09-12T02:10:57Z",
  "ProcessId": 28948,
  "LocalIpAddress": "unknown",
  "RemoteIpAddress": "unknown"
}
IdentityServer4.Validation.TokenRequestValidator: Debug: Start token request validation
IdentityServer4.Validation.TokenRequestValidator: Debug: Start resource owner password token request validation
IdentityServer4.Validation.TokenRequestValidator: Error: Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = SecureSpa.IntegrationTests }, details: {
  "ClientId": "SecureSpa.IntegrationTests",
  "ClientName": "SecureSpa.IntegrationTests",
  "GrantType": "password",
  "Raw": {
    "grant_type": "password",
    "username": "demouser@securespa",
    "password": "***REDACTED***",
    "scope": "SecureSpaAPI",
    "client_id": "SecureSpa.IntegrationTests",
    "client_secret": "***REDACTED***"
  }
}
IdentityServer4.Events.DefaultEventService: Information: {
  "Name": "Token Issued Failure",
  "Category": "Token",
  "EventType": "Failure",
  "Id": 2001,
  "ClientId": "SecureSpa.IntegrationTests",
  "ClientName": "SecureSpa.IntegrationTests",
  "Endpoint": "Token",
  "GrantType": "password",
  "Error": "unauthorized_client",
  "ActivityId": "0HLPN4PPDDMCJ",
  "TimeStamp": "2019-09-12T02:10:57Z",
  "ProcessId": 28948,
  "LocalIpAddress": "unknown",
  "RemoteIpAddress": "unknown"
}
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 212.96790000000001ms 400 application/json; charset=UTF-8

是否支持此方法?如果不是,是否存在可用于获取令牌以编写集成测试的替代方法?我打算与测试客户端一起建立测试用户,以便可以测试许多不同的行为.

Is this approach supported? If not, is there an alternative approach that can be used to get the token in order to write integration tests? I'm planning to set up test users along with the test client so that I can test lots of different behaviours.

推荐答案

我继续研究此问题,发现当配置文件设置为IdentityServerSPA时,未添加允许的密码授予类型.我看不到通过appsettings添加没有配置文件的客户端的方法,因此我从appsettings中删除了配置,并使用以下方法创建了客户端:

I continued working on this issue and found that the allowed grant type of password was not being added when the profile is set to IdentityServerSPA. I couldn't see a way to add a client without a profile via appsettings, so I removed the configuration from appsettings and created the clients using this approach:

services.AddIdentityServer()
    //.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
    {
        options.Clients.AddIdentityServerSPA("SecureSpa", builder =>
        {
            builder.WithRedirectUri("https://localhost:44307/authentication/login-callback");
            builder.WithLogoutRedirectUri("https://localhost:44307/authentication/logout-callback");
        });
        options.Clients.Add(new Client
        {
            ClientId = "SecureSpa.IntegrationTests",
            AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
            ClientSecrets = { new Secret("secret".Sha256()) },
            AllowedScopes = { "SecureSpaAPI", "openid", "profile" }
        });
    });

现在,我的测试就可以运行了.您可以在此处看到最终的解决方案; https://github.com/JasonGT/SecureSpa/.

With that in place my tests now run. You can see the final solution here; https://github.com/JasonGT/SecureSpa/.

一切正常,但是 DefaultClientRequestParametersProvider 中似乎存在一个错误(或功能限制).请参阅"GetClientParameters"方法-如果指定的客户端没有关联的配置文件,则会抛出 InvalidOperationException .

Everything works fine, however there seems to be a bug (or feature limitation) within DefaultClientRequestParametersProvider. See the 'GetClientParameters' method - if the specified client does not have an associated profile, an InvalidOperationException is thrown.

让我知道是否需要更多信息.

Let me know if you need more information.

这篇关于有关ASP.NET Core 3 Identity/Identity Server/SPA对资源所有者密码授予类型的支持的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆