我正在撰写有关如何使用Postman从IDS4获取令牌的演示。
密码令牌请求取自IDS4's page。
[HttpGet("token")]
public IActionResult GetToken([FromHeader] string user, [FromHeader] string pass)
{
string tokenEndpoint = "https://localhost:44300/connect/token";
HttpClient client = new HttpClient();
Task<TokenResponse> tokenResponse =
client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = tokenEndpoint,
ClientId = "client",
ClientSecret = "client_secret",
Scope = "MemberApi.full",
UserName = user,
Password = pass
});
TokenResponse toko = tokenResponse.Result;
if (toko.IsError)
return Ok(toko.Error);
return Ok(toko.AccessToken;
}
客户端设置如下。
private static IEnumerable<Client> GetClients => new[]
{
...
new Client
{
ClientId = "client",
ClientSecrets = { new Secret("client_secret".Sha256()) },
ClientName = "Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:5000/security/credentials" },
PostLogoutRedirectUris = { "http://localhost:5000/index.html" },
AllowedCorsOrigins = { "http://localhost:5000", "https://localhost:44300" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"MemberApi",
"MemberApi.full",
"MemberApi.limited"
}
}
};
API资源设置如下所示。
private static IEnumerable<ApiResource> GetApis => new[]
{
new ApiResource
{
Name = "MemberApi",
DisplayName = "Members' API",
ApiSecrets = {new Secret("MemberSecret".Sha256())},
UserClaims = {JwtClaimTypes.Name, JwtClaimTypes.Email, JwtClaimTypes.Role},
Scopes = {new Scope("MemberApi.full"), new Scope("MemberApi.limited")}
}
};
据我所知,我遵循了文档中的建议。我也尝试与示例进行比较。尽管如此,我仍然停留在错误消息 unauthorized_client 上。我会缺少什么?
答案 0 :(得分:3)
此流程中不允许客户请求:
AllowedGrantTypes = GrantTypes.Implicit
忘记client.RequestPasswordTokenAsync。您不需要它,也无法使用它。在隐式流中,只有用户知道密码。对于客户来说这是遥不可及的。
假定IdentityServer在一个域上运行:https://idp.mydomain.com,而客户端在其他域上运行:https://mvc.mydomain.com
当用户点击mvc客户端上的安全页面时,该用户会被路由到用户登录的IdentityServer 。在那里,用户输入凭据,如果成功,则将用户返回到客户端。作为已知身份。
取决于流,客户端最终最终会获得至少一个访问令牌。此令牌很重要,因为它允许客户端代表用户访问资源 。就像门票一样。
基于访问令牌,资源现在知道WHO想要访问该资源。访问令牌有一个区分这一点的声明,即“子”声明。没有此声明,客户端将无法访问此流程中的资源。
在您的配置中,允许客户端访问“ MemberApi”作用域,但在实际访问资源之前,需要用户的同意。
如果要检索以最简单的流程开头的令牌,则为client credentials流。
这就是根本没有用户的流程。客户端(如在软件中)可以使用clientid + secret登录。如果配置正确,将产生访问令牌。
现在,客户端无需任何用户交互即可访问资源。身份令牌不可用,因为没有用户。缺少“子”要求。此流中不支持刷新令牌,不需要它。客户端可以使用凭据请求新令牌。
如果您想了解refresh token的工作方式,请在hybrid flow中用户登录,并另外(如果已配置scope = offline)返回刷新令牌。
由于访问令牌仅在短时间内有效(取决于到期时间),因此必须获取新令牌。为此,应使用刷新令牌。刷新令牌使客户端可以请求新的访问令牌,而无需用户交互(离线访问)。
使用新的访问令牌,直到它过期,并且必须请求一个新的令牌。直到刷新令牌本身过期为止,但是可以对其进行配置。
在implicit flow中没有刷新令牌,但是访问令牌确实会全部过期。因此,您将需要另一种刷新令牌的方法。为此,您可以使用类似silent token renew的实现。
有关术语,请阅读documentation。
请注意各种流程。这完全取决于环境。是否有用户,是否是浏览器应用程序,是否存在前通道,后通道,是否需要脱机访问,客户端可以保密吗?选择流之前需要考虑的事情。
选择流后,您需要为客户端配置允许的授予。如果仅允许隐式授予类型,则使用客户端凭据的客户端将无法访问资源。
IdentityServer主要用于配置客户端和资源。查看示例,以了解不同的流程以及如何配置它们。
答案 1 :(得分:0)
仅允许客户端使用隐式流来获取用于访问Identity Server保护的资源的令牌:
AllowedGrantTypes = GrantTypes.Implicit,
但是您的客户正在使用Resource Owner Flow:
此赠款类型适用于能够获得 资源所有者的凭证(用户名和密码,通常使用 互动形式)。它还用于迁移现有客户端 使用直接身份验证方案,例如HTTP Basic或Digest 通过将存储的凭据转换为OAuth进行身份验证 访问令牌。
如果您使用的是SPA应用程序,则应使用“隐式流程”获取令牌,而不必将最终用户凭据暴露给第三方。
通常,您有三个应用程序:客户端应用程序,身份服务器(带有用户db)和api。使用隐式流时: