Skip to main content

Azure CIAM Setup

NextGenPoll uses Azure External Identities (CIAM) for presenter and admin authentication. Participants do not need an account.


Step 1 — Create an Azure CIAM Tenant

  1. Go to the Azure Portal.
  2. Search for Microsoft Entra External ID (or External Identities).
  3. Click Create a tenantExternal (CIAM).
  4. Fill in:
    • Organization name: NextGenPoll
    • Initial domain name: nextgenpoll (resulting in nextgenpoll.ciamlogin.com)
    • Country/region: Your region
  5. Click Review + Create.

Note the Tenant ID — you will need it as AZURE_TENANT_ID.


Step 2 — Register the Frontend Application

Inside your CIAM tenant:

  1. Go to App registrationsNew registration.
  2. Fill in:
    • Name: NextGenPoll Web
    • Supported account types: Accounts in this organizational directory only
    • Redirect URI (Single-page application):
      • http://localhost:3000/auth/callback (dev)
      • https://nextgenpoll.com/auth/callback (prod)
  3. Click Register.
  4. Note the Application (client) ID — this is NEXT_PUBLIC_AZURE_CLIENT_ID.

Add Additional Redirect URIs

After registration, go to Authentication and add:

  • http://localhost:3000/auth/silent-redirect (dev)
  • https://nextgenpoll.com/auth/silent-redirect (prod)

Enable the following under Implicit grant and hybrid flows — leave both unchecked (SPA uses PKCE, not implicit).

Enable under Advanced settings:

  • Allow public client flows: No

Step 3 — Expose an API Scope

  1. Go to Expose an API.
  2. Set the Application ID URI — accept the default or use api://{client-id}.
  3. Click Add a scope:
    • Scope name: access_as_user
    • Admin consent display name: Access NextGenPoll API
    • State: Enabled
  4. Note the full scope string (e.g. api://{client-id}/access_as_user) — this is NEXT_PUBLIC_AZURE_API_SCOPE.

Step 4 — Grant API Permissions

  1. Go to API permissionsAdd a permissionMy APIs.
  2. Select NextGenPoll Web.
  3. Check access_as_user.
  4. Click Grant admin consent for the tenant.

Step 5 — Configure User Flows

  1. Go to User flowsNew user flow.
  2. Choose Sign in and sign up.
  3. Configure:
    • Identity providers: Email with password (and/or social providers as needed)
    • User attributes: Email, Display name
  4. Click Create.
  5. Note the user flow name (e.g., B2C_1_signupsignin) — it forms part of the authority URL.

The authority URL format:

https://{tenant-name}.ciamlogin.com/{tenant-id}/v2.0

This is NEXT_PUBLIC_AZURE_AUTHORITY.


Step 6 — Set Backend Environment Variables

The backend validates JWTs. It needs the JWKS endpoint derived from the tenant ID:

# In application.yml (set via AZURE_TENANT_ID env var)
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://{tenant-name}.ciamlogin.com/{tenant-id}/discovery/v2.0/keys

This is configured automatically when AZURE_TENANT_ID is set.


Step 7 — Set Frontend Environment Variables

NEXT_PUBLIC_AZURE_CLIENT_ID=<application-client-id>
NEXT_PUBLIC_AZURE_AUTHORITY=https://<tenant-name>.ciamlogin.com/<tenant-id>/v2.0
NEXT_PUBLIC_AZURE_REDIRECT_URI=https://nextgenpoll.com/auth/callback
NEXT_PUBLIC_AZURE_POST_LOGOUT_REDIRECT_URI=https://nextgenpoll.com
NEXT_PUBLIC_AZURE_API_SCOPE=api://<client-id>/access_as_user
AZURE_TENANT_ID=<tenant-id>

Known Issue: Login Loop on Dev (React StrictMode)

Symptom: In development, the login redirects to Azure and back but ends up stuck in a redirect loop.

Root Cause: React StrictMode double-fires useEffect in development, causing two concurrent loginRedirect() calls. The second call throws interaction_in_progress, which triggers resetRequestCache() — clearing the PKCE code verifier after the first call has already set it. Azure returns a code, but the verifier is missing, so handleRedirectPromise returns null and the page re-initiates login.

Fix (already applied): A useRef guard (loginInitiated) in app/login/page.tsx prevents the second loginRedirect() call. The MSAL PCA singleton is also stored on window.__NEXTGENPOLL_MSAL__ to survive HMR reloads.

If you see this in production: Check that the redirect URIs registered in CIAM exactly match the ones in the environment variables (including trailing slashes and http vs https).


Creating the First Admin User

After setup, the seeded admin account is:

  • Email: [email protected]
  • Password: Set this directly in the CIAM tenant → Users → Create user.

Alternatively, invite users via the Admin dashboard at nextgenpoll.com/admin.