I have setup an working Enterprise connection to our companys Azure AD, when I try the connection from the Auth0 portal it works great, and when I check the login in the dashboard, I can see all Identity Provider Attributes, including the groups from Azure AD. But the issue is that I dont get the extended attributes (groups etc) when I try to authenticate to that connection from our application.
It is a .NET application, using OIDC. Here is the code from the startup.cs file:
private void UseAzureAd(IAppBuilder app)
{
// Enable Kentor Cookie Saver middleware
app.UseKentorOwinCookieSaver();
// Set Cookies as default authentication type
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
//Enable cookie authentication, used to store the claims between requests
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "Auth0",
Authority = ConfigurationManager.AppSettings["OpenIdAuthority"],
ClientId = ConfigurationManager.AppSettings["OpenIdClientIdInternal"],
ClientSecret = AppSettings.GetSetting<string>("ClientSecretInternal"),
ResponseType = OpenIdConnectResponseType.IdToken,
RedirectUri = ConfigurationManager.AppSettings["OpenIdDomainUrlInternal"],
PostLogoutRedirectUri = LogOutOpenIdUrl,
Scope = OpenIdConnectScope.OpenIdProfile,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
_logger.Info("*** AuthenticationFailed with following exception: " + context.Exception.Message + "redirecting to startpage, user will not be authenticated");
context.Response.Redirect("/");
context.HandleResponse();
return Task.FromResult(0);
},
RedirectToIdentityProvider = (ctx) =>
{
//To avoid a redirect loop to the federation server send 403 when user is authenticated but does not have access
if (ctx.OwinContext.Response.StatusCode == 401 && ctx.OwinContext.Authentication.User.Identity.IsAuthenticated)
{
ctx.OwinContext.Response.StatusCode = 403;
//ctx.Response.Redirect(LogoutUrl.Value);
ctx.HandleResponse();
}
return Task.FromResult(0);
},
SecurityTokenValidated = async (ctx) =>
{
//Ignore scheme/host name in redirect Uri to make sure a redirect to HTTPS does not redirect back to HTTP
var redirectUri = new Uri(ctx.AuthenticationTicket.Properties.RedirectUri, UriKind.RelativeOrAbsolute);
if (redirectUri.IsAbsoluteUri)
{
ctx.AuthenticationTicket.Properties.RedirectUri = redirectUri.PathAndQuery;
}
// Make sure the GroupMembershipClaims is set in the manifest in Azure AD for the application.
var adGroupClaims = ctx.AuthenticationTicket?.Identity?.Claims?.Where(c => c.Type == "groups");
if (adGroupClaims != null)
{
foreach (Claim claim in adGroupClaims)
{
// use the OID and get a friendly name to use as the role (if it exists)
var groupStringValue = ConfigurationManager.AppSettings[claim.Value];
if (groupStringValue != null)
{
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, groupStringValue));
if (groupStringValue.Equals(Constants.AdGroups.WebSupport) || groupStringValue.Equals(Constants.AdGroups.WebIntraTest))
{
// Access to EPiServer
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, "Administrators"));
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, "CmsEditors"));
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, "CmsAdmins"));
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, "WebEditors"));
ctx.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, "WebAdmins"));
}
}
}
}
await ServiceLocator.Current.GetInstance<ISynchronizingUserService>().SynchronizeAsync(ctx.AuthenticationTicket.Identity);
return;
},
AuthorizationCodeReceived = ctx =>
{
ctx.AuthenticationTicket.Properties.IsPersistent = true;
ctx.AuthenticationTicket.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60);
return Task.FromResult(0);
}
}
});
//Add stage marker to make sure WsFederation runs on Authenticate (before URL Authorization and virtual roles)
app.UseStageMarker(PipelineStage.Authenticate);
//Remap logout to a federated logout
app.Map(LogoutUrl, map =>
{
map.Run(ctx =>
{
Logout(ctx);
return Task.FromResult(0);
});
});
//Tell antiforgery to use the name claim
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;
}
The right configurations are made in the manifest in Azure AD, and as mentioned it works from the Auth0 portal, so I suspect there is something I’m missing in my setup above? I’m using an company associated email to login with as well, so there should be no problem there.
All feedback/suggestions is much appreciated.
Kind regards //Johannes