509. Integrating Foretify Manager with Microsoft Entra ID Single Sign-On (SSO)
Foretify Manager supports integrating with Microsoft Entra ID (formerly Azure Active Directory) SSO using OAuth2 and OpenID Connect (OIDC), to provide secure, centralized authentication and authorization for users accessing the Foretify platform, while user credentials remain managed by the organization’s identity provider.
Important
Before integrating with Microsoft Entra ID, configure Foretify Manager to use SSL (HTTPS) by following secure and configure Foretify Manager.
509.1 Configure Foretify Manager in Microsoft Entra ID
Register Foretify Manager as a single-page application (SPA) in Microsoft Entra ID to enable users to authenticate using their organization's identity provider.
-
Sign in to the Microsoft Entra admin center or Azure Portal and navigate to Azure Active Directory > App registrations > New registration.
-
Configure Foretify Manager as an application:
- Name: Enter a name for the application (e.g., "Foretify Manager").
- Supported account types: Select "Accounts in this organizational directory only" (single tenant).
- Redirect URI:
- Platform: Single-page application (SPA)
- URI: Set to Foretify Manager's
/login/callbackroute (e.g.,https://fmanager.example.com/login/callback).
-
Click Register to create the application.
-
Configure authentication settings:
- Navigate to Authentication in your app registration.
- Under Platform configurations > Single-page application:
- Ensure the Redirect URI is set to
https://fmanager.example.com/login/callback(replace with your actual URL). - Add a Front-channel logout URL:
https://fmanager.example.com.
- Ensure the Redirect URI is set to
- Under Implicit grant and hybrid flows:
- Leave both checkboxes unchecked (do not enable "Access tokens" or "ID tokens").
- The Single-page app (SPA) platform automatically uses the modern and more secure Authorization Code Flow with PKCE.
- The implicit flow is a legacy method and should not be used.
- Under Allow public client flows:
- Enable Allow public client flows to allow device code flow for programatically generating an ID token. This setting enables programmatic access to the Foretify Manager API. See token generation below for an example script.
-
Click Save.
-
Create App roles for authorization:
- Navigate to App roles > Create app role.
- Create two roles using these exact values:
- FMANAGER_ADMIN: For Administrator access to Foretify Manager.
- FMANAGER_USER: For Standard user access to Foretify Manager.
- Assign roles for each user or group:
- Display name:
FMANAGER_ADMINorFMANAGER_USER. - Allowed member types: Select Users or Groups.
- Value:
FMANAGER_ADMINorFMANAGER_USER(must match exactly). - Description: Provide an appropriate description.
- Click Apply for each role.
-
Assign users to roles:
- Navigate to Enterprise applications and find your Foretify Manager application.
- Go to Users and groups > Add user/group.
- Select users or groups and assign them to
FMANAGER_ADMINorFMANAGER_USER. - Click Assign for each user or group.
509.2 Configure Microsoft Entra ID in Foretify Manager
Note
Foretify Manager must be configured to use SSL (HTTPS) before integrating with Microsoft Entra ID. Follow Secure and configure Foretify Manager for instructions.
Configure Microsoft Entra ID settings in Foretify Manager by editing the following properties in the application.properties file.
| Property | Description |
|---|---|
| spring.security.oauth2.client.registration.microsoft-entra-id.client-id | Application (client) ID from Azure (found on app's Overview page) |
| spring.security.oauth2.client.provider.microsoft-entra-id.tenant-id | Directory (tenant) ID from Azure (found on app's Overview page) |
| spring.security.oauth2.client.provider.microsoft-entra-id.authorization-uri | OAuth 2.0 authorization endpoint. Usually https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize |
| spring.security.oauth2.client.provider.microsoft-entra-id.token-uri | OAuth 2.0 token endpoint. Usually https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token |
| spring.security.oauth2.client.provider.microsoft-entra-id.issuer-uri | OAuth 2.0 token endpoint. Usually https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0 |
| spring.security.oauth2.client.provider.microsoft-entra-id.callback-uri | URL for Foretify Manager's callback route (see "Redirect URI" above) |
| spring.security.oauth2.client.provider.microsoft-entra-id.post-logout-redirect-uri | (Optional) URL where users are redirected after logout. Defaults to Foretify Manager's homepage. Must match "Front-channel logout URL" in Azure |
For example:
spring.security.oauth2.client.registration.microsoft-entra-id.client-id=12345678-1234-1234-1234-123456789abc
spring.security.oauth2.client.provider.microsoft-entra-id.tenant-id=87654321-4321-4321-4321-cba987654321
spring.security.oauth2.client.provider.microsoft-entra-id.authorization-uri=https://login.microsoftonline.com/87654321-4321-4321-4321-cba987654321/oauth2/v2.0/authorize
spring.security.oauth2.client.provider.microsoft-entra-id.token-uri=https://login.microsoftonline.com/87654321-4321-4321-4321-cba987654321/oauth2/v2.0/token
spring.security.oauth2.client.provider.microsoft-entra-id.issuer-uri=https://login.microsoftonline.com/87654321-4321-4321-4321-cba987654321/oauth2/v2.0
spring.security.oauth2.client.provider.microsoft-entra-id.callback-uri=https://fmanager.example.com/login/callback
spring.security.oauth2.client.provider.microsoft-entra-id.post-logout-redirect-uri=https://fmanager.example.com
Front-channel logout URL
The post-logout-redirect-uri in application.properties must match the Front-channel logout URL configured in the Azure Portal (under Authentication). If omitted, it defaults to the Foretify Manager homepage. The Azure Portal requires this to be an HTTPS URL for production environments.
509.3 Usernames and roles
509.3.1 Username resolution
Foretify Manager reads the JSON Web Token (JWT) and uses the first available value from these token claims, in order, as the username:
- preferred_username - Primary username (typically the UPN).
- upn - User Principal Name.
- email - User's email address.
- sub - Subject identifier (stable unique user ID; not human-friendly).
509.3.2 Role authorization
User roles are derived from the JWT roles claim (from App Roles).
509.4 Token generation
Enabling public client flows in the app registration authentication settings allows you to generate an ID token programatically using the device code flow. With an ID token, you can then generate a Foretify Manager access token, which can be used to interact with the Foretify Manager API via direct REST API calls or the Python SDK.
The script below demonstrates these steps and ends by printing the generated access token. Be sure to fill in the values for FMANAGER_URL, MEID_TENANT_ID, and MEID_CLIENT_ID with the full HTTPS Foretify Manager URL and your Microsoft Entra ID tenant and client IDs.
#!/bin/bash
FMANAGER_URL=
MEID_TENANT_ID=
MEID_CLIENT_ID=
TTL=43200 # 12 hours in seconds
# Step 1: Request device code
DEVICE_RESPONSE=$(curl -s -X POST \
"https://login.microsoftonline.com/${MEID_TENANT_ID}/oauth2/v2.0/devicecode" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=${MEID_CLIENT_ID}&scope=openid profile")
DEVICE_CODE=$(echo $DEVICE_RESPONSE | jq -r '.device_code')
USER_CODE=$(echo $DEVICE_RESPONSE | jq -r '.user_code')
VERIFICATION_URI=$(echo $DEVICE_RESPONSE | jq -r '.verification_uri')
INTERVAL=$(echo $DEVICE_RESPONSE | jq -r '.interval')
echo "Please visit: $VERIFICATION_URI" >&2
echo "And enter code: $USER_CODE" >&2
echo "Waiting for authentication..." >&2
# Step 2: Poll for token
while true; do
sleep $INTERVAL
TOKEN_RESPONSE=$(curl -s -X POST \
"https://login.microsoftonline.com/${MEID_TENANT_ID}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=${MEID_CLIENT_ID}&device_code=${DEVICE_CODE}")
ERROR=$(echo $TOKEN_RESPONSE | jq -r '.error // empty')
if [ "$ERROR" = "authorization_pending" ]; then
continue
elif [ -z "$ERROR" ]; then
echo "Authentication successful!" >&2
break
else
echo "Error: $ERROR" >&2
echo $TOKEN_RESPONSE | jq >&2
exit 1
fi
done
# Step 3: Extract ID token
ID_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.id_token')
# Step 4: Generate Access Token
echo "Retrieving access token..." >&2
FINAL_RESPONSE=$(curl -s -X POST "${FMANAGER_URL}/api/accessTokens/generate" \
-H "Authorization: Bearer ${ID_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"timeToExpirationInSeconds\": $TTL}")
TOKEN=$(echo "$FINAL_RESPONSE" | jq -r '.token // .accessToken // .jwtToken // empty')
echo "$TOKEN"
509.5 Troubleshooting integration with Microsoft Entra ID SSO
509.5.1 Issue: Users cannot access Foretify Manager
Symptom: User authenticates successfully but gets an "Unauthorized" error after login, and cannot access Foretify Manager.
Likely cause: The user is not assigned to the Foretify Manager app in Microsoft Entra ID, or the App role is missing or incorrect.
Solution:
- Verify the user is assigned to the application in Microsoft Entra ID.
- Verify the user has been assigned an appropriate role (FMANAGER_ADMIN or FMANAGER_USER).
- Review Foretify Manager logs for authentication details.
509.5.2 Issue: Token validation fails
Symptom: Authentication fails with token validation errors in logs.
Solution:
- Verify the tenant-id is correct in application.properties.
- Ensure the server time is synchronized (JSON Web Token (JWT) validation is time-sensitive).
- Check that HTTPS is properly configured (required for production).
509.5.3 Issue: Roles not recognized
Symptom: User authenticates but has incorrect permissions.
Solution:
- Verify App Roles are properly configured in Microsoft Entra ID.
- Ensure role values match exactly: FMANAGER_ADMIN or FMANAGER_USER
- Verify users are assigned roles in Enterprise Applications > Users and groups
- Review the JWT token claims. Use jwt.ms to decode and inspect tokens.
509.5.4 Issue: Redirect URI mismatch
Symptom: Authentication fails with a redirect_uri_mismatch error.
Solution:
- Ensure the redirect URI in Microsoft Entra ID matches the callback in application.properties exactly.
- Verify the URI uses the HTTPS protocol.
- Check for trailing slashes or case sensitivity issues.