我有一个ASP.Net MVC应用程序,Owin,我也使用Azure Active Directory身份验证.
我想在用户重定向到Azure AD身份验证页面时传递参数.因此,当用户登录或注册时,我想将ProjectId(int)作为参数传递.
在用户登录/注册并重定向到我的应用程序后,我希望收到作为参数传递的ProjectId.
我怎样才能做到这一点?
// The ACR claim is used to indicate which policy was executed public const string AcrClaimType = "http://schemas.microsoft.com/claims/authnclassreference"; public const string PolicyKey = "b2cpolicy"; private const string OidcMetadataSuffix = "/.well-known/openid-configuration"; public void ConfigureAuth(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions { // These are standard OpenID Connect parameters,with values pulled from web.config ClientId = ClientId,RedirectUri = RedirectUri,PostlogoutRedirectUri = RedirectUri,UseTokenLifetime = false,Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = AuthenticationFailed,RedirectToIdentityProvider = OnRedirectToIdentityProvider,SecurityTokenValidated = OnSecurityTokenValidated },Scope = "openid",ResponseType = "id_token",// The PolicyConfigurationManager takes care of getting the correct Azure AD authentication // endpoints from the OpenID Connect Metadata endpoint. It is included in the PolicyAuthHelpers folder. ConfigurationManager = new PolicyConfigurationManager( string.Format(CultureInfo.InvariantCulture,AadInstance,Tenant,"/v2.0",OidcMetadataSuffix),new[] { SignUpPolicyId,SignInPolicyId,ProfilePolicyId }),// This piece is optional - it is used for displaying the user's name in the navigation bar. TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" } }; app.USEOpenIdConnectAuthentication(options); } private Task OnRedirectToIdentityProvider( RedirectToIdentityProviderNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> notification) { if (notification.ProtocolMessage.RequestType == OpenIdConnectRequestType.logoutRequest) { var currentPolicy = notification.OwinContext.Authentication.AuthenticationResponseRevoke.AuthenticationTypes .FirstOrDefault(x => x.StartsWith("b2c")); notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.Split('?')[0]; notification.ProtocolMessage.Parameters.Add("p",currentPolicy); } else { **// The value right now for the state is sort of "hijacked" and assigned by Microsoft** //notification.ProtocolMessage.Parameters["state"] = "OpenIdConnect.AuthenticationProperties=sRt-teBcxsd239viWo...... "; var currentPolicy = notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties .Dictionary[PolicyKey]; notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.Split('?')[0]; notification.ProtocolMessage.Parameters.Add("p",currentPolicy); } return Task.FromResult(0); } private async Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> notification) { await MyClass.CreatePrincipal(notification.AuthenticationTicket.Identity); } private Task AuthenticationFailed( AuthenticationFailedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> notification) { notification.HandleResponse(); notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message); return Task.FromResult(0); }
解决方法
与Gaurav建议的相似,但增加了一些特殊的考虑因素.基本上,状态是由Owin中间件使用的,所以当你可以注入自己的东西时,你需要确保在Owin中间件试图使用它之前将其还原,否则你将获得auth错误.
这实际上是我回答了一个非常相似的问题:
Custom parameter with Microsoft.Owin.Security.OpenIdConnect and AzureAD v 2.0 endpoint
在Startup.Auth.cs中,当您设置OpenIdConnectAuthenticationOptions时,您需要添加以下内容:
app.USEOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { //... Notifications = new OpenIdConnectAuthenticationNotifications { RedirectToIdentityProvider = OnRedirectToIdentityProvider,MessageReceived = OnMessageReceived },});
并使用RedirectToIdentityProvider注入您的参数,类似于:
private static Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> notification) { var stateQueryString = notification.ProtocolMessage.State.Split('='); var protectedState = stateQueryString[1]; var state = notification.Options.StateDataFormat.Unprotect(protectedState); state.Dictionary.Add("mycustomparameter","myvalue"); notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state); return Task.FromResult(0); }
然后使用MessageReceived来提取它,如下所示:
private static Task OnMessageReceived(MessageReceivedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> notification) { string mycustomparameter; var protectedState = notification.ProtocolMessage.State.Split('=')[1]; var state = notification.Options.StateDataFormat.Unprotect(protectedState); state.Dictionary.TryGetValue("mycustomparameter",out mycustomparameter); return Task.FromResult(0); }
你显然需要改进/强化这个,但这应该让你去.