使用资源所有者流程发布cookie

时间:2016-11-14 14:12:17

标签: identityserver3

我已经阅读了类似的问题,但我没有找到我的用例。我们有一个使用AspNetIdentity Forms Authentication的旧MVC应用程序。我们开始将站点的一部分转换为使用IdentityServer3 IdP的新系统。从用户的角度来看,他们会登录到旧的"现场。进一步进入该网站后,他们可能会被重定向到新网站。目前,当发生这种情况时,他们必须再次登录到SSO页面以获取新的SSO cookie。我们正试图缓解双重意义。

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

总之,在" old"中使用他们的明文凭据。 system signin我想用SSO预先验证它们以获取cookie,以便稍后导航到SSO站点并不要求登录。

这是资源所有者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();
    }

2 个答案:

答案 0 :(得分:3)

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

IOW - 如果没有浏览器重定向,您无法做什么。

答案 1 :(得分:1)

  

为了减少双重登录,我试图在“旧”站点的登录页面上使用资源所有者流程,因此它首先执行Forms Auth登录,然后使用资源所有者将凭据传递给IdentityServer以进行身份​​验证。系统。我想,如果SSO服务器auth发生在这个时候可以构建一个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中抓取此添加的参数(哈希),并从哈希
  • 中检索用户详细信息
  • 在自定义UserService中,填充登录字段,提供用户友好的消息以继续, - 或者创建一个动态提交表单的自定义ViewService - 或自定义LoginPage。查看here了解样本