This document provides a comprehensive, step‑by‑step implementation guide for securing a standalone React single‑page application (SPA) that serves agricultural research data using Microsoft Entra External ID (CIAM) OAuth2/OIDC. It covers the full end‑to‑end architecture, from Entra tenant configuration (app registrations, app roles, and custom extension claims for company, crop, and trial permissions) through React client setup with MSAL (PKCE authorization‑code flow, silent token acquisition, and UI role gating) to Azure API Management (APIM) gateway enforcement using the native `validate-azure-ad-token` policy, claim forwarding, and azp validation. The guide then details a .NET 8 isolated‑worker Azure Function middleware that re‑validates the JWT, extracts claims, and enforces fine‑grained permission logic (full‑access vs. breeder‑access) against a hierarchical data‑level permission model. Security hardening recommendations include locking Functions to APIM, using managed identities, caching signing keys, and defence‑in‑depth checks. An appended OSINT section summarizes publicly available information about the GRDC’s current Entra footprint, the likely migration from Azure AD B2C to Entra External ID, and a profile of Nathan Cook, a newly hired GRDC engineer, to infer the organization’s identity strategy. The guide is intended for developers and architects building CIAM‑enabled portals for sensitive agricultural data.
Topics
Configuring Entra External ID App Registrations and App Roles for Full and Breeder Access
Step‑by‑step creation of two app registrations (API and SPA), definition of app roles (VarietyData.FullAccess, VarietyData.BreederAccess) in the manifest, and assignment of users/groups.
Defining and Issuing Custom Extension Claims for Company, Crops, and Trials
Use of the b2c‑extensions‑app to add directory extension attributes, token configuration to emit `extension_<appclientid>_companyCode`, `allowedCrops`, `allowedTrials`, and optional token‑enrichment Azure Function for dynamic permissions.
React SPA MSAL Setup and PKCE Authorization Code Flow
Installation of `@azure/msal-react` and `@azure/msal-browser`, configuration object (clientId, authority, redirectUri, knownAuthorities), silent token acquisition, fallback to popup/redirect, and sessionStorage caching.
Client‑Side Role‑Based UI Gating and Safe Token Decoding Practices
Utility hook to read `roles` claim from the cached id token, UI conditional rendering, and warning that client‑side checks are UX only; real enforcement must happen downstream.
Azure API Management JWT Validation Policy and Claim Forwarding
Use of the native `<validate-azure-ad-token>` policy with tenant‑id, audience, client‑application‑ids, required‑claims for roles, and setting of outbound headers (`X-User-Roles`, `X-User-Company`). Includes azp claim validation example.
.NET 8 Isolated Worker JWT Middleware Implementation in Azure Functions
Code for a custom `JwtAuthMiddleware` implementing `IFunctionsWorkerMiddleware`, token extraction, OpenID configuration retrieval, `TokenValidationParameters`, caching strategy, and storing `ClaimsPrincipal` in `FunctionContext`.
Fine‑Grained Permission Enforcement Logic in Function Handlers
Sample `GetVarieties` function that checks roles, extracts custom extension claims, and calls repository methods to return either all varieties or breeder‑scoped filtered data.
Hierarchical Data‑Level Permission Model and Token Enrichment Extension Pattern
Design of nested permission claims (companyCode → allowedCrops[] → allowedTrials[]), and recommendation to use a Custom Authentication Extension Azure Function at token issuance time to keep permissions up‑to‑date.