Skip to main content

OAuth2 Token Management

EmailEngine automatically manages OAuth2 tokens for registered accounts, refreshing access tokens when they expire. You can also retrieve these tokens to use with other Google or Microsoft APIs directly.

Quick Reference

API Endpoint: GET /v1/account/{account}/oauth-token - Retrieve a valid OAuth2 access token for any account

Overview

When you register OAuth2 accounts in EmailEngine:

  • EmailEngine stores OAuth2 tokens in Redis
  • Access tokens are automatically refreshed when expired during API requests
  • EmailEngine makes regular API requests (at least daily) even for idle accounts, keeping refresh tokens active
  • You never need to handle token refresh logic
  • Tokens can be retrieved for use with other APIs via the OAuth2 Token API
Token Encryption

OAuth2 tokens (including sensitive refresh tokens and client secrets) are stored encrypted in Redis only if you configure the EENGINE_SECRET environment variable. Without encryption enabled, credentials are stored in cleartext. For production deployments, always enable encryption by setting a strong encryption secret. See encryption documentation →

This makes EmailEngine a convenient OAuth2 token manager for your entire application, not just for email access.

Use Cases

Email-Only Access

Most applications only need EmailEngine for email operations:

  • Reading emails via webhooks
  • Sending emails via REST API
  • Managing folders and messages

EmailEngine handles all OAuth2 complexity transparently.

Multi-Service Access

Some applications need to access multiple Google/Microsoft services:

Example with Gmail:

  • EmailEngine accesses Gmail for email operations
  • Your app accesses Google Calendar API
  • Your app accesses Google Drive API
  • All using the same OAuth2 tokens

Example with Outlook:

  • EmailEngine accesses Outlook for email operations
  • Your app accesses Microsoft Calendar API
  • Your app accesses OneDrive API
  • All using the same OAuth2 tokens

Instead of implementing separate OAuth2 flows, you can use EmailEngine as your central OAuth2 manager:

  1. Use EmailEngine for OAuth2 authentication
  2. Request additional scopes during setup
  3. Retrieve tokens from EmailEngine using the OAuth2 Token API
  4. Use tokens to call provider APIs directly

Setting Up Multi-Service Access

Step 1: Configure OAuth2 Scopes

When creating your OAuth2 application (Google Cloud Console or Azure AD), request all scopes you need.

Google Example

In Google Cloud Console, add all required scopes:

ScopePurpose
https://mail.google.com/Email access
https://www.googleapis.com/auth/calendarCalendar access
https://www.googleapis.com/auth/postmaster.readonlyPostmaster tools
https://www.googleapis.com/auth/drive.readonlyGoogle Drive (read-only)

Microsoft Example

In Azure AD, add all required permissions:

PermissionPurpose
Mail.ReadWriteEmail access
Mail.SendSending emails
Calendars.ReadWriteCalendar access
Files.ReadOneDrive access
offline_accessToken refresh capability
Microsoft Scope Compatibility

Additional OAuth2 scopes with Microsoft accounts are only supported when using the MS Graph API backend (Mail.* scopes). If you configure EmailEngine to use IMAP/SMTP (IMAP.AccessAsUser.All, SMTP.Send scopes), those access tokens are valid only for IMAP/SMTP and cannot be used with other Microsoft Graph APIs like Calendars or Files.

Step 2: Configure Additional Scopes in EmailEngine

When setting up the OAuth2 application in EmailEngine, add extra scopes to the Additional scopes field.

Google Example:

Navigate to ConfigurationOAuth2 → Edit your Gmail app.

Additional scopes field:

https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/postmaster.readonly

Microsoft Example:

Additional Microsoft Graph scopes are automatically included if you add them as delegated permissions in Azure AD. Just ensure they're configured in the Azure app.

Step 3: Enable OAuth2 Token API Endpoint

For security, the OAuth2 token API endpoint is disabled by default.

To enable via Web UI:

  1. Navigate to Configuration > General Settings
  2. Check Allow OAuth2 Token Access via API
  3. Click Save

To enable via environment variable:

Set EENGINE_ENABLE_OAUTH_TOKENS_API=true when starting EmailEngine.

Security Consideration

