【问题标题】:Using Resource Owner Flow to issue a cookie使用资源所有者流发出 cookie
【发布时间】:2017-03-28 05:00:48
【问题描述】:

我已经阅读了类似的问题,但没有找到我的用例。我们有一个使用 AspNetIdentity Forms 身份验证的旧 MVC 应用程序。我们开始将站点的某些部分转换到使用 IdentityServer3 IdP 的新系统。从用户的角度来看,他们登录到“旧”站点。进一步进入站点,他们可能会被重定向到新站点。目前,当发生这种情况时,他们必须再次登录 SSO 页面才能获取新的 SSO cookie。我们正在尝试缓解双重登录问题。

在后端,用户的帐户在两个身份验证数据库之间同步,因此他们的用户名和密码始终保持同步。为了减少双重登录,我尝试在“旧”站点的登录页面上使用资源所有者流程,因此它首先执行表单身份验证登录,然后使用资源所有者将凭据传递给 IdentityServer 以使用新系统进行身份验证。我想如果此时 SSO 服务器身份验证发生,可以构建一个 cookie,以便稍后当他们导航到受 SSO 保护的站点时,他们已经有一个有效的 cookie。我发现的问题是资源所有者方法似乎没有发出 cookie。我在 IdentityServer 托管网站上创建了一个执行资源所有者身份验证的 MVC 控制器。我让“旧”站点打开一个新的浏览器选项卡到该页面,以便在发出 Set-Cookie 时 HttpGet 控制器响应将返回到浏览器。资源所有者身份验证有效,我获得了访问令牌,并且 userInfo 也有效。我使用 OWIN 身份验证管理器构建 ClaimsIdentity 和 SignIn。声明主体显示用户已通过身份验证,但我没有收到 cookie。有没有办法做到这一点。

总之,在“旧”系统登录时使用他们的明文凭据,我想使用 SSO 对他们进行预身份验证以获取 cookie,以便以后导航到 SSO 站点时不需要登录。

这里是 Resource Owner Auth Get 控制器。

public ActionResult LoginGet(string username, string password) {
        try {
            username = HttpUtility.UrlDecode(username);
            password = HttpUtility.UrlDecode(password);
            //create identityserver sso cookie as well
            var tokenClient = new TokenClient(
                "https://localhost.fiddler:44333/core/connect/token",
                "clientId",
                "secret"
                );
            var scopes = "openid profile sampleApi roles";
            var token = tokenClient.RequestResourceOwnerPasswordAsync(username, password, scopes).Result;
            if (token != null && !String.IsNullOrWhiteSpace(token.AccessToken)) {
                var claims = new List<Claim>();
                var claimsClient = new UserInfoClient(new Uri("https://localhost.fiddler:44333/core/connect/userinfo"), token.AccessToken);
                var userInfo = claimsClient.GetAsync().Result;
                userInfo.Claims.ToList().ForEach(t => claims.Add(new Claim(t.Item1, t.Item2)));
                claims.Add(new Claim("token", token.AccessToken));
                var claimsId = new ClaimsIdentity(claims, "Cookies");
                Request.GetOwinContext().Authentication.SignIn(claimsId);
                ViewBag.Worked = true;
                ClaimsPrincipal cp = Request.GetOwinContext().Authentication.User;
                if(cp != null) {
                    ViewBag.IsAuthed = cp.Identity.IsAuthenticated;
                }
                return View();
            }
        } catch (Exception ex) {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        return View();
    }

【问题讨论】:

    标签: identityserver3


    【解决方案1】:

    在 API/反向通道调用中对令牌端点的调用。要设置 SSO cookie,您必须将浏览器重定向到 IdentityServer。

    IOW - 如果没有浏览器重定向,您想要做的事情是不可能的。

    【讨论】:

    • 谢谢多米尼克。我的 identityserver3 主机应用程序上已经存在资源所有者端点,因此它们共享相同的主机名。我还通过向端点打开一个新的浏览器选项卡来执行此操作(因此浏览器可以使用 set-cookie 响应)。该端点可以发出 SSO cookie 吗?还是我需要将它们发送到 IdSvr3 OWIN 中间件创建的端点?如果是这样,你能解释一下这个过程吗?我不希望用户必须为 SSO 重新输入他们的凭据,因为我已经有了凭据。
    【解决方案2】:

    为了减少双重登录,我试图在“旧”站点的登录页面上使用资源所有者流程,因此它首先执行表单身份验证登录,然后使用资源所有者将凭据传递给 IdentityServer 以使用新站点进行身份验证系统。我想如果此时 SSO 服务器身份验证发生,可以构建一个 cookie,以便稍后当他们导航到受 SSO 保护的站点时,他们已经有一个有效的 cookie。

    即使在同一个主机名中,您也无法从另一个路径访问或设置路径(此处为 IdentityServer)的 cookie(确实有一些棘手的方法可以做到这一点,但当然,您会知道要设置什么等) .见https://security.stackexchange.com/q/12439

    总之,在“旧”系统登录时使用他们的明文凭据,我想使用 SSO 对他们进行预身份验证以获取 cookie,以便以后导航到 SSO 站点时不需要登录。

    实现此目的的一个非常简单的方法是使用授权端点,该端点允许将额外的身份验证相关信息传递给用户服务。 https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html。然后,在登陆 IdentityServer 的登录页面时,您可以检索用户的身份。

    为了简单起见:

    • 从您的“旧”系统中,加密用户的详细信息或提供某种形式的唯一哈希
    • 重定向到 IdentityServer 或 OWIN 中间件时在授权端点参数中包含哈希
    • 在您的自定义用户服务中获取此添加的参数(哈希)并从哈希中检索用户详细信息
    • 从您的自定义 UserService 中,填充登录字段,提供用户友好的消息以继续, -- 或者创建一个自定义 ViewService 动态提交表单
      -- 或自定义登录页面。查看here 获取样品

    【讨论】:

      猜你喜欢
      • 2017-11-14
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 2017-05-18
      • 2014-08-05
      • 2013-11-23
      • 2016-04-28
      • 2023-03-19
      相关资源
      最近更新 更多