Microsoft 365 OAuth Integration
The ticket system uses Microsoft 365 OAuth 2.0 to fetch and send emails via the Microsoft Graph API, replacing traditional IMAP/SMTP with token-based authentication.
Overview
| Component | Details |
|---|---|
| Protocol | OAuth 2.0 Authorization Code Flow |
| API | Microsoft Graph API v1.0 |
| Operations | Mail fetch (IMAP replacement) + Mail send (SMTP replacement) |
| Token Storage | ost_config table (encrypted) |
| Refresh | Automatic token refresh on expiry |
| Key File | include/class.oauth.php |
Architecture
osTicket Email Account
→ OAuth Authorization (one-time consent flow)
→ Access Token + Refresh Token stored in DB
→ Cron fetches mail via Graph API: GET /me/mailFolders/inbox/messages
→ New emails → ticket creation or thread reply
→ Outbound mail sent via Graph API: POST /me/sendMail
→ Token auto-refreshes when expired
Azure AD Configuration
Step 1: Register Application
- Go to Azure Portal → App Registrations
- Click New registration
- Set name:
osTicket Mail Integration - Set redirect URI:
https://tickets.rhinogroup.com/scp/oauth-callback.php - Click Register
Step 2: Copy Application IDs
From the app's Overview page, copy:
- Application (client) ID → Used as Client ID in osTicket
- Directory (tenant) ID → Used as Tenant ID in osTicket
Step 3: Create Client Secret
- Go to Certificates & secrets
- Click New client secret
- Set description and expiry (recommended: 24 months)
- Copy the secret Value immediately (shown only once)
Step 4: Configure API Permissions
Add these Delegated permissions under Microsoft Graph:
| Permission | Purpose |
|---|---|
Mail.Read | Read emails from inbox |
Mail.ReadWrite | Mark emails as read, move to folders |
Mail.Send | Send emails on behalf of user |
offline_access | Refresh tokens without re-authorization |
User.Read | Basic user profile (required by default) |
Click Grant admin consent after adding permissions.
Step 5: Configure Authentication
- Go to Authentication
- Verify redirect URI:
https://tickets.rhinogroup.com/scp/oauth-callback.php - Under Implicit grant, leave unchecked (using authorization code flow)
- Set Supported account types to: Single tenant (this organization only)
osTicket Configuration
In Admin Panel
- Navigate to Admin → Emails
- Select the email account (e.g.,
[email protected]) - Go to the OAuth tab
- Enter:
- Tenant ID: Your Azure AD Directory ID
- Client ID: Application (client) ID from Azure
- Client Secret: The secret value you copied
- Click Authorize — this opens Microsoft login
- Complete the consent flow
- On success, you'll be redirected back with tokens saved
IMAP/SMTP Settings (Graph API Mode)
When OAuth is configured, these settings are used alongside Graph API:
| Setting | Value |
|---|---|
| Fetch Protocol | Microsoft Graph API |
| Send Protocol | Microsoft Graph API |
| Fetch Frequency | Every minute (via cron) |
Token Management
Storage
Tokens are stored encrypted in the ost_config table:
oauth_access_token— Short-lived (1 hour)oauth_refresh_token— Long-lived (90 days, rolling)oauth_token_expires— Expiry timestamp
Automatic Refresh
// class.oauth.php handles token refresh automatically
if ($token->isExpired()) {
$newToken = $oauth->refreshToken($refreshToken);
// Stores new access_token + updated refresh_token
}
Manual Re-authorization
If the refresh token expires (90 days without use):
- Go to Admin → Emails → (account) → OAuth tab
- Click Re-authorize
- Complete the Microsoft login flow again
Email Threading
Inbound Email Matching
When a new email arrives, the system matches it to existing tickets using:
- Message-ID / In-Reply-To headers — Primary match
- References header — Secondary match
- Subject line pattern — Fallback (
[#XXXXXX]ticket number extraction)
Auto-Reply Detection
The system detects and discards auto-replies:
- X-Auto-Responded-Suppress headers
- Auto-Submitted: auto-replied
- X-Autoreply headers
- Out-of-office patterns in subject
Inline Images
Inline images in HTML emails are handled via:
- CID references are extracted from email MIME parts
- Images are saved as attachments in osTicket's file system
- CID references in HTML are replaced with attachment URLs
Troubleshooting
| Issue | Solution |
|---|---|
| Authorization fails with "invalid_client" | Verify Client ID and Secret match Azure app |
| Token refresh fails | Re-authorize from Admin → Emails → OAuth tab |
| Emails not being fetched | Check cron is running; verify permissions in Azure |
| "Insufficient privileges" error | Ensure admin consent was granted for all permissions |
| Redirect URI mismatch | Verify exact URL in Azure matches osTicket callback |
| Sent emails not appearing in Sent folder | Add Mail.ReadWrite permission for folder access |
Security Considerations
- Client secrets should be rotated before expiry (set calendar reminders)
- Use single-tenant mode to restrict access to your organization
- Monitor sign-in logs in Azure AD for unauthorized access attempts
- The refresh token grants long-lived access — treat the database as sensitive
- Redirect URI must use HTTPS in production
Key Files
| File | Purpose |
|---|---|
include/class.oauth.php | OAuth flow, token storage, refresh logic |
scp/oauth-callback.php | Redirect URI handler (receives auth code) |
include/class.mailfetch.php | Email fetching (uses OAuth tokens for Graph API) |
include/class.mailer.php | Email sending (uses OAuth tokens for Graph API) |