I've read through similar issues, but am not finding my use case. We have an older MVC application using AspNetIdentity Forms Authentication. We are starting to transition parts of the site over to a new system that uses the IdentityServer3 IdP. From a user's prospective they log into the "old" site. Further into the site they may be redirected to the new site. Currently when this happens they have to log in again to the SSO page to get the new SSO cookie. We are trying to alleviate the dual signin.
On the back end the user's accounts are synchronized between the two authentication databases so their usernames and passwords are always in sync. To reduce the dual signin I was attempting to use the Resource Owner flow at the "old" site's signin page so it performs the Forms Auth signin first then uses Resource Owner to pass the credentials over to the IdentityServer for authentication with the new system. I figure if the SSO server auth happens at this time a cookie can be built so later when they navigate to the SSO protected sites they already have a valid cookie. The problem I'm finding is that the Resource Owner method doesn't seem to issue cookies. I created a MVC controller on the IdentityServer hosting website that performs the Resource Owner authentication. I have the "old" site opening a new browser tab to this page so that the HttpGet controller response will return to the browser if the Set-Cookie is issued. The Resource Owner auth works, I get an access token and the userInfo get works as well. I build up the ClaimsIdentity and SignIn using the OWIN authentication manager. The claims principal shows the user is authenticated, but I'm not getting a cookie. Is there a way to make this happen.
In summary, using their plaintext credentials at "old" system signin I want to pre-authenticate them with SSO to get a cookie so later navigation to SSO sites doesn't ask for a login.
Here is the Resource Owner Auth Get controller.
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();
}
The call to the token endpoint in a API/backchannel call. For setting an SSO cookie, you must redirect the browser to IdentityServer.
IOW - what you want to do is not possible without a browser redirect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With