# Backoffice Authentication

By default, Ucommerce automatically authenticates as a test administrator account.\
This is very useful when developing locally, so you do not have to set up authentication from the get-go. When going to production this should be changed, however, so the back office is protected from unverified use, and handle individual user permissions. \
Ucommerce leverages the [built-in ASP.NET Core authorization](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/introduction?view=aspnetcore-7.0) to restrict access to the back office API. This means that you will have to implement an ASP.NET authorization system yourself.

It is recommended that you integrate a well-known identity provider. We have examples of how it can be done using [Microsoft Entra ID](/readme/backoffice-authentication/microsoft-entra-id-example.md) and [Auth0](/readme/backoffice-authentication/auth0-authentication-example.md).

{% hint style="info" %}
We suggest that you implement an authorization system using [OpenID Connect](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/secure-net-microservices-web-applications/#authenticate-with-an-openid-connect-or-oauth-20-identity-provider) since this will enable you to use single sign-on (SSO), allowing you to share logins between Ucommerce and other OAuth-enabled applications like a CMS.
{% endhint %}

## Add an external identity provider

Ucommerce takes care of the local login session, so you need to set up a scheme that will take care of logging in the user. Additionally, Ucommerce needs an implementation of the [`IExternalClaimsMapper`](#external-claims-mapper)  interface.

Use the options hook when calling `AddBackOffice()` in `program.cs`, to configure your scheme:

```csharp
var ucommerceBuilder = builder.Services.AddUcommerce(builder.Configuration)
    .AddBackOffice(securitySettings =>
        {
            // This method can be called multiple times
            securitySettings.AddExternalIdentityProvider<MyExternalClaimsMapper>(
                "MyExternalScheme",
                authenticationBuilder =>
                {
                ... // Use the AuthenticationBuilder to add your scheme
                });
            // Configure Ucommerce to use your scheme from code
            securitySettings.UseExternalIdentityProvider("MyExternalScheme");
        }
    )
    ...
```

{% hint style="warning" %}
Since Ucommerce takes care of the session cookie, you should not set cookies in your external authentication scheme.
{% endhint %}

{% hint style="info" %}
You can use the [ASP.NET configuration](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0) to override the external identity provider that Ucommerce will forward to. You can define the scheme by setting the value for `Ucommerce:BackOffice:ExternalIdentityProviderScheme` to the name of one of the registered schemes. This allows you to change the provider depending on the environment. To use the built-in scheme set the value to `ucommerce-test-user`.
{% endhint %}

## External Claims Mapper

Ucommerce automatically creates and updates a local user when a user logs in via an external identity provider, so it needs a mapping of the external claims, to the local user in Ucommerce.\
To create a mapping you implement the `IExternalClaimsMapper` interface.

The interface consists of a single method `MapClaims` that must take care of the mapping from the incoming claim to an `AuthUser` object.

```csharp
using Ucommerce.Web.BackOffice.Authentication;
...

public class MyExternalClaimsMapper : IExternalClaimsMapper
{
    public Task<AuthUser> MapClaims(ClaimsPrincipal principal)
    {
        var externalId = // A claim value with a unique identifier for the user
        //e.g.
        //var externalId = principal.FindFirstValue(ClaimTypes.NameIdentifier)!;
        var name = // A claim value containing the name of the user
        var isAdmin = // A claim value indicating if the user is to be an admin
        var user = new AuthUser(externalId, name)
        {
            IsAdmin = isAdmin
        };
        return Task.FromResult(user);
    }
}
```

### AuthUser Properties

| Property   | Description                                                                      |
| ---------- | -------------------------------------------------------------------------------- |
| ExternalId | The identifier from the external provider used to identify the user in Ucommerce |
| Name       | The name of the user                                                             |
| IsAdmin    | Indicate if the user should have administrator rights                            |

## The default `ExternalClaimsMapper`

Ucommerce comes with a default claims mapper (`Ucommerce.Web.BackOffice.Authentication.ExternalClaimsMapper`) that maps claims in the following way. The keys are also defined in the `UcommerceClaimTypes` constants class.

| Property   | UcommerceClaimTypes Key | Value                                                                                                                                   |
| ---------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| ExternalId | EXTERNAL\_IDENTIFIER    | [ClaimTypes.NameIdentifier](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes.nameidentifier?view=net-8.0) |
| Name       | NAME                    | [ClaimTypes.Name](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes.name?view=net-8.0)                     |
| IsAdmin    | IS\_ADMIN               | "IsAdmin"                                                                                                                               |

## Related Articles

{% embed url="<https://learn.microsoft.com/en-us/aspnet/core/security/authorization/introduction?view=aspnetcore-7.0>" %}

{% embed url="<https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc>" %}

{% embed url="<https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-7.0>" %}

{% content-ref url="/pages/afGlzr37PZ2anwL1slrF" %}
[Microsoft Entra ID Example](/readme/backoffice-authentication/microsoft-entra-id-example.md)
{% endcontent-ref %}

{% content-ref url="/pages/jSskUNtNxL6cZJ7QXy5j" %}
[Auth0 Authentication Example](/readme/backoffice-authentication/auth0-authentication-example.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ucommerce.net/readme/backoffice-authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
