我如何使用身份服务器使用SPA(在我的情况下,它是vuejs)。在他们的javascript客户端的演示应用程序中,他们使用重定向登录页面来获取身份。但我想从我自己的页面登录。如何实现?
答案 0 :(得分:2)
您使用的是npm包oidc-client吗?
它支持多种使用高级UserManager类登录的方法。这些是:
编辑:iframe选项只能用于静默非交互式重新身份验证。典型的情况是,如果您访问令牌已过期(例如,在一小时后),并且您的身份提供商仍然拥有有效会话,则oidc-client可以在后台执行静默登录。
如果您希望获得更多嵌入式体验,并且客户端和身份提供商由同一组织控制,您可以使用资源所有者密码流(password
)并直接从您的spa-ui发送用户名和密码。但请记住,访问令牌不应该长期存在于纯SPA中(<1h),因为它们可能会受到危害。这意味着您的用户必须不断重新输入密码。
如果您需要有关如何实施这些特定解决方案的更多建议,请在评论中告诉我(或编辑您的原始问题)
答案 1 :(得分:1)
我相信我对这个问题有不同的解决方案,这可能更正确,但我不确定!
首先,我发现授权端点有一个名为acr_values
的参数,该参数的值例如为。 idp:Microsoft
指示授权服务器自动重定向到外部提供程序(正是我们想要的!)-但显然仅将此参数发送到 IdentityServer4 并没有什么特别的,它通常被忽略。发生的事情是它已存储并且可以通过您的代码检索。
因此,接下来,我修改/Identity/Account/Login
并通过首先注入IIdentityServerInteractionService
然后在其上调用GetAuthorizationContextAsync
来检索此参数:
var authReq = await _identityServerInteractionService.GetAuthorizationContextAsync(returnUrl);
返回的对象具有一个名为IdP
的属性,该属性从上述idp:...
参数的acr_values
值中获取值。然后,为了避免错误,我测试该值是受支持的外部登录名,因此:
if (!string.IsNullOrEmpty(authReq?.IdP)) {
if (ExternalLogins.All(x => x.Name != authReq.IdP)) {
ModelState.AddModelError(string.Empty, $"Unknown login provider {authReq.IdP}");
}
else {
// ... See below for this part
}
}
然后,我返回一个质询响应,该响应将用户重定向到某个外部提供程序。这部分是从/Identity/Account/ExternalLogin
复制而来,并稍作修改,因此:
var provider = authReq.IdP;
var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
最后,我更改SPA代码以发送此acr_values
参数,该参数基于dotnet angular
模板,该模板使用oidc-client
。该代码位于函数src\api-authorization\authorize.service.ts
中的ensureUserManagerInitialized
中,dotnet模板生成的代码是:
const settings: any = await response.json();
settings.automaticSilentRenew = true;
settings.includeIdTokenInSilentRenew = true;
我将其更改为:
const settings: UserManagerSettings = {
...await response.json(),
automaticSilentRenew: true,
includeIdTokenInSilentRenew: true,
acr_values: 'idp:Microsoft',
};