The OAuth2 token endpoint returns access tokens that can access user data. Only enable this if you need it, and ensure your EmailEngine API is properly secured with strong access tokens and appropriate access controls.

This setting cannot be changed via the API - it must be configured through the web interface or environment variable.

Step 4: Enable Required APIs

Make sure the APIs you want to use are enabled in the provider console.

Google Cloud Console:

Navigate to APIs & ServicesEnabled APIs and services.

Search for and enable required APIs (e.g., "Google Calendar API", "Gmail Postmaster API").

Azure AD:

Permissions added in Azure AD are automatically linked to their respective APIs.

Step 5: Add Accounts

Add accounts via hosted authentication or API. Users will be asked to grant all configured permissions during consent.

Add Accounts After Scope Configuration

If you add accounts before configuring all scopes, those accounts will be missing the required permissions. You'll need to have users re-authenticate to grant the new permissions.

Retrieving OAuth2 Tokens

Get Current Access Token

Use the OAuth2 Token API endpoint to retrieve a currently valid access token:

curl https://your-ee.com/v1/account/example/oauth-token \
-H "Authorization: Bearer YOUR_EMAILENGINE_TOKEN"

Response:

{
"account": "example",
"user": "user@example.com",
"accessToken": "ya29.a0AVA9y1sXQ....CP1A",
"provider": "gmail",
"registeredScopes": ["https://www.googleapis.com/auth/postmaster.readonly", "https://mail.google.com/"],
"expires": "2022-07-08T14:25:27.780Z"
}

Response Fields:

  • account - Account ID in EmailEngine
  • user - Email address of the account
  • accessToken - Currently valid OAuth2 access token
  • provider - OAuth2 provider type (gmail, outlook, gmailService, mailRu)
  • registeredScopes - List of scopes this token has access to
  • expires - When the access token expires (ISO 8601)
Token Validity

EmailEngine ensures the returned access token is valid and not expired. If the token is about to expire, EmailEngine automatically refreshes it before returning.

Token Lifetime

Google (Gmail API)

Access tokens:

  • Expire after 1 hour
  • EmailEngine refreshes them automatically using the refresh token

Refresh tokens:

  • Long-lived but can be invalidated under certain conditions
  • EmailEngine keeps them active by regular use

Conditions that invalidate Google refresh tokens:

ConditionExplanation
User revokes your appImmediate invalidation when user removes permissions via Google account settings
Not used for 6 monthsAuto-expired due to inactivity
Gmail password changedToken invalidated when Gmail scopes are present
Too many refresh tokens issuedGoogle enforces limits (~50 per user/client); oldest tokens invalidated first when limit exceeded
Consent was time-boundedIf user granted time-based access, it expires accordingly
OAuth consent screen in "Testing"For external apps in Testing mode, refresh tokens expire after 7 days. Move to Production to avoid this
Testing Mode Expiration

If your Google OAuth app is in "Testing" status, refresh tokens expire after 7 days. Publish your app to "In production" status to get long-lived refresh tokens.

Microsoft (Graph API / Outlook)

Access tokens:

  • Expire after 1 hour
  • EmailEngine refreshes them automatically using the refresh token

Refresh tokens:

  • Rolling lifetime up to 1 year
  • EmailEngine keeps them active by regular use

Conditions that invalidate Microsoft refresh tokens:

ConditionExplanation
User revokes consentUser removes app permissions via https://myapps.microsoft.com
Admin revokes or disables the appAdmin can revoke the service principal in Azure AD Enterprise Applications
Password change / account disabledChanging password or disabling account invalidates existing refresh tokens
Conditional access or MFA policy changeNew tenant policies (MFA, location requirements) invalidate old refresh tokens
Refresh token inactive for 90 daysIf not used to get new access tokens for 90 days, it expires
Maximum rolling lifetime (~1 year)Hard limit around 12 months even if used regularly (may vary by tenant config)
Application permission changesChanging requested scopes or app registration requires re-consent, invalidating old tokens
User signs out of all sessions"Sign out everywhere" action kills all refresh tokens
EmailEngine Keeps Tokens Active

EmailEngine automatically uses refresh tokens to obtain new access tokens, which resets the 90-day inactivity timer for Microsoft and the 6-month timer for Google. As long as accounts remain connected in EmailEngine, tokens stay active.

Microsoft Client Secret Expiration

