问题描述
有两个应用程序:
- 启用 OpenID 连接的 OneLogin 身份提供商。
- 我的 ASP.NET 核心 WEB API,它是前端应用程序的资源服务器。
最初我只实现了授权逻辑,使用以下代码:
serviceCollection
.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = clientId;
options.Authority = authority;
});
我为我的控制器设置了 [AuthorizeAttribute] 并且授权逻辑运行良好。 现在我需要在我的控制器中获取有关用户的信息。为此,我想使用 OpenID 信息。我通过添加 OpenID 连接修改了我的代码:
serviceCollection
.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = clientId;
options.Authority = authority;
})
.AddOpenIdConnect(options =>
{
options.ClientId = clientId;
options.Authority = authority;
options.GetClaimsFromUserInfoEndpoint = true;
});
但我在我的控制器 (User.Identity) 中仍然只看到 access_token 声明。我错过了什么?
解决方法
您可以像这样扩展 HttpContext
(不需要这样做,但是在控制器中调用会更好一些,您可以将代码直接放入控制器中)。
public static class AuthExtensions
{
public static string GetUserId(this HttpContext httpContext)
{
if (httpContext.User == null)
return string.Empty;
return httpContext.User.Claims.Single(x => x.Type == "id").Value;
}
public static UserRole GetUserRole(this HttpContext httpContext)
{
if (httpContext.User == null)
throw new InvalidOperationException("User not set on httpContext.");
var roleStr = httpContext.User.Claims.Single(x => x.Type == ClaimTypes.Role).Value;
return (UserRole) Enum.Parse(typeof(UserRole),roleStr);
}
}
然后您可以从您的控制器 var userId = Request.HttpContext.GetUserId();
调用它们。请注意,声明中的内容取决于您在创建令牌时放入其中的内容。例如,您可能没有角色。如果您不知道,您可以通过将令牌复制/粘贴到 jwt.io 中来查找令牌包含的内容。
你有两个选择。
您可以将所需的声明添加到访问令牌(在 ApiScope 或 ApiResources 中),然后通过 API 中的 AddJwtBearer 进行访问。
或者,您可以获取访问令牌并将其发送到令牌 introspection 端点,从响应中您可以获得有关用户的更多详细信息。您还可以使用访问令牌手动调用 userinfo 端点。但是,AddJWtBearer 不会为您调用这些端点。 IdentityModel 中的辅助类可以帮助您做到这一点。
将 AddOpenIdConnect 添加到 API 中,只是为了获取用户详细信息是错误的做法。