AspNetCore 使用 OpenIdConnect 身份验证
AspNetCore UseOpenIdConnectAuthentication
我正在使用 Azure AD B2C 在 AspNetCore RC2 MVC 应用程序中进行身份验证,这在一定程度上起作用,因为当我导航到需要身份验证的操作时,我会相应地重定向到 B2C 登录页面。当我成功登录时,我被正确地重定向到我的应用程序页面(我可以看到查询参数中适当提供的 id_token 字段)。不幸的是,管道身份验证中间件似乎没有正确处理重定向查询参数,因为它立即将我重定向到登录页面。有人可以建议吗?
我使用的代码如下:
public static void UseOAuth(this IApplicationBuilder app)
{
// By default, all middleware are passive/not automatic. Making cookie middleware automatic so that it acts on all the messages.
app.UseCookieAuthentication( new CookieAuthenticationOptions{ AutomaticAuthenticate = true, CookieSecure = CookieSecureOption.Never });
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
ClientId = B2CAuthentication.ClientId,
ResponseType = OpenIdConnectResponseTypes.IdToken,
Authority = string.Format(CultureInfo.InvariantCulture, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, string.Empty, string.Empty),
AuthenticationScheme = "Cookies",
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
OnTokenResponseReceived = OnTokenResponseReceived,
OnTokenValidated = OnTokenValidated,
OnTicketReceived = OnTicketReceived,
OnMessageReceived = OnMessageReceived,
OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut,
OnRemoteFailure = OnRemoteFailure,
OnUserInformationReceived = OnUserInformationReceived
},
// 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, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, "/v2.0", "/" + OpenIdProviderMetadataNames.Discovery),
new string[] { B2CAuthentication.ResetPolicy, B2CAuthentication.CommonPolicy, B2CAuthentication.SignInPolicy })
});
}
private static Task OnUserInformationReceived(UserInformationReceivedContext arg)
{
...Never called...
}
private static Task OnRemoteFailure(FailureContext arg)
{
...Never called...
}
private static Task OnRedirectToIdentityProviderForSignOut(RedirectContext arg)
{
...Never called...
}
private static Task OnMessageReceived(MessageReceivedContext arg)
{
...Never called...
}
private static Task OnTicketReceived(TicketReceivedContext arg)
{
...Never called...
}
private static Task OnTokenValidated(TokenValidatedContext arg)
{
...Never called...
}
private static Task OnTokenResponseReceived(TokenResponseReceivedContext arg)
{
...Never called...
}
private static Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext arg)
{
...Never called...
}
private static async Task OnRedirectToIdentityProvider(RedirectContext context)
{
PolicyConfigurationManager mgr = (PolicyConfigurationManager)context.Options.ConfigurationManager;
if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
OpenIdConnectConfiguration config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, B2CAuthentication.CommonPolicy);
context.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint;
}
else
{
OpenIdConnectConfiguration config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, B2CAuthentication.CommonPolicy);
context.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint;
context.ProtocolMessage.RedirectUri = "http://localhost:8080/Portal/";
context.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
context.ProtocolMessage.ResponseMode = OpenIdConnectResponseModes.Query;
}
}
private static Task OnAuthenticationFailed(AuthenticationFailedContext context)
{
context.HandleResponse();
context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
我已通过执行以下操作成功实现了此功能:
从根本上说,我认为 CallbackPath 的使用、对 AuthenticationScheme 的更改以及将 ResponseMode 更改为 FormPost 所有这些都有助于修复。
public static void UseOAuth(this IApplicationBuilder app)
{
// By default, all middleware are passive/not automatic. Making cookie middleware automatic so that it acts on all the messages.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
CookieName = "MyCookieName",
CookieSecure = CookieSecureOption.Never,
AuthenticationScheme = "Cookies"
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
AutomaticAuthenticate = true,
Authority = string.Format(CultureInfo.InvariantCulture, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, string.Empty, string.Empty),
ClientId = B2CAuthentication.ClientId,
ResponseType = OpenIdConnectResponseTypes.IdToken,
AuthenticationScheme = "oidc",
ResponseMode = OpenIdConnectResponseModes.FormPost,
CallbackPath = "/",
Scope = { "openid" },
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnTokenValidated = OnTokenValidated,
OnRemoteFailure = OnRemoteFailure
},
// 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, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, "/v2.0", "/" + OpenIdProviderMetadataNames.Discovery),
new string[] { B2CAuthentication.ResetPolicy, B2CAuthentication.CommonPolicy, B2CAuthentication.SignInPolicy })
});
}
使用
ResponseType = OpenIdConnectResponseType.Code
里面
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
...
});
似乎使中间件提示 CodeReceived 事件。
同时将 Microsoft.AspNetCore.Mvc.Formatters.Xml
添加到 project.json 以避免 Could not load file or assembly System.Private.DataContractSerialization
错误
我正在使用 Azure AD B2C 在 AspNetCore RC2 MVC 应用程序中进行身份验证,这在一定程度上起作用,因为当我导航到需要身份验证的操作时,我会相应地重定向到 B2C 登录页面。当我成功登录时,我被正确地重定向到我的应用程序页面(我可以看到查询参数中适当提供的 id_token 字段)。不幸的是,管道身份验证中间件似乎没有正确处理重定向查询参数,因为它立即将我重定向到登录页面。有人可以建议吗?
我使用的代码如下:
public static void UseOAuth(this IApplicationBuilder app)
{
// By default, all middleware are passive/not automatic. Making cookie middleware automatic so that it acts on all the messages.
app.UseCookieAuthentication( new CookieAuthenticationOptions{ AutomaticAuthenticate = true, CookieSecure = CookieSecureOption.Never });
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
ClientId = B2CAuthentication.ClientId,
ResponseType = OpenIdConnectResponseTypes.IdToken,
Authority = string.Format(CultureInfo.InvariantCulture, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, string.Empty, string.Empty),
AuthenticationScheme = "Cookies",
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
OnTokenResponseReceived = OnTokenResponseReceived,
OnTokenValidated = OnTokenValidated,
OnTicketReceived = OnTicketReceived,
OnMessageReceived = OnMessageReceived,
OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut,
OnRemoteFailure = OnRemoteFailure,
OnUserInformationReceived = OnUserInformationReceived
},
// 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, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, "/v2.0", "/" + OpenIdProviderMetadataNames.Discovery),
new string[] { B2CAuthentication.ResetPolicy, B2CAuthentication.CommonPolicy, B2CAuthentication.SignInPolicy })
});
}
private static Task OnUserInformationReceived(UserInformationReceivedContext arg)
{
...Never called...
}
private static Task OnRemoteFailure(FailureContext arg)
{
...Never called...
}
private static Task OnRedirectToIdentityProviderForSignOut(RedirectContext arg)
{
...Never called...
}
private static Task OnMessageReceived(MessageReceivedContext arg)
{
...Never called...
}
private static Task OnTicketReceived(TicketReceivedContext arg)
{
...Never called...
}
private static Task OnTokenValidated(TokenValidatedContext arg)
{
...Never called...
}
private static Task OnTokenResponseReceived(TokenResponseReceivedContext arg)
{
...Never called...
}
private static Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext arg)
{
...Never called...
}
private static async Task OnRedirectToIdentityProvider(RedirectContext context)
{
PolicyConfigurationManager mgr = (PolicyConfigurationManager)context.Options.ConfigurationManager;
if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
OpenIdConnectConfiguration config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, B2CAuthentication.CommonPolicy);
context.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint;
}
else
{
OpenIdConnectConfiguration config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, B2CAuthentication.CommonPolicy);
context.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint;
context.ProtocolMessage.RedirectUri = "http://localhost:8080/Portal/";
context.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
context.ProtocolMessage.ResponseMode = OpenIdConnectResponseModes.Query;
}
}
private static Task OnAuthenticationFailed(AuthenticationFailedContext context)
{
context.HandleResponse();
context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
我已通过执行以下操作成功实现了此功能:
从根本上说,我认为 CallbackPath 的使用、对 AuthenticationScheme 的更改以及将 ResponseMode 更改为 FormPost 所有这些都有助于修复。
public static void UseOAuth(this IApplicationBuilder app)
{
// By default, all middleware are passive/not automatic. Making cookie middleware automatic so that it acts on all the messages.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
CookieName = "MyCookieName",
CookieSecure = CookieSecureOption.Never,
AuthenticationScheme = "Cookies"
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
AutomaticAuthenticate = true,
Authority = string.Format(CultureInfo.InvariantCulture, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, string.Empty, string.Empty),
ClientId = B2CAuthentication.ClientId,
ResponseType = OpenIdConnectResponseTypes.IdToken,
AuthenticationScheme = "oidc",
ResponseMode = OpenIdConnectResponseModes.FormPost,
CallbackPath = "/",
Scope = { "openid" },
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnTokenValidated = OnTokenValidated,
OnRemoteFailure = OnRemoteFailure
},
// 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, B2CAuthentication.AadInstance, B2CAuthentication.PortalTenant, "/v2.0", "/" + OpenIdProviderMetadataNames.Discovery),
new string[] { B2CAuthentication.ResetPolicy, B2CAuthentication.CommonPolicy, B2CAuthentication.SignInPolicy })
});
}
使用
ResponseType = OpenIdConnectResponseType.Code
里面
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
...
});
似乎使中间件提示 CodeReceived 事件。
同时将 Microsoft.AspNetCore.Mvc.Formatters.Xml
添加到 project.json 以避免 Could not load file or assembly System.Private.DataContractSerialization
错误