OAuth Connector API
Let learners and tenant admins grant the platform permission to act on their behalf via OAuth, powering authenticated MCP server connections.
Overview
Front-end clients use the OAuth connector APIs to let a learner (or tenant admin) grant our platform permission to act on their behalf. This guide documents the discovery endpoints, the authorization handshake, and the post-connection management APIs.
Key terms:
- OAuth Provider -- A top-level vendor such as Google or Dropbox.
- OAuth Service -- A concrete surface offered by a provider (e.g., Google Drive, Google Calendar). A
ConnectedServicereferences one service. - ConnectedService -- The persisted token bundle that represents a user's grant. These are always per user and per service.
API Summary
| Capability | Endpoint | Method | Notes |
|---|---|---|---|
| List available services | /api/accounts/orgs/{org}/oauth-services/ | GET | Returns all enabled services across all providers. |
| List scopes for a service | /api/accounts/orgs/{org}/oauth-services/{service_name}/scopes/ | GET | Service-specific breakdown of scopes. |
| Start OAuth flow | /api/accounts/connected-services/orgs/{org}/users/{user_id}/{provider}/{service}/ | GET | Returns the vendor authorization URL and primes the OAuth state cache. |
| Handle callback | /api/accounts/connected-services/callback/ | GET | Called by the browser after the vendor redirects back with a code. |
| List a user's connections | /api/accounts/connected-services/orgs/{org}/users/{user_id}/ | GET | Returns ConnectedService records for the current user. |
| Delete a connection | /api/accounts/connected-services/orgs/{org}/users/{user_id}/{id}/ | DELETE | Removes the connection. |
Authentication is the standard Authorization: Token ... scheme. Tenants must have credentials named auth_{provider} configured in the credential store before the flow can start.
Connection Lifecycle
Front-end Client Mentor API (Accounts) OAuth Provider
| | |
|-- GET /oauth-services/ ->| |
|<- 200 OK (services) ----| |
| | |
|-- GET /connected-services/.../provider/service/ ------->|
|<- 200 OK {"auth_url":..} | |
| | |
|-- Redirect user -------->| |
| |<-- Redirect back w/ code ----|
|-- GET /callback?code=... | |
| |-- Token exchange ----------->|
| |<-- Token payload ------------|
|<- 200 OK (Connected) ---| |
Step-by-Step Implementation
Discover services
GET /api/accounts/orgs/acme/oauth-services/ HTTP/1.1
Authorization: Token {{TOKEN}}
Sample response:
[
{
"id": 12,
"oauth_provider": "google",
"name": "drive",
"display_name": "Google Drive",
"description": "File access for Drive",
"scope": "https://www.googleapis.com/auth/drive",
"image": "https://cdn.example.com/oauth/google-drive.svg",
"created_at": "2025-11-01T12:32:55Z",
"updated_at": "2025-11-01T12:32:55Z"
}
]
Start the OAuth flow
When the learner clicks Connect, call the start endpoint:
GET /api/accounts/connected-services/orgs/acme/users/alice/google/drive/ HTTP/1.1
Authorization: Token {{TOKEN}}
Response:
{
"auth_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=..."
}
Open auth_url in a new window/tab. The user authenticates with the vendor and approves permissions.
Handle the callback
After approval, the vendor redirects the browser to the callback URL. Capture the query parameters and relay them:
GET /api/accounts/connected-services/callback/?code=4/0A...&state=acme:google:drive:alice:09e4... HTTP/1.1
Successful response:
{
"id": 77,
"provider": "google",
"service": "drive",
"expires_at": "2025-11-12T14:05:00Z",
"scope": "https://www.googleapis.com/auth/drive",
"scope_names": ["drive"],
"scopes": ["https://www.googleapis.com/auth/drive"],
"token_type": "bearer",
"service_info": {
"id": 12,
"name": "drive",
"display_name": "Google Drive",
"logo": "https://cdn.example.com/oauth/google-drive.svg"
}
}
At this point the connection is persisted. If the connection already existed, it is updated in place.
Listing and deleting connections
GET /api/accounts/connected-services/orgs/acme/users/alice/ HTTP/1.1
Authorization: Token {{TOKEN}}
To delete:
DELETE /api/accounts/connected-services/orgs/acme/users/alice/77/ HTTP/1.1
Authorization: Token {{TOKEN}}
Returns 204 No Content.
UI/UX Considerations
- State management -- The
statereturned by the start endpoint must be round-tripped without modification. Do not decode or alter it. - Window strategy -- Use
window.openor a redirect. If using a modal, capture the redirect in that context and forward the query params to the callback endpoint. - Error handling -- Handle HTTP 400 responses (most likely missing provider credential configuration). Display actionable guidance ("Admin must configure auth_google credentials").
- Credential refresh -- The API auto-refreshes tokens when needed. The front-end only needs to re-list connections to pick up new expiry times.
Troubleshooting
| Symptom | Likely Cause | Action |
|---|---|---|
/oauth-services/ returns empty array | Tenant has no enabled services or provider is disabled | Confirm OauthProvider.is_enabled and OauthService records. |
Start endpoint returns 400 "No credentials found" | auth_{provider} credential is missing | Ask tenant admin to configure credential via admin UI. |
Callback returns Invalid state | Start and callback requests happened in different browser contexts or state expired | Ensure the same browser session completes the round-trip within 60 minutes. |
Callback returns Could not exchange auth token | Provider rejected the code | Try restarting the flow; verify redirect URI matches provider settings. |