IdentityServer4 用户的声明未包含在 JWT 中且未发送到 Web Api
Claims for IdentityServer4 user not included in JWT and not sent to Web Api
按照官方 IdentityServer4 文档,我已经有了一个 MVC 客户端应用程序、IdentityServer4 和一个 Web Api(资源服务器 运行)。 IS4 主页显示用户的所有声明,当使用访问令牌调用 api 时,我们再次得到用户的所有声明。
示例代码可用 here,尽管它可能不是必需的,而且我只是遗漏了一些明显的东西。
无论如何,为了简单起见,我们不要从数据库中获取声明,而只是分配一个随机的硬编码声明:
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.IssuedClaims.Add(new System.Security.Claims.Claim("role", "admin"));
return Task.FromResult(0);
}
...
}
我在启动文件中注册了自定义配置文件服务,现在当我登录 IS4 时,我看到了额外的声明。
但是,当调用网络api(资源服务器)时,JWT 中不包含此附加声明。 api 调用代码:
public async Task<IActionResult> CallApiUsingUserAccessToken()
{
var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
var client = new HttpClient();
client.SetBearerToken(accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View("json");
}
(api 所做的只是 return User.Claims 的列表)。我添加的声明不在那里,当我调试代码并选择访问令牌字符串并在 jwt.io 上对其进行解码时,又没有这样的声明。
问题是:我错过了什么? HttpContext.Authentication.GetTokenAsync 对我的用例不利吗?如果是这样 - 我应该使用什么替代品?
编辑:这是 OpenId 连接选项(在 MVC 客户端上):
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "mvc",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "api1", "offline_access" },
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
});
我想原因是您还没有为您的 API 分配任何声明。这就是我们根本不调用配置文件服务的原因。
这是一个常见问题并且有点不一致,因为我们总是为身份令牌调用配置文件服务。
我们在 1.0.2 中更改了此行为
https://github.com/IdentityServer/IdentityServer4/releases/tag/1.0.2
请再试一次,看看是否能得到预期的结果。
按照官方 IdentityServer4 文档,我已经有了一个 MVC 客户端应用程序、IdentityServer4 和一个 Web Api(资源服务器 运行)。 IS4 主页显示用户的所有声明,当使用访问令牌调用 api 时,我们再次得到用户的所有声明。
示例代码可用 here,尽管它可能不是必需的,而且我只是遗漏了一些明显的东西。
无论如何,为了简单起见,我们不要从数据库中获取声明,而只是分配一个随机的硬编码声明:
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.IssuedClaims.Add(new System.Security.Claims.Claim("role", "admin"));
return Task.FromResult(0);
}
...
}
我在启动文件中注册了自定义配置文件服务,现在当我登录 IS4 时,我看到了额外的声明。
但是,当调用网络api(资源服务器)时,JWT 中不包含此附加声明。 api 调用代码:
public async Task<IActionResult> CallApiUsingUserAccessToken()
{
var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
var client = new HttpClient();
client.SetBearerToken(accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View("json");
}
(api 所做的只是 return User.Claims 的列表)。我添加的声明不在那里,当我调试代码并选择访问令牌字符串并在 jwt.io 上对其进行解码时,又没有这样的声明。
问题是:我错过了什么? HttpContext.Authentication.GetTokenAsync 对我的用例不利吗?如果是这样 - 我应该使用什么替代品?
编辑:这是 OpenId 连接选项(在 MVC 客户端上):
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "mvc",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "api1", "offline_access" },
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
});
我想原因是您还没有为您的 API 分配任何声明。这就是我们根本不调用配置文件服务的原因。
这是一个常见问题并且有点不一致,因为我们总是为身份令牌调用配置文件服务。
我们在 1.0.2 中更改了此行为
https://github.com/IdentityServer/IdentityServer4/releases/tag/1.0.2
请再试一次,看看是否能得到预期的结果。