Skip to main content

Microsoft Integration Setup

All Microsoft integrations in BonardaHR are optional — the application works fully in dev mode without any Azure credentials. This guide covers how to configure each integration for staging and production environments.


Integration Overview​

IntegrationPurposeDefault Dev Behaviour
Azure AD SSO"Sign in with Microsoft" buttonDev login dropdown (no SSO button shown)
SharePointDocument browsing, upload, and previewMock service returns realistic fake data
Outlook Calendar SyncSync approved time-off to employee calendarsEvents logged to console only

Dev Workflow Summary​

ScenarioConfigWhat Works
Quick local devDefault (no env vars)Mock SharePoint + dev login (no SSO)
SSO testing onlySet AZURE_AD_* vars (free Azure account)Real Microsoft login + mock SharePoint
Full integrationSet AZURE_AD_* + MS_* + SP_MOCK_ENABLED=falseReal SSO + real SharePoint + calendar sync

Azure AD SSO Setup​

Prerequisites​

A regular free Azure account includes Azure AD (Entra ID) at no cost — no M365 Developer Program required.

Step 1 — Register an App in Azure​

  1. Sign in to Azure Portal
  2. Navigate to Azure Active Directory → App registrations → New registration
  3. Configure the registration:
    • Name: BonardaHR (or BonardaHR Dev)
    • Supported account types: Accounts in this organizational directory only
    • Redirect URI: Select Web and enter:
      http://localhost:8081/login/oauth2/code/azure
    • For production, also add:
      https://your-domain.com/login/oauth2/code/azure
  4. Click Register

Step 2 — Add API Permissions​

  1. Go to API permissions → Add a permission → Microsoft Graph → Delegated permissions
  2. Add the following permissions:
    • openid
    • profile
    • email
    • User.Read
  3. Click Grant admin consent for [Your Organization]

Step 3 — Create a Client Secret​

  1. Go to Certificates & secrets → New client secret
  2. Set a description and expiry (24 months recommended)
  3. Copy the secret value immediately — it's only shown once

Step 4 — Configure Environment Variables​

Add the following to your backend/.env file:

AZURE_AD_ENABLED=true
AZURE_AD_TENANT_ID=your-directory-tenant-id
AZURE_AD_CLIENT_ID=your-application-client-id
AZURE_AD_CLIENT_SECRET=your-client-secret-value
AZURE_AD_FRONTEND_CALLBACK_URL=http://localhost:5173/auth/callback
tip

Find your Tenant ID and Client ID in Azure Portal → App registrations → your app → Overview.

Step 5 — Create Test Users​

In Azure Active Directory → Users → New user, create users with emails matching your seeded employees (or create new employees in BonardaHR with matching emails).

Testing SSO​

  1. Start the backend: ./mvnw spring-boot:run
  2. Start the frontend: npm run dev
  3. Navigate to http://localhost:5173/login
  4. You should see a "Sign in with Microsoft" button
  5. Click it → Authenticate with a test user → You'll be redirected back to the app

Check SSO status via API:

curl http://localhost:8081/api/v1/auth/sso-config

Expected when enabled:

{
"ssoEnabled": true,
"ssoUrl": "http://localhost:8081/oauth2/authorization/azure"
}

SharePoint Integration Setup​

SharePoint integration uses application-level permissions (client credentials flow), so it does not require user delegation.

Prerequisites​

Your Azure tenant must have SharePoint Online (requires an M365 license). If you only have a free Azure account, use the mock service.

Step 1 — Register an App for SharePoint​

You can create a second app registration or add permissions to the existing SSO app.

  1. Go to App registrations → New registration (or use your existing SSO app)
  2. Go to API permissions → Add a permission → Microsoft Graph → Application permissions
  3. Add:
    • Sites.ReadWrite.All
    • Files.ReadWrite.All
  4. Click Grant admin consent for [Your Organization]
  5. Create a client secret (Certificates & secrets → New client secret)

