Entra ID Configuration

1. Overview

This guide explains how to configure the Registration Portal to authenticate against Microsoft Entra ID (formerly Azure AD / Azure AD B2C).

2. Prerequisites

  • Access to the Azure portal

  • An Entra ID B2C tenant (create one if not yet available)

  • User Flows configured under Policies in the B2C tenant

3. App Registration

Navigate to App Registrations in your Entra ID B2C tenant and select + New registration.

3.1. Initial Registration

Complete the registration form with the following settings:

Field Value

Name

A name to identify the application (e.g., "Registration Portal")

Supported account types

"Accounts in any identity provider or organizational directory"

Redirect URI - Type

Web

Redirect URI - URL

<BaseURL>/login/oauth2/code/oidc

Permissions

Select "Grant admin consent to openid and offline_access permissions"

The application is configured as a web application (not a public SPA) because authentication is performed by the Java backend layer, not purely in the browser. This out-of-band, backend authentication means PKCE is not strictly required.

Example Redirect URI:

http://localhost:12505/login/oauth2/code/oidc

3.2. Required Information

After registration, note the following values from the Overview page:

  • Application (client) ID - Used as client-id in configuration

  • Directory (tenant) ID - Used to construct the issuer URL

3.3. Issuer URL Configuration

  1. Click the Endpoints button at the top of the Overview page

  2. Locate the "Azure AD B2C OpenID Connect metadata document" URL

  3. Modify the URL as follows:

    • Remove the trailing part after …​/v2.0/

    • Insert /tfp after the hostname and before the Tenant ID

Issuer URL Format:

https://<Tenant Hostname>/tfp/<Tenant ID>/<Policy Name>/v2.0/

This format ensures:

  • The discovery endpoint functions correctly

  • The issuer claim in tokens matches the OAuth2 client configuration

3.4. Client Secret

  1. Navigate to Certificates & Secrets

  2. Create a new Client Secret

  3. Copy and securely store the Value field as the client-secret

The client secret value is only displayed once at creation. Store it securely immediately.

4. Application Configuration

4.1. Dynamic Per-Tenant Configuration (Current)

IdP configuration is now stored per-tenant in the Gateway database as TenantIdentityProvider entities. The Registration Portal dynamically loads OAuth2 client registrations based on the resolved tenant.

Create a TenantIdentityProvider record with the following values:

Field Value

provider_type

ENTRA_ID

display_name

"Sign in with Microsoft" (or organisation-specific label)

client_id

Application (client) ID from the App Registration

client_secret

Client Secret Value (encrypted at rest)

issuer_uri

https://<Tenant>.b2clogin.com/tfp/<Tenant ID>/<Policy Name>/v2.0/

scopes

openid,profile,email

user_name_attribute

sub

subject_claim_name

oid — Microsoft recommends using oid (the user’s Object ID) as the stable identifier. Unlike sub, which is pairwise (unique per application registration), oid is unique across all application registrations within the Entra ID tenant.

enabled

true

The Gateway’s TenantClientRegistrationRepository constructs a Spring Security ClientRegistration from these values at runtime.

4.2. Redirect URI

The redirect URI to register in the Entra ID App Registration is:

https://<tenant-domain>/login/oauth2/code/entra_id

Each tenant domain requires its own redirect URI entry.

4.3. Static Configuration (Legacy)

The previous approach configured a single static provider in application.yml. This is deprecated in favour of per-tenant database configuration. Existing static configuration should be migrated to TenantIdentityProvider records.

spring:
  security:
    oauth2:
      client:
        registration:
          oidc:
            client-id: <Application (client) ID>
            client-secret: <Client Secret Value>
            scope: openid,profile,email
        provider:
          oidc:
            issuer-uri: https://<Tenant>.b2clogin.com/tfp/<Tenant ID>/<Policy Name>/v2.0/