Microsoft Graph API OAuth2 client secrets expire and must be renewed regularly. Secret expiration times are configured in Azure AD and can range from 90 days to 2 years maximum. When a client secret expires, EmailEngine can no longer refresh access tokens, causing all accounts using that OAuth2 app to fail immediately.

To prevent service disruption:

  1. Monitor client secret expiration in Azure AD: Certificates & secrets section
  2. Generate a new client secret before the current one expires
  3. Update EmailEngine configuration with the new client secret
  4. Azure AD allows multiple active secrets simultaneously, so you can add the new secret before removing the old one

If the secret expires:

  • All accounts bound to that OAuth2 app will fail authentication
  • Users will need to re-authenticate after you update the client secret
  • No data is lost, but accounts become inaccessible until the secret is updated

Token Lifetime Summary

ProviderAccess TokenRefresh Token (Active)Refresh Token (Inactive)
Google1 hourLong-lived (up to token limit)Expires after 6 months
Microsoft1 hourUp to 1 year (rolling)Expires after 90 days

Using Tokens with Provider APIs

All examples below use the OAuth2 Token API to retrieve access tokens.

Google API Example

Retrieve token from EmailEngine using the OAuth2 Token API:

curl https://your-ee.com/v1/account/example/oauth-token \
-H "Authorization: Bearer YOUR_EMAILENGINE_TOKEN"

Use the access token with Google APIs:

curl https://gmailpostmastertools.googleapis.com/v1/domains \
-H "Authorization: Bearer ya29.a0AVA9y1sXQ....CP1A"

Response:

{
"domains": [
{
"name": "domains/example.com",
"createTime": "2020-01-15T12:30:00Z",
"permission": "OWNER"
}
]
}

Google Calendar Example

# Get token
TOKEN=$(curl -s https://your-ee.com/v1/account/example/oauth-token \
-H "Authorization: Bearer YOUR_EMAILENGINE_TOKEN" \
| jq -r '.accessToken')

# List calendars
curl https://www.googleapis.com/calendar/v3/users/me/calendarList \
-H "Authorization: Bearer $TOKEN"

Microsoft Graph Example

# Get token
curl https://your-ee.com/v1/account/example/oauth-token \
-H "Authorization: Bearer YOUR_EMAILENGINE_TOKEN"

# Use with Microsoft Graph
curl https://graph.microsoft.com/v1.0/me/calendars \
-H "Authorization: Bearer EwBIA8l6..."

Example: Creating a Calendar Event

Using EmailEngine's OAuth2 tokens to create a Google Calendar event:

// Get current access token from EmailEngine
const tokenResponse = await fetch("https://your-ee.com/v1/account/user123/oauth-token", {
headers: {
Authorization: "Bearer YOUR_EMAILENGINE_TOKEN",
},
});

const { accessToken } = await tokenResponse.json();

// Create calendar event
const eventResponse = await fetch("https://www.googleapis.com/calendar/v3/calendars/primary/events", {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
summary: "Team Meeting",
start: {
dateTime: "2024-01-15T10:00:00+02:00",
timeZone: "Europe/Tallinn",
},
end: {
dateTime: "2024-01-15T11:00:00+02:00",
timeZone: "Europe/Tallinn",
},
attendees: [{ email: "colleague@example.com" }],
}),
});

const event = await eventResponse.json();
console.log("Event created:", event.htmlLink);

Token Refresh

EmailEngine handles token refresh automatically:

When EmailEngine Refreshes Tokens:

  • When an API operation encounters an expired access token
  • During account reconnection
  • When you request a token via the API endpoint (if expired)
  • As part of regular daily operations (keeping refresh tokens active)

What EmailEngine Does:

  1. Detects expired access token during an API request
  2. Uses the refresh token to obtain a new access token
  3. Updates stored credentials in Redis
  4. Retries the original operation with the new token

Your Responsibility:

  • Nothing! EmailEngine handles everything automatically
  • Just retrieve tokens when you need them via the API endpoint
  • They'll always be valid and up-to-date
Caching Tokens

While you can cache tokens in your application for a short time (e.g., 5-10 minutes), it's usually simpler to just request them from EmailEngine on-demand. EmailEngine's token retrieval is fast and guarantees validity.