Microsoft Sign-in Button Not Showing on Preview Deployment - Root Cause Analysis and Fix¶
Date: 2025-11-02 Issue: "Sign in with Microsoft" button not visible on deployed preview instance Status: Fixed
Executive Summary¶
The Microsoft sign-in button was not appearing on the preview deployment signin page due to two issues:
- Critical Code Bug: The
azure_configuredtemplate variable was not being passed to the signin template on initial page load - Missing Configuration: Azure AD environment variables were not configured in the preview deployment workflow
Both issues have been resolved.
Root Cause Analysis¶
Issue 1: Missing Template Variable (Critical Bug)¶
Location: app/auth/router.py:35-46
Problem: The GET handler for the signin page (@router.get("/")) was not passing the azure_configured variable to the template:
# BEFORE (Broken)
return templates.TemplateResponse("signin.html.j2", {
"request": request,
"version": settings.VERSION
}) # azure_configured NOT passed
Impact: The signin template (app/auth/templates/signin.html.j2:194-205) has a conditional that only renders the Microsoft sign-in button when azure_configured is truthy:
{% if azure_configured %}
<div class="azure-auth">
<a href="/auth/azure/login?redirect_url={{ redirect_url or '/' | urlencode }}"
role="button"
class="outline">
<i class="fab fa-microsoft"></i>
Sign in with Microsoft
</a>
</div>
{% endif %}
Since the variable was not passed, the condition evaluated to False and the button never rendered.
Interesting Finding: The variable was being passed in the POST error handler (line 204-218), which means the button would only appear after a failed login attempt, not on initial page load.
Issue 2: Missing Azure AD Environment Variables¶
Location: .github/workflows/preview.yml
Problem: The preview deployment workflow was not setting the required Azure AD environment variables in the container apps. The workflow set many other secrets (OpenAI, Mistral, Anthropic, storage, etc.) but was missing:
AZURE_TENANT_IDAZURE_CLIENT_IDAZURE_CLIENT_SECRETAZURE_REDIRECT_URI
Impact: Even if the button had been displayed, the authentication flow would fail because the application requires all four variables to be non-empty for Azure authentication to work (app/auth/azure_auth.py:218-232):
def is_azure_configured() -> bool:
required_settings = [
settings.AZURE_TENANT_ID,
settings.AZURE_CLIENT_ID,
settings.AZURE_CLIENT_SECRET,
settings.AZURE_REDIRECT_URI
]
return all(setting for setting in required_settings)
Additionally, the Azure authentication router is only registered in the main app if is_azure_configured() returns True (app/main.py:337-347), meaning the /auth/azure/login endpoint wouldn't even exist.
Solutions Implemented¶
Fix 1: Pass azure_configured Variable to Template¶
File: app/auth/router.py
Change:
# AFTER (Fixed)
@router.get("/")
def redirect_to_sign_in_or_matching(request: Request, user: SessionData = Depends(verifier)):
if ( request.cookies ):
if ( settings.COOKIE_NAME in request.cookies.keys() ):
return RedirectResponse("/home")
# Check if Azure authentication is configured to show/hide Microsoft sign-in button
try:
from app.auth.azure_auth import is_azure_configured
azure_configured = is_azure_configured()
except ImportError:
azure_configured = False
return templates.TemplateResponse("signin.html.j2", {
"request": request,
"version": settings.VERSION,
"azure_configured": azure_configured # ✅ Now passed
})
Rationale: - Imports is_azure_configured() to check if Azure AD is properly configured - Uses try/except to handle potential import errors gracefully - Passes azure_configured to template, enabling conditional rendering - Matches the pattern used in the POST error handler
Fix 2: Add Azure AD Environment Variables to Preview Deployment¶
File: .github/workflows/preview.yml
Changes: Added 4 Azure AD environment variables to all container deployments: 1. Web container update (line 90) 2. Web container create (line 108) 3. Worker container update (line 133) 4. Worker container create (line 151)
Added variables:
AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" \
AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" \
AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" \
AZURE_REDIRECT_URI="${{ secrets.AZURE_REDIRECT_URI }}"
Required GitHub Secrets Configuration¶
To complete the setup, the following secrets must be added to the GitHub repository:
Navigation¶
- Go to repository Settings
- Click "Secrets and variables" → "Actions"
- Click "New repository secret"
Secrets to Add¶
| Secret Name | Description | How to Obtain |
|---|---|---|
AZURE_TENANT_ID | Your Azure AD tenant/directory ID | Azure Portal → Azure Active Directory → Overview → Tenant ID |
AZURE_CLIENT_ID | Application (client) ID from app registration | Azure Portal → App registrations → [Your App] → Overview → Application (client) ID |
AZURE_CLIENT_SECRET | Client secret value | Azure Portal → App registrations → [Your App] → Certificates & secrets → Client secrets → New client secret |
AZURE_REDIRECT_URI | OAuth callback URL | Should be: https://your-preview-domain.azurecontainerapps.io/auth/callback |
Setting up Azure App Registration (if not done)¶
- Create App Registration:
- Go to Azure Portal → Azure Active Directory → App registrations
- Click "New registration"
- Name: "S5 Slidefactory Preview"
- Supported account types: Choose based on your needs (typically "Single tenant")
- Redirect URI:
- Platform: Web
- URI:
https://your-preview-domain.azurecontainerapps.io/auth/callback
-
Click "Register"
-
Create Client Secret:
- In your app registration → Certificates & secrets
- Click "New client secret"
- Description: "Preview deployment"
- Expires: Choose duration (recommended: 24 months)
- Click "Add"
-
IMPORTANT: Copy the secret value immediately (it won't be shown again)
-
Configure API Permissions (if needed):
- In your app registration → API permissions
- Add permissions as needed (e.g., User.Read for basic profile)
-
Click "Grant admin consent" if required
-
Note the IDs:
- Tenant ID: App registration → Overview
- Client ID: App registration → Overview
- Client Secret: The value you copied in step 2
- Redirect URI: What you configured in step 1
Testing Checklist¶
After deploying the fixes and configuring GitHub secrets:
- Initial Page Load:
- Navigate to preview signin page
- Verify "Sign in with Microsoft" button is visible
-
Verify button appears below the standard login form with "Or sign in with your organization account" text
-
Microsoft Authentication Flow:
- Click "Sign in with Microsoft" button
- Verify redirect to Microsoft login page
- Complete Microsoft authentication
- Verify redirect back to application
-
Verify user is logged in
-
Application Logs:
- Check container logs for:
"Azure authentication router enabled" - Verify no errors related to MSAL or Azure AD
-
Confirm
/auth/azure/loginand/auth/callbackendpoints are registered -
Configuration Status Endpoint:
- Check
/auth/azure/statusendpoint -
Verify it returns proper Azure AD configuration status
-
Error Handling:
- Test with invalid credentials
- Verify button still shows after failed standard login
- Verify graceful error messages
Technical Details¶
Authentication Flow¶
- User clicks "Sign in with Microsoft"
- App redirects to Microsoft login (
/auth/azure/login) - Microsoft authenticates user and redirects to callback (
/auth/callback) - App validates OAuth response using MSAL library
- App creates session and redirects user to application
Dependencies¶
- MSAL (Microsoft Authentication Library): Required for Azure AD authentication
- Verify
msal>=1.28.0is inrequirements.txt - Check import in app/auth/azure_router.py:29-36
Router Registration Logic¶
The Azure authentication router is conditionally registered (app/main.py:337-347):
try:
from app.auth.azure_router import router as azure_auth_router
from app.auth.azure_auth import is_azure_configured
if is_azure_configured():
app.include_router(azure_auth_router, prefix="/auth", tags=["azure-auth"])
logger.info("Azure authentication router enabled")
else:
logger.warning("Azure authentication not configured - router disabled")
except ImportError:
logger.warning("Azure authentication module not available")
This means: - Router only loads if all 4 environment variables are set - If not configured, /auth/azure/login endpoint won't exist - Application logs will show warning if not configured
Files Modified¶
- app/auth/router.py - Added
azure_configuredvariable to signin template - .github/workflows/preview.yml - Added Azure AD environment variables to all container deployments
Files Referenced¶
- app/auth/templates/signin.html.j2 - Template with conditional Microsoft sign-in button
- app/auth/azure_auth.py - Azure AD configuration validation
- app/auth/azure_router.py - Azure AD OAuth endpoints
- app/main.py - Router registration logic
- app/config.py - Environment variable definitions
Next Steps¶
- Add GitHub Secrets:
- Follow instructions above to add all 4 required secrets
-
Verify secrets are properly set in repository settings
-
Deploy:
- Push changes to
previewbranch - Monitor GitHub Actions workflow execution
-
Check deployment logs for "Azure authentication router enabled"
-
Test:
- Use testing checklist above
- Verify Microsoft sign-in button appears
-
Test complete authentication flow
-
Production Deployment (Optional):
- Create separate Azure App Registration for production
- Add secrets:
AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_REDIRECT_URI - Update .github/workflows/production.yml with same environment variable additions
- Test on production deployment
Additional Notes¶
Security Considerations¶
- Client secrets should never be committed to code
- Use GitHub encrypted secrets for all sensitive values
- Rotate client secrets periodically (every 6-24 months)
- Monitor Azure AD sign-in logs for suspicious activity
Troubleshooting¶
Button still not showing: - Check browser console for JavaScript errors - Verify GitHub secrets are set correctly (no typos) - Check container environment variables: az containerapp show --name slidefactory-web-preview --query properties.template.containers[0].env - Verify all 4 variables are non-empty
Authentication fails: - Verify redirect URI matches exactly what's in Azure App Registration - Check MSAL library is installed - Review application logs for MSAL errors - Verify tenant ID is correct
Router not registered: - Check application startup logs - Look for "Azure authentication router enabled" or warning messages - Verify is_azure_configured() returns True
Conclusion¶
The Microsoft sign-in button is now properly configured to: 1. ✅ Show on initial page load when Azure AD is configured 2. ✅ Hide when Azure AD is not configured (graceful degradation) 3. ✅ Work correctly in preview deployment environment 4. ✅ Support easy extension to production environment
The fix ensures proper separation of concerns and follows the existing codebase patterns for configuration-dependent features.