Skip to content

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:

  1. Critical Code Bug: The azure_configured template variable was not being passed to the signin template on initial page load
  2. 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_ID
  • AZURE_CLIENT_ID
  • AZURE_CLIENT_SECRET
  • AZURE_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:

  1. Go to repository Settings
  2. Click "Secrets and variables" → "Actions"
  3. 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)

  1. Create App Registration:
  2. Go to Azure Portal → Azure Active Directory → App registrations
  3. Click "New registration"
  4. Name: "S5 Slidefactory Preview"
  5. Supported account types: Choose based on your needs (typically "Single tenant")
  6. Redirect URI:
    • Platform: Web
    • URI: https://your-preview-domain.azurecontainerapps.io/auth/callback
  7. Click "Register"

  8. Create Client Secret:

  9. In your app registration → Certificates & secrets
  10. Click "New client secret"
  11. Description: "Preview deployment"
  12. Expires: Choose duration (recommended: 24 months)
  13. Click "Add"
  14. IMPORTANT: Copy the secret value immediately (it won't be shown again)

  15. Configure API Permissions (if needed):

  16. In your app registration → API permissions
  17. Add permissions as needed (e.g., User.Read for basic profile)
  18. Click "Grant admin consent" if required

  19. Note the IDs:

  20. Tenant ID: App registration → Overview
  21. Client ID: App registration → Overview
  22. Client Secret: The value you copied in step 2
  23. 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/login and /auth/callback endpoints are registered

  • Configuration Status Endpoint:

  • Check /auth/azure/status endpoint
  • 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

  1. User clicks "Sign in with Microsoft"
  2. App redirects to Microsoft login (/auth/azure/login)
  3. Microsoft authenticates user and redirects to callback (/auth/callback)
  4. App validates OAuth response using MSAL library
  5. App creates session and redirects user to application

Dependencies

  • MSAL (Microsoft Authentication Library): Required for Azure AD authentication
  • Verify msal>=1.28.0 is in requirements.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

  1. app/auth/router.py - Added azure_configured variable to signin template
  2. .github/workflows/preview.yml - Added Azure AD environment variables to all container deployments

Files Referenced


Next Steps

  1. Add GitHub Secrets:
  2. Follow instructions above to add all 4 required secrets
  3. Verify secrets are properly set in repository settings

  4. Deploy:

  5. Push changes to preview branch
  6. Monitor GitHub Actions workflow execution
  7. Check deployment logs for "Azure authentication router enabled"

  8. Test:

  9. Use testing checklist above
  10. Verify Microsoft sign-in button appears
  11. Test complete authentication flow

  12. Production Deployment (Optional):

  13. Create separate Azure App Registration for production
  14. Add secrets: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_REDIRECT_URI
  15. Update .github/workflows/production.yml with same environment variable additions
  16. 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.