Help shape the future of CMS PaaS release notes! Take this quick survey and share your feedback.
Help shape the future of CMS PaaS release notes! Take this quick survey and share your feedback.
If using Azure AD or B2C your roles should be managed in that platform and then synched to CMS, (You can still set Access Rights on these Synched Roles).
/// <summary>
/// Azure ad extension
/// </summary>
public static class AzureAdExtensions
{
/// <summary>
/// Azure Ad authentication
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="forceHttpsRedirect"></param>
public static void ConfigureAzureAd(this IServiceCollection services, IConfiguration configuration, bool forceHttpsRedirect)
{
services
.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(
identityOptions =>
{
configuration.Bind("AzureAd", identityOptions);
identityOptions.Scope.Add("email");
identityOptions.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = ClaimTypes.Role,
NameClaimType = ClaimTypes.Email
};
identityOptions.Events ??= new OpenIdConnectEvents();
identityOptions.Events.OnTokenValidated = async (context) =>
{
if (context?.Principal == null)
{
await Task.FromResult(0);
return;
}
if (!string.IsNullOrEmpty(context.Properties.RedirectUri))
{
var redirectUri = new Uri(context.Properties.RedirectUri, UriKind.RelativeOrAbsolute);
if (redirectUri.IsAbsoluteUri)
{
context.Properties.RedirectUri = redirectUri.PathAndQuery;
}
}
await ServiceLocator.Current.GetInstance<ISynchronizingUserService>().SynchronizeAsync(context.Principal?.Identity as ClaimsIdentity);
};
identityOptions.Events.OnRedirectToIdentityProvider = async (context) =>
{
if (forceHttpsRedirect)
{
context.ProtocolMessage.RedirectUri =
context.ProtocolMessage.RedirectUri.Replace("http:", "https:");
}
await Task.FromResult(0);
};
},
null,
OpenIdConnectDefaults.AuthenticationScheme,
CookieAuthenticationDefaults.AuthenticationScheme,
true);
}
/// <summary>
/// Configure cookie policy
/// </summary>
/// <param name="services"></param>
/// <param name="setCookieDomain"></param>
public static void ConfigureCookiePolicy(this IServiceCollection services, bool setCookieDomain)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
{
if (cookieContext.CookieOptions.SameSite == SameSiteMode.None)
{
cookieContext.CookieOptions.SameSite = SameSiteMode.Unspecified;
}
// this should be environment specific
if (setCookieDomain)
{
cookieContext.CookieOptions.Domain = ".localhost";
}
};
options.OnDeleteCookie = cookieContext =>
{
if (cookieContext.CookieOptions.SameSite == SameSiteMode.None)
{
cookieContext.CookieOptions.SameSite = SameSiteMode.Unspecified;
}
};
});
}
}
UI Role Provider
public class UIRoleProviderAad : UIRoleProvider
{
private EPiServer.ServiceLocation.Injected<SecurityEntityProvider> _uiRoleProvider;
public override bool Enabled { get; set; } = true;
public override string Name => "UIRoleProviderAAD";
public override async IAsyncEnumerable<IUIRole> GetAllRolesAsync()
{
var uiRoles = await _uiRoleProvider.Service.SearchAsync(null, ClaimTypes.Role);
foreach (var item in uiRoles.Select(r => new UIRoleImpl(r.Name, "DefaultProvider")))
{
yield return item;
}
}
}
Role Model
public class UIRoleImpl : IUIRole
{
public UIRoleImpl()
{
}
public UIRoleImpl(string name, string provider)
{
Name = name;
ProviderName = provider;
}
public string Name { get; set; }
public string ProviderName { get; set; }
}
Startup.cs
services.ConfigureAzureAd(Configuration, !_environment.IsDevelopment());
services.ConfigureCookiePolicy(!_environment.IsDevelopment());
services.AddTransient<UIRoleProvider, UIRoleProviderAad>();
You can also then Map your roles to virtual roles in appsettings e.g.
"EPiServer": {
"Cms": {
"MappedRoles": {
"Items": {
"CmsEditors": {
"MappedRoles": [ "WebEditors", "WebAdmins" ]
},
"CmsAdmins": {
"MappedRoles": [ "WebAdmins" ]
}
}
}
}
Hi Minesh,
thanks a lot for your reply. I tested the solution and it already works on my side.
But I think that the solution fails if you have two ISP-providers (e.g. Azure for inhouse colleques + Google for external employees), what is the future's plan.
Example:
Let's say we have to users:
- user1 -> inhouse user authentificated in azure to the role ContentEditorGroup1 in azure
- user2 -> external user authentificated in google to the role ContentEditorGroup1 in google
Is it not the case that role mapping will fail in that case?
Have a look at Mixed Mode Authentication I believe if the roles have the same name it should work, although suggestion would be to use unique roles and than map to a virtual role
Hello,
We are using the EPi_AspNetIdentityUserProvider in order to set the policies to the pages, blocks etc.
But we want to use Azure as the ISP-Provider for Authentfication.
Later on maybe also some more other ISP-Provider
So I in the startup
I'm calling ...
and later on i I setup the Azure - Authentification.
The problem came when the user has been "azure - authentificated".
This is the code - snippet where the user get's "azure - authentificated" within the OnTokenValidated-Event:
I see two strategies:
-----------------------------
Strategy 1):
With the "azure - authentificated user" I read the user's roles/claims from the EpiServerDb and add the EpiServer-roles/claims to the "azure - authentificated user" - claims
I tried this in the code snippet above without success.
Strategy 2):
With the "azure - authentificated user" I can archieve a impersonation to a "EPi_AspNetIdentityUserProvider - user"
Do you see any solution how to solve this issue ?