Step 2 — Find Your SharePoint Site and Drive IDs​

Use Microsoft Graph Explorer to find your site and drive IDs:

GET https://graph.microsoft.com/v1.0/sites?search=your-site-name
GET https://graph.microsoft.com/v1.0/sites/{site-id}/drives

Step 3 — Configure Environment Variables​

# Microsoft Graph (SharePoint + Calendar)
MS_TENANT_ID=your-tenant-id
MS_CLIENT_ID=your-client-id
MS_CLIENT_SECRET=your-client-secret-value
SP_MOCK_ENABLED=false

# Optional: Quick Access library shortcuts
SP_POLICIES_SITE_ID=contoso.sharepoint.com,abc-123,def-456
SP_POLICIES_DRIVE_ID=b!abc123def456
SP_PERSONNEL_SITE_ID=contoso.sharepoint.com,ghi-789,jkl-012
SP_PERSONNEL_DRIVE_ID=b!ghi789jkl012

Testing SharePoint​

  1. Start the app with the env vars above
  2. Navigate to Documents → Add Document → Browse SharePoint
  3. You should see your organisation's SharePoint sites

Check SharePoint status via API:

curl -H "Authorization: Bearer <your-jwt>" http://localhost:8081/api/v1/sharepoint/status

Expected when configured:

{
"configured": true,
"libraries": [
{ "key": "policies", "name": "Company Policies", "configured": true },
{ "key": "personnel", "name": "Personnel Documents", "configured": true }
]
}

Outlook Calendar Sync Setup​

Calendar sync uses the same MS_* credentials as SharePoint — no additional app registration is needed. You only need to add the Calendars.ReadWrite application permission.

Step 1 — Add Calendar Permission​

In Azure Portal → your Microsoft Graph app → API permissions → Application permissions, add:

  • Calendars.ReadWrite

Then click Grant admin consent.

For calendar sync to work, an employee's microsoftUserId must be set in BonardaHR. This is populated automatically when the employee first signs in via SSO. For employees who don't use SSO, set it manually in the employee detail page.

Testing Calendar Sync​

  1. Ensure MS_* env vars are configured and Calendars.ReadWrite is granted
  2. Create or identify a test employee with a matching microsoftUserId
  3. Submit a time-off request for that employee
  4. Log in as a manager and Approve the request
  5. Check the employee's Outlook calendar — a new event should appear

Check sync status on a request:

curl -H "Authorization: Bearer <your-jwt>" http://localhost:8081/api/v1/time-off-requests/me

Look for "calendarSynced": true on approved requests.

Cancelling an approved request will delete the calendar event.


Complete .env Reference​

# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=bonarda_hr
DB_USERNAME=postgres
DB_PASSWORD=postgres

# JWT (generate a secure random string for production — minimum 32 chars)
JWT_SECRET=your-256-bit-secret-key-here-minimum-32-chars

# Azure AD SSO
AZURE_AD_ENABLED=true
AZURE_AD_TENANT_ID=12345678-1234-1234-1234-123456789012
AZURE_AD_CLIENT_ID=abcdef12-3456-7890-abcd-ef1234567890
AZURE_AD_CLIENT_SECRET=your-client-secret-value
AZURE_AD_FRONTEND_CALLBACK_URL=http://localhost:5173/auth/callback

# SharePoint / Microsoft Graph
MS_TENANT_ID=12345678-1234-1234-1234-123456789012
MS_CLIENT_ID=fedcba09-8765-4321-fedc-ba0987654321
MS_CLIENT_SECRET=another-client-secret-value
SP_MOCK_ENABLED=false

# Optional: Quick Access library shortcuts
SP_POLICIES_SITE_ID=contoso.sharepoint.com,abc-123,def-456
SP_POLICIES_DRIVE_ID=b!abc123def456
SP_PERSONNEL_SITE_ID=contoso.sharepoint.com,ghi-789,jkl-012
SP_PERSONNEL_DRIVE_ID=b!ghi789jkl012

