This runbook explains how to set up Microsoft Entra app registrations for Outlook email integration and user authentication.
The setup-outlook.ps1 script creates two app registrations:
Orcha Email - {env})For email acquisition (reading Outlook inbox):
https://{app-domain}/oauth/outlook/callbackOrcha Auth - {env})For direct user authentication (bypasses Cognito):
https://{app-domain}/auth/microsoft/callbackNote: Microsoft authentication is handled directly by the application instead of through Cognito because Cognito's OIDC issuer validation rejects Microsoft's multi-tenant tokens (the issuer varies by tenant ID).
After deploying Phase 1 (FoundationStack + DataStack) and before deploying Phase 2 (ComputeStack).
Install-Module Microsoft.Graph -Scope CurrentUser
contoso.onmicrosoft.com)app.getorcha.com)Install-Module Microsoft.Graph -Scope CurrentUser
cd /home/volrath/code/orcha/orcha/infra
./scripts/setup-outlook.ps1 `
-EnvName "prod" `
-TenantId "contoso.onmicrosoft.com" `
-AppDomain "app.getorcha.com"
The script will:
The Email App is used for both email acquisition and direct authentication. Add the auth redirect URI to the existing Email App:
Via Azure Portal:
https://app.getorcha.com/auth/microsoft/callbackhttps://orcha.barreto.tech/auth/microsoft/callbackVia PowerShell:
Connect-MgGraph -Scopes "Application.ReadWrite.All"
$app = Get-MgApplication -Filter "displayName eq 'Orcha Email - prod'"
$currentUris = $app.Web.RedirectUris
$newUris = $currentUris + @(
"https://app.getorcha.com/auth/microsoft/callback",
"https://orcha.barreto.tech/auth/microsoft/callback"
)
Update-MgApplication -ApplicationId $app.Id -Web @{
RedirectUris = $newUris
}
Generate a secure secret for HMAC state signing:
# Generate a 32-character random secret
openssl rand -base64 24
# Add to your secrets file
echo "/v1-orcha/microsoft-auth-state-secret=<generated-secret>" >> secrets
# Update SSM
./scripts/update-secrets.sh --from-file secrets
Navigate to Applications > App registrations
Find "Orcha Email - prod" and verify:
https://app.getorcha.com/oauth/outlook/callback (email acquisition)https://app.getorcha.com/auth/microsoft/callback (direct auth)accessTokenAcceptedVersion)Cause: App registration doesn't support personal Microsoft accounts.
Fix: The app must be created with:
SignInAudience = "AzureADandPersonalMicrosoftAccount"accessTokenAcceptedVersion = 2 in manifestDelete and recreate the apps with -DeleteExisting:
./scripts/setup-outlook.ps1 `
-EnvName "prod" `
-TenantId "contoso.onmicrosoft.com" `
-AppDomain "app.getorcha.com" `
-DeleteExisting
Cause: Redirect URI mismatch.
Fix:
https://app.getorcha.com/auth/microsoft/callbackhttps://app.getorcha.com/oauth/outlook/callbackCause: Client secret expired or copied incorrectly.
Fix:
/v1-orcha/outlook-client-secretCause: Missing permissions or wrong token version.
Fix:
accessTokenAcceptedVersion: 2Cause: Missing or incorrect state secret.
Fix:
/v1-orcha/microsoft-auth-state-secret| Resource | Prod Value |
|---|---|
| Email App Name | Orcha Email - prod |
| App Domain | app.getorcha.com |
| Email Redirect URI | https://app.getorcha.com/oauth/outlook/callback |
| Auth Redirect URI | https://app.getorcha.com/auth/microsoft/callback |
| Local Dev Auth URI | https://orcha.barreto.tech/auth/microsoft/callback |
| Email API Permissions | Mail.Read, User.Read, offline_access |
| Auth API Permissions | openid, email, profile |
| Client Secret Expiry | 24 months |
| Script | scripts/setup-outlook.ps1 |
Email Acquisition (Orcha Email - prod):
| Parameter | Purpose |
|---|---|
/v1-orcha/outlook-client-id |
Microsoft OAuth client ID for email |
/v1-orcha/outlook-client-secret |
Microsoft OAuth client secret for email |
/v1-orcha/outlook-state-secret |
HMAC secret for email OAuth state |
Direct Authentication (Orcha Auth - prod):
| Parameter | Purpose |
|---|---|
/v1-orcha/microsoft-auth-client-id |
Microsoft OAuth client ID for auth |
/v1-orcha/microsoft-auth-client-secret |
Microsoft OAuth client secret for auth |
/v1-orcha/microsoft-auth-state-secret |
HMAC secret for auth OAuth state |
Email Acquisition:
User → App → Microsoft → App → Store tokens in SSM
Direct Authentication (bypasses Cognito):
User → App → Microsoft → App → Validate JWT → Create session
Why not Cognito for Microsoft?
Cognito's OIDC issuer validation requires an exact match, but Microsoft
multi-tenant tokens have tenant-specific issuers like:
- https://login.microsoftonline.com/{tenant-id}/v2.0
The issuer varies by user's organization, so Cognito rejects the tokens.
Direct authentication validates the issuer pattern instead of exact match.