2

I have integrated Auth0 as an Owin identity provider so that in the future I can manage website users via the Auth0 platform. After registration the user should be redirected to a form asking for some additional data (postal address, etc.), then a Sitecore user account should be created.

For the implementation I followed this project: Auth0 in Sitecore. I use the same processor class (Auth0IdentityProviderProcessor.cs), the same provider configuration (Auth0InSitecore.config) and also enabled federated authentication.

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore role:require="Standalone or ContentDelivery or ContentManagement">
    <settings>
      <setting name="Owin.Authentication.Enabled" value="true" />
      <setting name="FederatedAuthentication.Enabled" value="true" />
    </settings>
    <services>
      <register serviceType="Sitecore.Abstractions.BaseAuthenticationManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Security.AuthenticationManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
      <register serviceType="Sitecore.Abstractions.BaseTicketManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Security.TicketManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
      <register serviceType="Sitecore.Abstractions.BasePreviewManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Publishing.PreviewManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
    </services>
    <sites>
      <site name="shell" set:loginPage="/sitecore/login" role:require="Standalone or ContentManagement" />
      <site name="admin" set:loginPage="/sitecore/admin/login.aspx" />
    </sites>
  </sitecore>
</configuration>

Of course I added the Auth0 credentials (client ID, redirect URI, etc.) and set the URLs (callback URL, logout URL) in my Auth0 development account. The callback URL would be https://mypage.de/Web/Account/LoginWithRole (I test on my local computer with an IIS site).

My account controller looks like this:

using System.Security.Claims;
using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Sitecore;
using Sitecore.Links;
using Sitecore.Security.Authentication;

namespace Controllers
{
    public class AccountController : AreaController
    {
        public ActionResult Login()
        {
            HttpContext
                .GetOwinContext()
                .Authentication
                .Challenge(new AuthenticationProperties
                {
                   RedirectUri = Url.Action("LoginWithRole", "Account", new { area = "" })
                },
                "Auth0"
            );
            return new HttpUnauthorizedResult();
        }

        public ActionResult LoginWithRole()
        {
            var claimsIdentity = User.Identity as ClaimsIdentity;
            var eMail = claimsIdentity?.FindFirst(c => c.Type == ClaimTypes.Email)?.Value;
        
            return Content(""); // only for testing
        }
    }
}

So, the login action method works as expected. Auth0 opens and I can register a new user via login form. When I go into SecurityTokenReceived handler (Auth0 processor) with debugger I can also see my data (name, access token, etc.). But the data is not accessible in LoginWithRole action method. I would like to get the Auth0 claims from User.Identity.

In the network panel of the browser developer console, I could see that Auth0 makes a POST request to https://mypage.de/Web/Account/LoginWithRole, but the program flow does not go into the method (I checked this while debugging). Instead, another redirect is made to the same URL using the GET method. Then the program flow goes into the method body, but the User.Identity property points to a Sitecore user object.

When I add attributes like Authorize or HttpPost to my action method, I get into a redirect loop (Login > LoginWithRole as POST > Login > etc.). I do not know why.

Maybe someone has had the same (or similar) problem before and knows how to solve it? Any suggestion would be really helpful.

Thanks in advance.

2 Answers 2

1

Sitecore user (virtual or persistent) is created automatically when Federated Authentication processes the POST request from Auth0 back to Sitecore. If you want to ask users for additional information after the first login, I would recommend to store a custom flag in the Auth0 user profile that will help you identify whether current user completed the second step of registration or not. For example, you can store a boolean value in a field called "Registration Complete" and check its value to redirect the user appropriately.

Here is some additional information to answer your questions:

How to access Auth0 user profile fields in Sitecore?

The best way to do this is by mapping Auth0 claims to Sitecore user profile fields during login. Federated Authentication provides a standard way to do this with <propertyInitializer> config section. For example, this is how you can map the Email address claim in Sitecore config file:

<sitecore>
  <federatedAuthentication>
    <propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication">
      <maps hint="list">
        <map name="Email claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
          <data hint="raw:AddData">
            <source name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" />
            <target name="Email" />
          </data>
        </map>
      </maps>
    </propertyInitializer>
  </federatedAuthentication>
</sitecore>

Then you will be able to access email of the logged-in user in your custom code using standard Sitecore API:

Sitecore.Context.User.Profile.Email

Why is the POST request from Auth0 followed by GET request?

This is expected behaviour. When Sitecore receives a POST request and sees OAuth 2.0 parameters in the request body, it tries to find an Identity Provider Processor for the current website and call notification handlers from the found processor. After this, Sitecore will authenticate the user and redirect him via GET request to the redirectUrl that was sent in the original https://YOUR_DOMAIN.auth0.com/authorize request. So the user is not authenticated until Sitecore processes the first POST request, but he will be in the next GET request. This is why you get a redirect loop after adding [Authorize] attribute to the method LoginWithRole - it prevents Sitecore from running authentication process and instead redirects to the URL configured as loginPage in the site config.

Therefore, you should perform the custom logic that will check user profile fields and display the second step of registration only after Sitecore authentication is complete. Please note that you will need to handle scenarios when users successfully logged in but did not complete the second step and went to another page instead. Depending the desired user experience, you may want to use a custom processor in <httpRequestBegin> pipeline to redirect users or choose to have a component that will prompt users to complete registration.

4
  • Thank you for your response. Do I have to notice something more to map the data (Email) into Context.User.Profile object? I use the same propertyInitializer configuration and checked the status of Context.User.Profile in LoginWithRole during debug mode. But the User property refers only to a extranet\Anonymous user with empty mail address.
    – salted
    Nov 9, 2022 at 10:19
  • 1
    @salted if your user is still showing as extranet\Anonymous after the redirect back to Sitecore, please check the following things. 1) Make sure that your identity provider is mapped to the correct site name in <identityProvidersPerSites> configuration section, otherwise Sitecore will not be able to find an identity provider for the context website.
    – Anna Gevel
    Nov 9, 2022 at 16:20
  • 1
    2) You should use the pipeline GetSignInUrlInfoPipeline to generate the login link, the generated link will look like /identity/externallogin?authenticationType=.... It is required because Sitecore will include additional authentication properties that are necessary for federated authentication to work. You can find an example here github.com/kate-orlova/auth0-in-sitecore/blob/main/src/Sitecore/…
    – Anna Gevel
    Nov 9, 2022 at 16:21
  • 1
    3) Use POST request to initialize login process using the URL generated by the pipeline GetSignInUrlInfoPipeline, there is an example of login button here github.com/kate-orlova/auth0-in-sitecore/blob/main/src/Sitecore/…
    – Anna Gevel
    Nov 9, 2022 at 16:22
1

In the propertyInitializer you can map claims, just like below code:

    <propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication">
                <maps hint="list">
                    <map name="set SSO FullName" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true" patch:source="Project.NAC.AzureAD.config">
                        <data hint="raw:AddData">
                            <source name="full_name" />
                            <target name="FullName" />
                        </data>
                    </map>
                    <map name="Given Name" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
                        <data hint="raw:AddData">
                            <source name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" />
                            <target name="Name" />
                        </data>
                    </map>
                </maps>
            </propertyInitializer>

As I map FullName, I am getting value as Sitecore.Context.User.Profile.FullName.

More detail you can check here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.