I have a web forms app currently using either forms authentication (or LDAP which then sets a FormsAuthenticationTicket cookie). I need to add SSO to this project and I'm currently using OpenID/Azure AD to authenticate with. I have the following Startup.cs configured.
public void Configuration(IAppBuilder app)
{
string appId = "<id here>";
string aadInstance = "https://login.microsoftonline.com/{0}";
string tenant = "<tenant here>";
string postLogoutRedirectUri = "https://localhost:21770/";
string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = appId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenReceived = context =>
{
System.Diagnostics.Debug.WriteLine("SecurityTokenReceived");
return Task.FromResult(0);
},
SecurityTokenValidated = async n =>
{
var claims_to_exclude = new[]
{
"aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
};
var claims_to_keep =
n.AuthenticationTicket.Identity.Claims
.Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
if (n.ProtocolMessage.AccessToken != null)
{
claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
//var userInfoClient = new UserInfoClient(new Uri("https://localhost:44333/core/connect/userinfo"), n.ProtocolMessage.AccessToken);
//var userInfoResponse = await userInfoClient.GetAsync();
//var userInfoClaims = userInfoResponse.Claims
// .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token
// .Select(x => new Claim(x.Item1, x.Item2));
//claims_to_keep.AddRange(userInfoClaims);
}
var ci = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
"name", "role");
ci.AddClaims(claims_to_keep);
n.AuthenticationTicket = new AuthenticationTicket(
ci, n.AuthenticationTicket.Properties
);
},
MessageReceived = context =>
{
System.Diagnostics.Debug.WriteLine("MessageReceived");
return Task.FromResult(0);
},
AuthorizationCodeReceived = context =>
{
System.Diagnostics.Debug.WriteLine("AuthorizationCodeReceived");
return Task.FromResult(0);
},
AuthenticationFailed = context =>
{
System.Diagnostics.Debug.WriteLine("AuthenticationFailed");
context.HandleResponse();
context.Response.Write( context.Exception.Message);
return Task.FromResult(0);
}
,
RedirectToIdentityProvider = (context) =>
{
System.Diagnostics.Debug.WriteLine("RedirectToIdentityProvider");
//string currentUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.Path;
//context.ProtocolMessage.RedirectUri = currentUrl;
return Task.FromResult(0);
}
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
I have placed this in page Load event of my master (although it never seems to be getting hit - something else must be causing the authentication process to kick off when I navigate to a page requiring authentication.)
if (!Request.IsAuthenticated)
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Login.aspx" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
My Azure settings are all correct because I am hitting SecurityTokenValidated and AuthorizationCodeReceived functions - I can see my email I am logged in with in the claims information, but I am not sure what to do next. As is I have a never ending loop of authentication requests. I am assuming this is because I have not translated the claim information I have received back into forms authentication ? I attempted to add a dummy auth ticket to the response in AuthorizationCodeReceived but that didn't appear to change anything - I am still getting the looping authentication requests.
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, "<UserName>", DateTime.Now, DateTime.Now.AddMinutes(60), true,"");
String encryptedTicket = FormsAuthentication.Encrypt(authTicket);
context.Response.Cookies.Append(FormsAuthentication.FormsCookieName, encryptedTicket);