2016-11-14 31 views
1

我已经阅读了类似的问题,但没有找到我的用例。我们有一个使用AspNetIdentity Forms Authentication的旧MVC应用程序。我们正在开始将部分网站转换为使用IdentityServer3 IdP的新系统。从用户的预期他们登录到“旧”的网站。进一步到网站,他们可能会被重定向到新的网站。目前,当发生这种情况时,他们必须再次登录到SSO页面以获取新的SSO cookie。我们正试图缓解双重签名。使用资源所有者流来发布cookie

在后端用户的账户在两个认证数据库之间同步,因此他们的用户名和密码始终保持同步。为了减少双重登录,我试图在“旧”站点的登录页面上使用资源所有者流,以便首先执行Forms Auth登录,然后使用资源所有者将凭据传递到IdentityServer以与新系统进行身份验证。我想,如果SSO服务器验证在此时发生,则可以在稍后导航到受SSO保护的站点时创建cookie,以便他们拥有有效的cookie。我发现的问题是资源所有者方法似乎没有发出cookie。我在执行资源所有者身份验证的IdentityServer托管网站上创建了一个MVC控制器。我有“旧”站点打开一个新的浏览器选项卡到此页面,以便HttpGet控制器响应将返回到浏览器,如果发出Set-Cookie。资源所有者身份验证的作品,我得到一个访问令牌和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(); 
    } 

回答

3

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

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

+0

谢谢多米尼克。资源所有者端点已经存在于我的identityserver3主机应用程序中,因此它们共享相同的主机名。我也通过打开一个新的浏览器标签到端点来做到这一点(所以浏览器可以使用set-cookie响应)。该终端可以发布SSO cookie吗?还是需要将它们发送到IdSvr3 OWIN中间件创建的端点?如果是这样,你可以对这个过程有所了解吗?我不希望用户必须重新输入他们的SSO凭证,因为我已经拥有凭据。 – gilm0079

1

为了降低双登入我试图使用资源所有者流在“老”网站的登录页面,因此执行窗体身份验证登入第一,然后使用资源所有者超过凭据传递到IdentityServer认证与新系统。我想,如果SSO服务器验证在此时发生,则可以在稍后导航到受SSO保护的站点时创建cookie,以便他们拥有有效的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动态提交表单
    - 或者自定义的LoginPage。检查here样本