I might be a little late to the party here, but I've come across the same issue and found that the AzureAD authentication middleware is very sparsely documented. Adding the solution here for others struggling with the same question.
As you can see at the bottom of the code snippet in the question, the AzureAD provider actually relies on OpenIdConnect
and Cookie
auth providers under the hoods, and does not implement any authentication logic itself.
To accomplish this, two additional authentication schemes are added, using the names defined as AzureADDefaults.OpenIdScheme
and AzureADDefaults.CookieScheme
, respectively.
(Although the names can also be customized when using the AddAzureAD(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, string scheme, string openIdConnectScheme, string cookieScheme, string displayName, Action<Microsoft.AspNetCore.Authentication.AzureAD.UI.AzureADOptions> configureOptions)
overload).
That, in turn, allows to configure the effective OpenIdConnectOptions
and CookieAuthenticationOptions
by using the scheme names from above, including access to OpenIdConnectEvents
.
See this complete example:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async ctxt =>
{
// Invoked before redirecting to the identity provider to authenticate. This can be used to set ProtocolMessage.State
// that will be persisted through the authentication process. The ProtocolMessage can also be used to add or customize
// parameters sent to the identity provider.
await Task.Yield();
},
OnMessageReceived = async ctxt =>
{
// Invoked when a protocol message is first received.
await Task.Yield();
},
OnTicketReceived = async ctxt =>
{
// Invoked after the remote ticket has been received.
// Can be used to modify the Principal before it is passed to the Cookie scheme for sign-in.
// This example removes all 'groups' claims from the Principal (assuming the AAD app has been configured
// with "groupMembershipClaims": "SecurityGroup"). Group memberships can be checked here and turned into
// roles, to be persisted in the cookie.
if (ctxt.Principal.Identity is ClaimsIdentity identity)
{
ctxt.Principal.FindAll(x => x.Type == "groups")
.ToList()
.ForEach(identity.RemoveClaim);
}
await Task.Yield();
},
};
});
services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, options =>
{
options.Events = new CookieAuthenticationEvents
{
// ...
};
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…