【发布时间】:2018-04-13 07:32:30
【问题描述】:
我有一个 Web 表单应用程序,当前使用表单身份验证(或 LDAP,然后设置 FormsAuthenticationTicket cookie)。我需要将 SSO 添加到这个项目,我目前正在使用 OpenID/Azure AD 进行身份验证。我配置了以下 Startup.cs。
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);
}
我已将此放置在我的主人的页面加载事件中(尽管它似乎从未受到打击 - 当我导航到需要身份验证的页面时,肯定是其他原因导致身份验证过程开始。)
if (!Request.IsAuthenticated)
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Login.aspx" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
我的 Azure 设置都是正确的,因为我正在使用 SecurityTokenValidated 和 AuthorizationCodeReceived 函数 - 我可以在索赔信息中看到我登录时使用的电子邮件,但我不确定下一步该做什么。因为我有一个永无止境的身份验证请求循环。我假设这是因为我没有将收到的索赔信息转换回表单身份验证?我试图在 AuthorizationCodeReceived 的响应中添加一个虚拟身份验证票,但这似乎没有改变任何东西 - 我仍然收到循环身份验证请求。
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);
【问题讨论】:
-
您的问题是“永无止境的身份验证请求循环”吗?从记忆中,我很确定我不需要使用任何显式的登录代码——这一切都是通过将正确的东西添加到 startup.cs 来处理的。也许最好的解决方案是使用 OpenID 创建一个全新的项目并查看它自动生成的代码。
-
问题有两个方面 - 永无止境的循环,以及我需要让登录 AD 的人与我认识的用户、他们在我的应用程序中被赋予的角色等相关的事实。(假设这将是一个直接的电子邮件地址比较)。不过我也会看一个新项目。
标签: c# azure single-sign-on openid-connect