Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Hi Graham
Your code seems fine at first glance.
One thing to call out is that you should use "policy-scheme" for your default schemes as it is this custom policy scheme which then controls which authentication scheme to use
{
options.DefaultScheme = "policy-scheme";
options.DefaultChallengeScheme = "policy-scheme";
})
Hi Ron,
Many thanks for your reply, I have updated the default scheme as shown above but the issue still persists. The functionality to login via the FE via Identity Server works fine until you add the:
services.AddCmsAspNetIdentity<ApplicationUser>();
line and then it stops working, you can login via Identity Server fine but the user session/cookie is not retained. You can however login to the CMS no problem with it's own session/cookie being retained with no problem.
Thanks,
Graham
Did you find a solution?
I'm facing the same problem. Coming to the login page and loging in but then stay on the login page instead of redirecting to the actual page.
hi, I did find a solution in the end, and I wrote a blog post about it which can be viewed here https://world.optimizely.com/blogs/allthingsopti/dates/2023/2/a-day-in-the-life-of-an-optimizely-developer---implementing-identity-server-4-and-asp-net-identity/ hope that helps?
I've read your post, very nice!
Unfortunatly it doesn't work for me although I don't have exactly the same setup.
I need to have azuread and aspnet identity. I followed your guide, my problem is that loging in with azuread into /episerver admin and edit is working well. Then I want some pages to have read access rights for a specific user in the db. So I set the access right in the tree in the admin.
Then when I try to access this page I get redirected to the login so far so good.
I then log in with the user credential, it worked BUT the redirect is not to the page but back to the login page?
The code I have in my startup class as a middleware extension is below:
namespace xxx.Web.Infrastructure.ServiceExtensions; using System.Text; using xxx.Features.Common.Configuration; using EPiServer.Cms.UI.AspNetIdentity; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Protocols.OpenIdConnect; public static class UserAuthenticationServiceExtensions { private const string AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme; private const string ChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; public static IServiceCollection AddUserAuthentication( this IServiceCollection services, IWebHostEnvironment environment, IConfiguration configuration) { services.AddCmsAspNetIdentity<ApplicationUser>(); services.AddIdentityServer(configuration); return services; } /// <summary> /// Sets up authentication based on Identity Server 4 using Open ID Connect /// </summary> /// <param name="services"></param> /// <param name="configuration"></param> /// <returns></returns> public static void AddIdentityServer(this IServiceCollection services, IConfiguration configuration) { var identityServerSettings = configuration.GetSection(nameof(IdentityServerSettings)).Get<IdentityServerSettings>(); var authority = identityServerSettings?.Authority ?? string.Empty; _ = bool.TryParse(identityServerSettings?.RequireHttpsMetadata ?? "true", out bool requireHttpsMetadata); var clientId = identityServerSettings?.ClientId ?? string.Empty; var clientSecret = identityServerSettings?.ClientSecret?? string.Empty; services.AddAuthentication(options => { options.DefaultAuthenticateScheme = AuthenticationScheme; options.DefaultChallengeScheme = "policy-scheme"; }) .AddCookie(AuthenticationScheme, options => { // Defines a path to redirect the user to if they don't have access to a page. // This page should return a 200 response so as to not cause authentication loops. options.AccessDeniedPath = new PathString("/no-access"); }) .AddOpenIdConnect(ChallengeScheme, options => { options.SignInScheme = AuthenticationScheme; options.SignOutScheme = AuthenticationScheme; options.ResponseType = OpenIdConnectResponseType.Code; options.CallbackPath = "/signin-oidc"; options.UsePkce = false; options.Authority = authority; options.RequireHttpsMetadata = requireHttpsMetadata; options.ClientId = clientId; options.ClientSecret = clientSecret; options.Scope.Clear(); options.Scope.Add(OpenIdConnectScope.OpenId); options.Scope.Add("xxx"); options.MapInboundClaims = false; options.Events.OnRedirectToIdentityProvider = context => { // Prevent redirect loop if (context.Response.StatusCode == 401) { context.HandleResponse(); } if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout) { var idTokenHint = context.HttpContext.User.FindFirst("id_token"); if (idTokenHint != null) { context.ProtocolMessage.IdTokenHint = idTokenHint.Value; } } return Task.CompletedTask; }; options.Events.OnAuthenticationFailed = async context => { context.HandleResponse(); await context.Response.BodyWriter.WriteAsync(Encoding.ASCII.GetBytes(context.Exception.Message)); }; }) .AddPolicyScheme("policy-scheme", null, options => { options.ForwardDefaultSelector = ctx => { if (ctx.Request.Path.StartsWithSegments("/episerver", StringComparison.OrdinalIgnoreCase)) { return "Identity.Application"; } return OpenIdConnectDefaults.AuthenticationScheme; }; }); } }
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
Does anyone have any experience of successfully implementing mixed-mode authentication in CMS12, or anyone who can provide any pointers/help.
Thanks in advance.