如何在.net核心Web应用程序和Web API之间传递/验证Open ID令牌?

我们具有以下架构:

  • 使用剃须刀页面,jQuery等作为UI的.NET Core 3.1 Web应用程序(不是角度应用程序)
  • .net core 3.1 Web api应用程序充当我们的api层
  • Okta作为我们的身份提供者

我已经在Web应用程序中实现了Okta小部件和中间件。用户可以登录,然后发生这种情况,我便可以获取ClaimsPrincipal,访问其所有范围并访问通过开放ID存储的任何自定义配置文件数据。我可以通过[授权]装饰来保护视图。所有这些都运行良好。

我现在要做的是在API端实现安全性检查。我花了很多小时来研究示例,发现了很多示例,但是我错过了一些明显的东西,或者我正在做的事情是独一无二的(而且我无法想象我正在做的事情是独一无二的)。基本上我需要做的是:

  • 已让网络应用将auth和id令牌传递给api
  • 让api能够验证令牌,然后从id令牌中解密用户信息

然后,这将允许我在API方面实现必要的安全性逻辑。假设它是用于返回客户订单的API-那么,我需要确保调用它的用户是管理员或实际客户(因此,我不会将客户数据返回给不应该看到的人)。我已经弄清了所有角色,但我一生无法弄清楚如何通过令牌确定某人是谁?

传递令牌非常简单,但是如何将令牌从ClaimsPrincipal对象中取出呢?还是我需要在用户登录后调用Okta API来专门获取访问和ID令牌?

然后,我当然必须弄清楚如何使API端正确验证和解析发送的令牌。

如果有人可以帮助我开始使用该示例,或者为我指明正确的方向,例如,我将不胜感激。至此,我已经阅读了所有有关Owin,OpenID,Okta,.net核心中的授权的文章,我可以找到。

qwweerrttyyuuiioop 回答:如何在.net核心Web应用程序和Web API之间传递/验证Open ID令牌?

多亏了卡梅隆·廷克(Cameron Tinker)的建议,我才能够使它成功。有几件事使我不胜其烦,因此,如果有人遇到相同的情况,我将在这里分享。

如果您使用Okta,则可以通过Okta中间件软件包来完成所有这些操作。您可以仅使用c#OpenID库来完成此操作,但是Okta.AspNetCore库将帮助您解决问题。

首先,您在Web应用程序中注册中间件。 Okta在其网站上有很多此类示例,而且非常简单。

在您的网络应用中,您可以使用它来获取令牌(当然是在用户通过身份验证之后)

await context.HttpContext?.GetTokenAsync("id_token")

通过标准机制,在API调用中将其作为标头的一部分发送:

"Authorization" : "Bearer [token]"

在Web API端,您使用相同的Okta.AspNetCore中间件软件包,然后可以使用[Authorize]装饰控制器以对它们执行身份验证。这是我被绊倒的地方。如果您不是使用Okta中的默认身份验证服务器来,并且已为您的应用程序设置了自定义服务器,则需要在配置中指定它和受众群体:

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
                options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
                options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
            })
            .AddOktaWebApi(new OktaWebApiOptions()
            {
                OktaDomain = oktaDomain,AuthorizationServerId = authServerId,Audience = clientId
            });

            services.AddAuthorization();

我已经完全忘记了受众部分-通过令牌验证的工作方式,该部分是必需的。

从那里开始,中间件负责为您填充ClaimsPrincipal,因此您可以通过ClaimsPrincipal(HttpContext.User)访问用户信息。我最终创建了一个“ CurrentUserService”,并将其拉入其自己的库中,以便在那里整合所有身份验证处理程序。从而允许我的Web应用程序和Web API代码以相同的方式检查权限并检索有关当前用户的信息。如果您有兴趣,可以在这里找到该代码:

    public interface ICurrentUserService
    {
        public ClaimsPrincipal GetCurrentUser();

        public string GetCurrentUserDisplayName();

        public string GetCurrentUserFullName();

        public string GetCurrentUserId();

        public DateTime? GetCurrentUserDob();

        public string GetCurrentUserGender();

        public AddressFromClaimsDTO GetCurentUserAddress();

        public bool IsAuthenticated();
    }

    public class CurrentUserService : ICurrentUserService
    {

        private const string FULL_ADDRESS_CLAIM_TYPE = "address";

        private readonly IHttpContextAccessor _context;

        public CurrentUserService(IHttpContextAccessor context)
        {
            _context = context;
        }

        /// <summary>
        /// Gets whether or not the current user context is authenticated.
        /// </summary>
        /// <returns></returns>
        public bool IsAuthenticated()
        {
            return GetCurrentUser().Identity.IsAuthenticated;
        }

        /// <summary>
        /// Gets the current user's address.
        /// TODO: tie this into our address data model... but if addresses live in Okta what does that mean?
        /// </summary>
        /// <returns></returns>
        public AddressFromClaimsDTO GetCurentUserAddress()
        {
            var addressClaim = GetClaim(FULL_ADDRESS_CLAIM_TYPE);

            if (addressClaim != null)
            {
                //var parseValue = addressClaim.Value.ToString().Replace("{address:","{\"address\":");
                var address = JsonSerializer.Deserialize<AddressFromClaimsDTO>(addressClaim.Value.ToString());
                return address;
            }
            else
            {
                return new AddressFromClaimsDTO();
            }
        }

        public ClaimsPrincipal GetCurrentUser()
        {
            return _context.HttpContext.User;
        }

        public string GetCurrentUserDisplayName()
        {
            return GetCurrentUser().Identity.Name;
        }

        public string GetCurrentUserFullName()
        {
            throw new NotImplementedException();
        }

        public string GetCurrentUserId()
        {
            throw new NotImplementedException();
        }

        public DateTime? GetCurrentUserDob()
        {
            var claim = GetClaim("birthdate");

            if (claim != null && !string.IsNullOrEmpty(claim.Value))
            {
                return DateTime.Parse(claim.Value);
            }
            else
            {
                return null;
            }
        }

        public string GetCurrentUserGender()
        {
            return GetClaim("gender")?.Value.ToString();
        }


        public Claim GetClaim(string claimType)
        {
            return _context.HttpContext.User.FindFirst(x => x.Type == claimType);
        }

    }
,

在这种情况下,您的ID提供商Okta将颁发OpenID Connect授权承载令牌,您需要将其传递给要保护的任何应用程序。

在应用程序的Web Api端,您将需要注册中间件来处理Okta的OpenID Connect令牌处理。然后,您可以使用@wip Scenario Outline: Browse to Target URL having multiple specified WebElements Given Using browser "<theBrowser>" When targetURL "<targetURL>" is entered Then Expected Page "<targetURL>" is loaded And Loaded Page displays webelements with locator "<locatorID>" Examples: | theBrowser | targetURL | locatorID | | chrome | www.qaweb.net/ | //*[@id="loginwithajaxwidget-5"] | | firefox | www.ganbatte.net/ | //*[@id="loginwithajaxwidget-2"] | 装饰控制器/操作,并可以检查身份声明。

本文链接:https://www.f2er.com/2789000.html

大家都在问