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
- Go to the Azure Portal.
- Search for Microsoft Entra External ID (or External Identities).
- Click Create a tenant → External (CIAM).
- Fill in:
- Organization name:
NextGenPoll - Initial domain name:
nextgenpoll(resulting innextgenpoll.ciamlogin.com) - Country/region: Your region
- Organization name:
- 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:
- Go to App registrations → New registration.
- 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)
- Name:
- Click Register.
- 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
- Go to Expose an API.
- Set the Application ID URI — accept the default or use
api://{client-id}. - Click Add a scope:
- Scope name:
access_as_user - Admin consent display name:
Access NextGenPoll API - State: Enabled
- Scope name:
- Note the full scope string (e.g.
api://{client-id}/access_as_user) — this isNEXT_PUBLIC_AZURE_API_SCOPE.
Step 4 — Grant API Permissions
- Go to API permissions → Add a permission → My APIs.
- Select NextGenPoll Web.
- Check
access_as_user. - Click Grant admin consent for the tenant.
Step 5 — Configure User Flows
- Go to User flows → New user flow.
- Choose Sign in and sign up.
- Configure:
- Identity providers: Email with password (and/or social providers as needed)
- User attributes: Email, Display name
- Click Create.
- 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.