GALS API

BackOffice Portal Login (Azure B2C + PKCE)

This document describes how the GALS portal authenticates MCA employees via Azure B2C using the PKCE authorization code flow, and how the backend validates access tokens and resolves platform RBAC from the employee database.

MITA provides the Azure B2C tenant details. PTL implements the flow in the portal and configures the API to validate B2C-issued JWT access tokens.

Flow overview

1. Portal generates a code verifier and code challenge (S256). 2. Portal redirects the user to the Azure B2C authorization endpoint with the code challenge. 3. User signs in with their MCA corporate account on the B2C-hosted login page. 4. Azure B2C redirects back to the portal callback URL with an authorization code. 5. Portal exchanges the authorization code and code verifier for tokens at the B2C token endpoint. 6. ID token — used by the portal to display the signed-in user's name in the UI. 7. Access token — sent as a Bearer token on every API request. 8. Backend validates the access token, resolves the employee by email, and enforces screen/action permissions.

Portal configuration (.env.development)

Replace placeholders with values provided by MITA:

<pre><code class="language-env">VITE_APP_API_URL=http://localhost:7137

VITE_B2C_TENANT_NAME=your-tenant-name VITE_B2C_TENANT_DOMAIN=your-tenant-name.onmicrosoft.com VITE_B2C_CLIENT_ID=your-spa-client-id VITE_B2C_SIGNIN_POLICY=B2C_1A_SIGNUP_SIGNIN VITE_B2C_REDIRECT_URI=http://localhost:5173/auth/callback VITE_B2C_API_SCOPE=https://your-tenant-name.onmicrosoft.com/your-api-app-id/gals.access

Portal routes

RoutePurpose
/loginStarts the B2C PKCE redirect
/auth/callbackHandles the authorization code exchange
/access-deniedShown when the user is not provisioned or lacks permissions

Backend configuration (AzureAd in appsettings)

<pre><code class="language-json">&quot;AzureAd&quot;: { &quot;Instance&quot;: &quot;https://your-tenant-name.b2clogin.com/&quot;, &quot;Domain&quot;: &quot;your-tenant-name.onmicrosoft.com&quot;, &quot;ClientId&quot;: &quot;your-api-app-client-id&quot;, &quot;SignUpSignInPolicyId&quot;: &quot;B2C_1A_SIGNUP_SIGNIN&quot;, &quot;Audience&quot;: &quot;your-api-app-client-id&quot; }

ClientId and Audience must match the API app registration that exposes the scope requested by the portal.

Authenticated API calls

The portal stores the access token in sessionStorage and attaches it via an Axios interceptor:

<pre><code class="language-javascript">Authorization: Bearer &lt;access_token&gt;

After sign-in, the portal calls GET /Employee/Me to load role and permissions for navigation and route guards.

Error handling

ScenarioBackend responsePortal behavior
No token401 UnauthorizedRedirect to /login
Valid B2C token but no employee recordAuto-provisions an active employee from the Entra app role (or User) and continuesLoad /Employee/Me and navigate by role permissions
Valid token and employee existsAligns employee role with the Entra app role on each sign-inLoad /Employee/Me with the synced role
Authenticated employee is inactive403 with inactive messageShow inactive account message
Missing screen permission403 ForbiddenShow permission denied state

Azure B2C app registration checklist (MITA)

Local development checklist

1. Obtain B2C tenant, policy, SPA client ID, API client ID, and scope from MITA. 2. Update portal .env.development and backend appsettings.Development.json. 3. Start the backend on http://localhost:7137. 4. Start the portal on http://localhost:5173. 5. Ensure the signed-in corporate account can obtain a B2C access token. The API auto-provisions a matching active employee on first authenticated request when none exists.