Environment Variable Reference​

Azure AD SSO

VariableRequiredDefaultDescription
AZURE_AD_ENABLEDYesfalseSet to true to enable SSO
AZURE_AD_TENANT_IDIf enabled—Azure AD directory (tenant) ID
AZURE_AD_CLIENT_IDIf enabled—Application (client) ID
AZURE_AD_CLIENT_SECRETIf enabled—Client secret value
AZURE_AD_FRONTEND_CALLBACK_URLNohttp://localhost:5173/auth/callbackRedirect after successful auth

SharePoint / Microsoft Graph

VariableRequiredDefaultDescription
MS_TENANT_IDIf SP_MOCK_ENABLED=false—Azure AD tenant ID
MS_CLIENT_IDIf SP_MOCK_ENABLED=false—Application (client) ID
MS_CLIENT_SECRETIf SP_MOCK_ENABLED=false—Client secret value
SP_MOCK_ENABLEDNotrueSet to false to use real SharePoint
SP_POLICIES_SITE_IDNomock-site-hrSite ID for Policies library
SP_POLICIES_DRIVE_IDNomock-drive-hr-docsDrive ID for Policies library
SP_PERSONNEL_SITE_IDNomock-site-intranetSite ID for Personnel library
SP_PERSONNEL_DRIVE_IDNomock-drive-intranet-docsDrive ID for Personnel library

Troubleshooting​

SSO: "AADSTS50011: Reply URL does not match"​

Cause: The redirect URI in Azure doesn't match the callback URL.

Fix: Azure Portal → App registrations → your app → Authentication → add the exact redirect URI:

http://localhost:8081/login/oauth2/code/azure

SSO: "User not found" after authentication​

Cause: The authenticated user's email doesn't match any employee in the database.

Fix: Create an employee in BonardaHR with the same email as the Azure AD user, or create an Azure AD user with the email of a seeded employee.


SharePoint: "Access denied" or 403 errors​

Cause: Missing admin consent for application permissions.

Fix: Azure Portal → your app → API permissions → Grant admin consent for [Your Organization]. Ensure all permissions show a green checkmark.


SharePoint: "Configured: false" even with credentials​

Cause: Invalid credentials or SP_MOCK_ENABLED is still true.

Fix: Verify SP_MOCK_ENABLED=false, double-check tenant/client IDs and secret, and check backend logs for specific errors.


Calendar: Events not appearing in Outlook​

Cause: Missing Calendars.ReadWrite permission or employee has no microsoftUserId.

Fix:

  1. Verify Calendars.ReadWrite permission is granted with admin consent
  2. Ensure the employee has a microsoftUserId set (auto-populated on first SSO login)
  3. Verify the microsoftUserId matches a real user in your Azure AD tenant

Calendar: "calendarSynced": false on approved requests​

Cause: Calendar sync failed (approval still succeeded).

Fix: Check backend logs for the specific error. Common causes:

  • Employee has no microsoftUserId (expected — will be silently skipped)
  • Invalid microsoftUserId
  • Calendars.ReadWrite permission not granted
  • Microsoft Graph API quota exceeded (rare)
note

Calendar sync is best-effort — failures do not roll back time-off approvals. See ADR-023 for the rationale.


General: Environment variables not loading​

Fix:

  1. Ensure .env file is in the backend/ directory (not project root)
  2. Restart the backend after modifying .env
  3. Check for typos in variable names (case-sensitive)

Security Best Practices​

  1. Never commit secrets — ensure .env is in .gitignore
  2. Use separate app registrations for dev and production environments
  3. Rotate secrets regularly — Azure client secrets can expire
  4. Use managed identities when hosting on Azure (eliminates the need for secrets entirely)
  5. Limit permissions — only grant the permissions listed above
  6. Monitor usage — review Azure AD sign-in logs regularly for anomalies