带有SPA的Identityserver4,无需重定向到登录页面

时间:2017-08-25 19:02:25

标签: identityserver4

我如何使用身份服务器使用SPA(在我的情况下,它是vuejs)。在他们的javascript客户端的演示应用程序中,他们使用重定向登录页面来获取身份。但我想从我自己的页面登录。如何实现?

2 个答案:

答案 0 :(得分:2)

您使用的是npm包oidc-client吗?

它支持多种使用高级UserManager类登录的方法。这些是:

  • 重定向(您在演示中找到的内容)
  • 使用弹出窗口
  • 使用iframe

编辑: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',
};