Authentication by Azure AD B2C

KK
KK
Vote:
 

Hi experts,

I am trying to setup Azure AD B2C to authenticate my localhost cms.

I am following links as below and some microsoft examples:

https://docs.developers.optimizely.com/content-cloud/v12.0.0-content-cloud/docs/integrate-azure-ad-using-openid-connect

https://www.blendinteractive.com/thoughts/integrating-azure-ad-with-optimizely-cms-12/

Now the problem was after accessing "https://localhost:5000/episerver/cms" and logged in, it finally returns to 

This localhost page can’t be found

No web page was found for the web address: https://localhost:5000/Account/AccessDenied?ReturnUrl=%2Fepiserver%2Fcms

HTTP ERROR 404
 
But if visited the page https://localhost:5000, the website was in correct status(logged in). 

My code piece:

services
        .AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = "azure-cookie";
            options.DefaultChallengeScheme = "azure";
        })
        .AddCookie("azure-cookie", options =>
        {
            options.Events.OnSignedIn = async ctx =>
            {
                if (ctx.Principal?.Identity is ClaimsIdentity claimsIdentity)
                {
                    // Syncs user and roles so they are available to the CMS
                    var synchronizingUserService = ctx
                        .HttpContext
                        .RequestServices
                        .GetRequiredService<ISynchronizingUserService>();

                    await synchronizingUserService.SynchronizeAsync(claimsIdentity);
                }
            };
        })
        .AddOpenIdConnect("azure", options =>
        {
            options.SignInScheme = "azure-cookie";
            options.SignOutScheme = "azure-cookie";
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.CallbackPath = "/signin-oidc";
            
            options.ClientSecret = "my client secret";
            options.UsePkce = true;

            options.Authority = "https://login.microsoftonline.com/common/v2.0/";
            options.ClientId = "my client id";

            options.Scope.Clear();
            options.Scope.Add(OpenIdConnectScope.OpenId);
            options.Scope.Add(OpenIdConnectScope.OfflineAccess);
            options.Scope.Add(OpenIdConnectScope.Email);
            options.MapInboundClaims = false;

            options.TokenValidationParameters = new TokenValidationParameters
            {
                RoleClaimType = ClaimTypes.Role,
                NameClaimType = "preferred_username",
                //NameClaimType = ClaimTypes.Email,
                //NameClaimType = "userName",
                ValidateIssuer = false,
                SaveSigninToken = true
            };

            options.Events.OnRedirectToIdentityProvider = ctx =>
            {
                // Prevent redirect loop
                if (ctx.Response.StatusCode == 401)
                {
                    ctx.HandleResponse();
                }

                return Task.CompletedTask;
            };

            options.Events.OnAuthenticationFailed = context =>
            {
                context.HandleResponse();
                context.Response.BodyWriter.WriteAsync(Encoding.ASCII.GetBytes(context.Exception.Message));
                return Task.CompletedTask;
            };
        });

        services.AddHttpClient<IExternalOutputService, ExternalOutputService>();
        services.AddCmsHost().AddCmsHtmlHelpers().AddCmsUI().AddAdmin().AddVisitorGroupsUI().AddTinyMce()
            .AddEmbeddedLocalization<Startup>();

Thanks in advance

#284572
Jul 28, 2022 15:46
Vote:
 

When the user does not have the correct permissions (or roles) then you will be redirected to the AccessDenied page. Please make sure you have added and assigned the application roles described in this section of the documentation:
https://docs.developers.optimizely.com/content-cloud/v12.0.0-content-cloud/docs/integrate-azure-ad-using-openid-connect#adding-application-roles-in-azure-active-directory

If that does not work, then you can try adding the following roles to the user:

  • CmsEditors
  • CmsAdmins
  • SearchAdmins
  • FindAdmins

SearchAdmins and FindAdmins are important if you have Optimizely Search & Navigation installed!

If you are using custom role names and you cannot change them, then the roles can be mapped in the appsettings.json like so:

"EPiServer": {
  "Cms": {
    "MappedRoles": {
      "Items": {
        "CmsEditors": {
          "MappedRoles": [ "X" ]
        },
        "CmsAdmins": {
          "MappedRoles": [ "X" ]
        },
        "SearchAdmins": {
          "MappedRoles": [ "X" ],
          "ShouldMatchAll": "false"
        },
        "FindAdmins": {
          "MappedRoles": [ "X" ],
          "ShouldMatchAll": "false"
        }
      }
    }
  }
}

You can also confirm if the roles have been synchronized correctly by inspecting the following database tables:

  • tblSynchedUser
  • tblSynchedUserRelations
  • tblSynchedUserRole
#284613
Edited, Jul 29, 2022 1:24
KK
Vote:
 

Thanks so much, @Ynze. 

Tried to add app roles in Azure B2C. But looks like Azure AD B2C does not support roles creation in app registration. 

Under Azure AD B2C | App registrations --> no app roles blade. Searched and tried some tricks, none of them worked.

And besides that, more specifically I can see the token returned has no Role claim at all.  But if I check my azure AD B2C tenant --> Users --> click a specific AD User --> it has several built-in roles.

Does anyone know how to make the token returned with the Roles claims? 

So as the last resort, I did a hack by manually adding a line in options.Events.OnTokenValidated. 

claimsIdentity?.AddClaim(new Claim(ClaimTypes.Role, "CmsAdmins"));

And  if I would like the external users directly login to the website home page, any suggestions about how to  create a custom login page as start page? 

Thanks in advance. 

#284619
Edited, Jul 29, 2022 15:58
Vote:
 

KK

Referring back to your attempt to access episerver/cms/ and being redirected to accessdenied url (even though your actually getting a 404).

I believe your cms admin mode is still using the default scheme. You've changed the challenge scheme to use "azure" so cms admin will not use that..unless you tell it too.

Look at this documentation and implement the .AddPolicyScheme: https://docs.developers.optimizely.com/content-cloud/v12.0.0-content-cloud/docs/mixed-mode-authentication

#284692
Jul 30, 2022 23:20
Vote:
 

It looks like the default roles cannot be retrieved via the claims, but instead you have to call to the Graph SDK. See this stackoverflow post for more details.

Then for custom roles you can apparently use custom policies as described in this stackoverflow post. You'll also need to do a Graph request to retrieve those.

Then lastly, if I understand you correctly, then you can simply configure the access rights in the admin section of the CMS to require users to login when accessing the homepage. Usually the 'Everyone' role is set to 'read', you can remove that and set the 'Authenticated' role to 'read' instead. Then if a user navigates to the page it will trigger the authentication and redirect to the login page. 

Good luck 😄

#284810
Edited, Aug 02, 2022 7:40
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.