如何解决使用Saml2和Okta作为服务提供者的Asp.Net Core 3中的用户身份验证
我要用Okta代替我们内部的身份验证服务,并且需要在我们的应用程序中使用Saml2支持SSO。 Okta可以配置为服务提供商,发送SAMLRequest
并接收和验证SAMLResponse
。到目前为止一切顺利:我能够在Okta中配置Identity Provider,接收断言,并且根据日志,断言已成功验证并自动配置了用户。
但是从现在开始会发生什么?
- 在Idp启动流中,如何将用户重定向到应用程序URL?是仅由IDP配置
RelayState
吗?我不喜欢这样的想法,即如果我们更改应用程序URL,我们所有的客户都必须进行更改。我希望可以将Idp链接到Okta应用程序,因此重定向URL将由此应用程序配置。 - 重定向到我们的应用程序站点后,如何在Asp.Net Core中对用户进行身份验证?我实现了自定义
AuthenticationHandler
,它读取了Okta在重定向上设置的sid
cookie,并从Okta检索了会话信息。从那里我获得用户名并创建Principal
。这种方法有效,但我觉得错了-太手工了,我希望Okta.Sdk可以为我做这件事(如果这是正确的身份验证方法)。 - 成功进行断言验证后,是否可以将saml令牌交换为OAuth令牌以在应用程序中进行身份验证?
解决方法
基于纯SAML方法回答您的问题:
- 您可以使用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之间的映射。
- 您希望Okta成为您的SAML身份提供者,而您的应用程序要成为SAML服务提供者。您尝试了这种基于cookie的解决方法,因为您不了解如何在.NET应用程序中实现SAML。
Okta没有为充当SAML服务提供者的.NET应用程序提供SAML工具包或SDK,他们建议使用第三方库。 ASP.NET不支持开箱即用的SAML ...这是Okta建议第三方的另一个原因。 (微软不是这些第三方之一)。 Sustainsys和ITFoxTec是两个流行,免费和广泛使用的选择。看一下他们的文档,选择一个并实现它。在那之后,您不必求助于cookie解决方法。
- 您的应用程序处理完SAML响应并生成了回复(如果有)后,便完成了身份验证步骤,并且知道了主体的身份。您的应用程序现在可以执行下一步所需的任何操作,包括获取oAuth令牌。下一步不是SAML协议的一部分...除非是全新的SAML流程。
根据您使用Okta作为SAML服务提供者以及与其他SAML身份提供者的身份存储的方法来回答您的问题。流为2跳:SAML IdP-> Okta作为SAML SP->您的应用。
您的应用必须通过前通道回调(类似于SAML)或API回调(类似于oAuth)进行integrate with Okta。后者或多或少要求前者,尽管这条道路上有很多变化。以下答案假定了集成的前端回调样式。
-
在处理来自第一跳的SAML响应之后,通过Okta重定向到RelayState中的URL,将通过RelayState“调用”您的应用程序。如果将RelayState设置为
https://my.app.com/foo/bar
,则在IdP和SP与您的应用程序之间来回切换后,用户将以https://my.app.com/foo/bar
作为最终目的地。您的应用必须通过通过IdP发起或SP发起的SAML流激活第一跳来触发此序列。 -
在集成的前端回调样式中,您将使用Microsoft接口+ Okta库,如Okta的example所示。
-
使用Okta作为您的身份存储和经过身份验证的主体,您可以通过其他步骤从Okta获取令牌。如果您的目标是允许第三方通过Okta从您的应用程序中调用API,请查看API callback style of integration。
最后,我能够按照自己想要的方式进行工作。目前,Idp发起的流程存在问题,如果找到解决方案,我将更新答案。
-
首先配置组织的Okta as Saml Sp for external Saml IdP。 Api文档为here。用户界面说明为here。您应该从外部IdP收到
SAML PROTOCOL SETTINGS
(IdP颁发者URI,IdP单一登录URL和IdP签名证书)的信息。 -
下一步在Okta中创建Web application。您的
Login redirect URIs
应该以{{1}}结尾,否则必须在代码的/authorization-code/callback
属性中对其进行配置(请参见下文)。您不需要实现此端点,框架会为您实现。 -
现在安装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
。
-
现在是最有趣的部分。如果要触发内部用户(而不是外部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 举报,一经查实,本站将立刻删除。