问题描述
我已按照此处的指示添加了更改密码策略:
稍作调试并查看其他示例后,ConfigureAuth中最后指定的策略是唯一起作用的策略.
下面是代码:
公共无效的ConfigureAuth(IAppBuilder应用){//Azure webapps必需,因为默认情况下它们强制TLS 1.2,并且此项目尝试1.0ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);app.UseCookieAuthentication(new CookieAuthenticationOptions{//与ASP.NET Web主机兼容的Cookie管理器CookieManager =新的SystemWebChunkingCookieManager()});app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.EditProfilePolicyId));app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.ResetPasswordPolicyId));app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.DefaultPolicy));}私有OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(字符串策略){返回新的OpenIdConnectAuthenticationOptions{//使用租户和策略信息生成元数据地址MetadataAddress = String.Format(Globals.WellKnownMetadata,Globals.Tenant,policy),//这些是标准的OpenID Connect参数,其值从web.config中提取ClientId = Globals.ClientId,RedirectUri = Globals.RedirectUri,PostLogoutRedirectUri = Globals.RedirectUri,//为每种通知类型指定回调通知=新的OpenIdConnectAuthenticationNotifications{RedirectToIdentityProvider = OnRedirectToIdentityProvider,AuthorizationCodeReceived = OnAuthorizationCodeReceived,AuthenticationFailed = OnAuthenticationFailed,},//指定指定Name属性的声明类型.TokenValidationParameters =新的TokenValidationParameters{NameClaimType =名称",ValidateIssuer = false,SaveSigninToken = true//将令牌保存在引导上下文中},//通过将所有请求的范围附加到一个字符串中(以空格分隔)来指定范围Scope = $" openid profile offline_access {Globals.ReadTasksScope} {Globals.WriteTasksScope}",ResponseType ="id_token",//与ASP.NET Web主机兼容的Cookie管理器CookieManager =新的SystemWebCookieManager()};}/**在每次调用Azure AD B2C时,请检查是否在OWIN上下文中指定了策略(例如,配置文件编辑或密码重置策略).*如果是这样,请在拨打电话时使用该策略.另外,请勿请求代码(因为不需要).*/私有任务OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification< OpenIdConnectMessage,OpenIdConnectAuthenticationOptions>通知){var policy = notification.OwinContext.Get< string>("Policy");如果(!string.IsNullOrEmpty(policy)&!policy.Equals(Globals.DefaultPolicy)){notification.ProtocolMessage.Scope = OpenIdConnectScope.OpenId;notification.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(Globals.DefaultPolicy.ToLower(),policy.ToLower());}返回Task.FromResult(0);}/**捕获身份验证中间件收到的任何故障并适当处理*/私有任务OnAuthenticationFailed(AuthenticationFailedNotification< OpenIdConnectMessage,OpenIdConnectAuthenticationOptions>通知){notification.HandleResponse();//处理尝试从登录页面重置密码时Azure AD B2C引发的错误代码//因为注册或登录策略"不支持密码重置,如果(notification.ProtocolMessage.ErrorDescription!= null&& notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))){//如果用户单击了重置密码链接,则重定向到重置密码路由notification.Response.Redirect("/User/ResetPassword2");}否则,如果(notification.Exception.Message =="access_denied"){notification.Response.Redirect("/");}别的{notification.Response.Redirect("/Home/Error?message =" + notification.Exception.Message);}返回Task.FromResult(0);}
在上面的代码中,如果我最后调用 app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.EditProfilePolicyId))
,则在加载应用程序并转到/user/signin时,它实际上将通过更改密码"我为其配置的策略.
如果我最后调用 app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.ResetPasswordPolicyId));
,那么启动应用程序时将带我通过重置密码策略.
最后,弄清楚了.我将控制器中的处理程序更改为以下内容:
public void ChangePassword(){如果(Request.IsAuthenticated){//让中间件知道您正在尝试使用重置密码策略(请参阅Startup.Auth.cs中的OnRedirectToIdentityProvider)HttpContext.GetOwinContext().Set("Policy",Globals.EditProfilePolicyId);HttpContext.GetOwinContext().Authentication.Challenge(新的AuthenticationProperties {RedirectUri ="/"});}}
在上面,请确保不要像我一样将策略指定为 Authentication.Challenge()
方法的第二个参数.
还要确保在Startup.Auth.cs中,您只注入一次OpenId Auth中间件-对于默认策略.例如SUSI政策.基本上严格按照此Startup.Auth.cs 进行操作.您会看到 app.UseOpenIdConnectAuthentication
仅使用默认登录策略被调用一次.您无需在此处为其他策略调用它.控制器处理程序将分配一个策略".进入上下文,并将其重定向到身份提供者,并将触发Startup.Auth.cs中指定的 OnRedirectToIdentityProvider
委托,该委托将检查"policy"属性.在owin上下文中,并用新策略替换默认策略,并相应地重定向到该策略.
I have added the change password policy as directed here: https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-password-change-policy?pivots=b2c-custom-policy
How can I now direct the user when they click the "Change Password" link in my app to direct them to this policy?
I am trying this below but doesn't seem to work (Globals.EditProfilePolicyId is my change password profile's policy id):
public void ChangePassword()
{
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = Globals.RedirectUri }, Globals.EditProfilePolicyId);
}
I keep getting this browser popup to enter credentials even though I'm logged in.:
After debugging it a bit and looking at some other samples, the policy that is last specified in ConfigureAuth, is the only one that has any effect.
Below is the code:
public void ConfigureAuth(IAppBuilder app)
{
// Required for Azure webapps, as by default they force TLS 1.2 and this project attempts 1.0
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// ASP.NET web host compatible cookie manager
CookieManager = new SystemWebChunkingCookieManager()
});
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.EditProfilePolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.ResetPasswordPolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.DefaultPolicy));
}
private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(string policy)
{
return new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(Globals.WellKnownMetadata, Globals.Tenant, policy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = Globals.ClientId,
RedirectUri = Globals.RedirectUri,
PostLogoutRedirectUri = Globals.RedirectUri,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
// Specify the claim type that specifies the Name property.
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
ValidateIssuer = false,
SaveSigninToken = true //save the token in the bootstrap context
},
// Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
Scope = $"openid profile offline_access {Globals.ReadTasksScope} {Globals.WriteTasksScope}",
ResponseType = "id_token",
// ASP.NET web host compatible cookie manager
CookieManager = new SystemWebCookieManager()
};
}
/*
* On each call to Azure AD B2C, check if a policy (e.g. the profile edit or password reset policy) has been specified in the OWIN context.
* If so, use that policy when making the call. Also, don't request a code (since it won't be needed).
*/
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(Globals.DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScope.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(Globals.DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
/*
* Catch any failures received by the authentication middleware and handle appropriately
*/
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/User/ResetPassword2");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
In the above code if I call app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.EditProfilePolicyId))
last, then when loading the app and going to /user/sign in, it will actually go through the "Change Password" policy that I have configured it for.
If I call app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(Globals.ResetPasswordPolicyId));
last, then it will take me through reset password policy when launching the app.
Finally, figured it out. I changed my handler in the controller to the following:
public void ChangePassword()
{
if (Request.IsAuthenticated)
{
// Let the middleware know you are trying to use the reset password policy (see OnRedirectToIdentityProvider in Startup.Auth.cs)
HttpContext.GetOwinContext().Set("Policy", Globals.EditProfilePolicyId);
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" });
}
}
In the above, make sure you DO NOT specify the policy as the second parameter to the Authentication.Challenge()
method like I was doing.
Also make sure that in Startup.Auth.cs, you only inject the OpenId Auth middleware once - for the default policy. e.g. the SUSI policy. Basically follow this Startup.Auth.cs exactly. You will see that app.UseOpenIdConnectAuthentication
is only being called once - with the default signin policy. You do not need to call it for other policies here. The controller handler will assign a "policy" to owin context, and redirect it to the identity provider and will trigger the OnRedirectToIdentityProvider
delegate specified in the Startup.Auth.cs which will then check the "policy" in the owin context, and replace the default policy with the new one and redirect to this policy accordingly.
这篇关于如何在我的应用中将用户定向到广告b2c更改密码政策的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!