微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用Saml2和Okta作为服务提供者的Asp.Net Core 3中的用户身份验证

如何解决使用Saml2和Okta作为服务提供者的Asp.Net Core 3中的用户身份验证

我要用Okta代替我们内部的身份验证服务,并且需要在我们的应用程序中使用Saml2支持SSO。 Okta可以配置为服务提供商,发送SAMLRequest并接收和验证SAMLResponse。到目前为止一切顺利:我能够在Okta中配置Identity Provider,接收断言,并且根据日志,断言已成功验证并自动配置用户

但是从现在开始会发生什么?

  1. 在Idp启动流中,如何将用户重定向到应用程序URL?是仅由IDP配置RelayState吗?我不喜欢这样的想法,即如果我们更改应用程序URL,我们所有的客户都必须进行更改。我希望可以将Idp链接到Okta应用程序,因此重定向URL将由此应用程序配置。
  2. 重定向到我们的应用程序站点后,如何在Asp.Net Core中对用户进行身份验证?我实现了自定义AuthenticationHandler,它读取了Okta在重定向上设置的sid cookie,并从Okta检索了会话信息。从那里我获得用户名并创建Principal。这种方法有效,但我觉得错了-太手工了,我希望Okta.Sdk可以为我做这件事(如果这是正确的身份验证方法)。
  3. 成功进行断言验证后,是否可以将saml令牌交换为OAuth令牌以在应用程序中进行身份验证?

解决方法

基于纯SAML方法回答您的问题:

  1. 您可以使用SP发起的SSO-您将达到在某个页面上登陆的相同目标。假设您充当SAML服务提供商的应用程序驻留在my.app.com上,并且您希望用户在经过身份验证后登陆https://my.app.com/foo/bar。向客户/用户发布https://my.app.com/foo/bar会导致他们最终单击此链接时启动SP-init流。在IdP和SP之间往返后,用户将以https://my.app.com/foo/bar作为最终目的地。

您可以通过应用程序中或堆栈中应用程序上游的其他重定向,使用IdP发起的流程来实现相同的想法。有时称为虚荣 URL。例如,如果个性化URL为https://my.app.com/home,则您的应用或其他上游组件可以将此URL转换为另一个目标URL,并发出重定向到目标的URL。目标URL可以如上所述启动具有RelayState的IdP启动的流或SP启动的流。您的应用或上游组件必须维护虚荣网址和目标URL之间的映射。

  1. 您希望Okta成为您的SAML身份提供者,而您的应用程序要成为SAML服务提供者。您尝试了这种基于cookie的解决方法,因为您不了解如何在.NET应用程序中实现SAML。

Okta没有为充当SAML服务提供者的.NET应用程序提供SAML工具包或SDK,他们建议使用第三方库。 ASP.NET不支持开箱即用的SAML ...这是Okta建议第三方的另一个原因。 (微软不是这些第三方之一)。 SustainsysITFoxTec是两个流行,免费和广泛使用的选择。看一下他们的文档,选择一个并实现它。在那之后,您不必求助于cookie解决方法。

  1. 您的应用程序处理完SAML响应并生成了回复(如果有)后,便完成了身份验证步骤,并且知道了主体的身份。您的应用程序现在可以执行下一步所需的任何操作,包括获取oAuth令牌。下一步不是SAML协议的一部分...除非是全新的SAML流程。

根据您使用Okta作为SAML服务提供者以及与其他SAML身份提供者的身份存储的方法来回答您的问题。流为2跳:SAML IdP-> Okta作为SAML SP->您的应用。

您的应用必须通过前通道回调(类似于SAML)或API回调(类似于oAuth)进行integrate with Okta。后者或多或少要求前者,尽管这条道路上有很多变化。以下答案假定了集成的前端回调样式。

  1. 在处理来自第一跳的SAML响应之后,通过Okta重定向到RelayState中的URL,将通过RelayState“调用”您的应用程序。如果将RelayState设置为https://my.app.com/foo/bar,则在IdP和SP与您的应用程序之间来回切换后,用户将以https://my.app.com/foo/bar作为最终目的地。您的应用必须通过通过IdP发起或SP发起的SAML流激活第一跳来触发此序列。

  2. 在集成的前端回调样式中,您将使用Microsoft接口+ Okta库,如Okta的example所示。

  3. 使用Okta作为您的身份存储和经过身份验证的主体,您可以通过其他步骤从Okta获取令牌。如果您的目标是允许第三方通过Okta从您的应用程序中调用API,请查看API callback style of integration

,

最后,我能够按照自己想要的方式进行工作。目前,Idp发起的流程存在问题,如果找到解决方案,我将更新答案。

  1. 首先配置组织的Okta as Saml Sp for external Saml IdP。 Api文档为here。用户界面说明为here。您应该从外部IdP收到SAML PROTOCOL SETTINGS(IdP颁发者URI,IdP单一登录URL和IdP签名证书)的信息。

  2. 下一步在Okta中创建Web application。您的Login redirect URIs应该以{{1​​}}结尾,否则必须在代码的/authorization-code/callback属性中对其进行配置(请参见下文)。您不需要实现此端点,框架会为您实现。

  3. 现在安装Okta.AspNetCore nuget并将此代码添加到CallbackPath方法中

    ConfigureServices

您将在步骤2中创建的Web应用程序的“常规”标签的底部找到 services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OktaDefaults.MvcAuthenticationScheme; }) .AddCookie() .AddOktaMvc(new OktaMvcOptions { OktaDomain = "<okta_domain>",ClientId = "<app_client_id>",ClientSecret = "<app_client_secret>",Scope = OktaDefaults.Scope,//CallbackPath = "/authorization-code/callback" <= it's default value,change it if required }); app_client_id

  1. 现在是最有趣的部分。如果要触发内部用户(而不是外部Saml Idp用户)的身份验证过程,请调用app_client_secret方法。像这样:

    ChallengeAsync

只要您点击 [ApiController] [Route("[controller]")] public class AuthController : ControllerBase { [HttpGet("login")] public async Task Login() { var properties = new AuthenticationProperties { RedirectUri = "/" }; await HttpContext.ChallengeAsync(properties); } } 网址,就会将您重定向到Okta进行身份验证。

当您要为外部Idp用户触发身份验证过程时,应在/auth/login类中添加idp参数。

AuthenticationProperties

当您点击[ApiController] [Route("[controller]")] public class SsoController : ControllerBase { private readonly ILogger<SsoController> _logger; private readonly IOktaClient _oktaClient; public SsoController(ILogger<SsoController> logger,IOktaClient oktaClient) { _logger = logger; _oktaClient = oktaClient; } [HttpGet] public async Task Sso([FromQuery] string name) { var idpProviders = await _oktaClient.IdentityProviders.ListIdentityProviders(q: name,limit: 1).ToListAsync(); // search is case insensitive and "starts with",and not "exact match" var idp = idpProviders.FirstOrDefault(p => p.Name.Equals(name,StringComparison.InvariantCultureIgnoreCase)); if (idp == null) { _logger.LogWarning($"idp name '{name}' doesn't exist"); var authenticationProperties = new AuthenticationProperties { RedirectUri = "/" }; await HttpContext.ForbidAsync(authenticationProperties); } else { var properties = new AuthenticationProperties { RedirectUri = "/",Items = { ["idp"] = idp.Id } }; await HttpContext.ChallengeAsync(properties); } } } url时,您将寻找在步骤1中定义的/sso?name=MySamlIdp身份提供者,并使用其ID告诉Okta将用户重定向到哪里进行身份验证。 Okta.Sdk nuget中定义的MySamlIdp

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。