首页 > 解决方案 > 使用 IdentityServer4 向 SSO 动态添加步骤

问题描述

在尝试从 identityServer4 QuickStart 9自定义快速入门之一时,我遇到了一些问题,基本上,我需要创建一个单点登录应用程序,该应用程序将被多个服务、多个 Web 应用程序、一个电子和 PhoneGap 应用程序使用。

目前,我的流程比简单地验证用户要复杂一些,见下文:

用户输入登录名和密码 -> 系统验证这条数据并向用户提供可供选择的可能子应用程序的选择 -> 用户选择其中一个子应用程序 -> 系统现在要求用户选择一个可能的子应用程序此应用程序的环境(可以自定义暂存/生产)

我想在身份验证层上执行此流程,否则,我将不得不在所有应用程序上复制所有这些步骤,而且我当然希望身份验证具有单独的开发生命周期。

目前,我正在尝试进行 3 处修改以实现此目的:

  1. PersistentGrantStore -> 使用授权键作为参考将此步骤保存到自定义表中。(类似于密钥/应用程序/环境)

  2. IProfileService -> 添加代表此步骤的自定义声明 (卡在此处),并且是临时的,它们仅对此令牌和后续刷新有意义。

  3. authenticationHandler -> 验证用户是否完成了所有步骤

由于我的水疗中心的应用程序,我还需要对令牌端点进行修改以通过自定义标头接受这两个参数

我的问题归结为:有更好的方法吗?我是否过于复杂了?

对不起,如果这个问题太基本了,但我不习惯做这种类型的身份验证。

标签: asp.netasp.net-coresingle-sign-onsingle-page-applicationidentityserver4

解决方案


如果我理解正确,以下方式可能会有所帮助。

创建一个临时 cookie 并在用户登录后显示选择页面:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model, string button)
{
    if (ModelState.IsValid)
    {
        var loginResult = .service.Check(model.Username, model.Password);
        if (loginResult.IsSucceed)
        {
            await HttpContext.SignInAsync("TempCookies", loginResult.Principal);
            var selectViewModel = new SelectViewModel();
            model.ReturnUrl = model.ReturnUrl;
            return View("SelectUserAndEnvironment", selectViewModel);
        }
        else
        {
            ModelState.AddModelError("", "****.");
            return View(model);
        }
    }
    return View(model);
}

添加您想要的声明并登录IdentityServerConstants.DefaultCookieAuthenticationScheme

[HttpPost]
[Authorize(AuthenticationSchemes = "TempCookies")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SelectUserAndEnvironment(SelectModel model)
{
    // add claims from select input
    var claims = new List<Claim>();
    claims.Add(new Claim(<Type>, <Value>));
    var p = new ClaimsPrincipal(new ClaimsIdentity(auth.Principal?.Identity, claims));
    await HttpContext.SignOutAsync("TempCookies");
    await HttpContext.SignInAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme, p);
    return Redirect(model.ReturnUrl);
}

并在ProfileService

public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
    // you can get claims added in login action by using context.Subject.Claims
    // other stuff
    context.IssuedClaims = claims;
    await Task.CompletedTask;
}

最后在中添加身份验证方案Startup.cs

services.AddAuthentication()
            .AddCookie("TempCookies", options =>
            {
                options.ExpireTimeSpan = new TimeSpan(0, 0, 300);
            })

如果要使用外部登录,请适当更改上述代码。


推荐阅读