如何在 ASP.NET 核心 WEB API 控制器中获取 OpenID 信息

问题描述

有两个应用程序:

  1. 启用 OpenID 连接的 OneLogin 身份提供商。
  2. 我的 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 中,只是为了获取用户详细信息是错误的做法。