Skip to content

MCP OAuth

The MCP server supports OAuth 2.0 authentication, allowing MCP clients to authenticate as AMSDAL users with full permission checks.

Overview

When OAuth is enabled, MCP clients must authenticate before accessing tools. The flow:

  1. Client discovers OAuth endpoints via /.well-known/oauth-protected-resource
  2. Client registers and receives a client_id
  3. User is redirected to AMSDAL's login page
  4. After login, client receives an authorization code
  5. Client exchanges code for access + refresh tokens
  6. Tokens are sent with each MCP request

All AMSDAL permission checks (class-level and object-level) are applied based on the authenticated user.

Configuration

Env Variable Default Description
OAUTH_ENABLED true Enable/disable OAuth for MCP
OAUTH_CLIENT_ID_EXPIRATION_DAYS 30 Client ID token expiration (days)
OAUTH_CODE_EXP_MINUTES 10 Authorization code expiration (minutes)
OAUTH_ACCESS_TOKEN_EXP_HOURS 24 Access token expiration (hours)
OAUTH_REFRESH_TOKEN_EXP_DAYS 90 Refresh token expiration (days)
OAUTH_LOGIN_PATH /auth/login Custom login page path
OAUTH_ISSUER http://127.0.0.1:8000 Token issuer identifier

OAuth Endpoints

The following endpoints are mounted automatically when the plugin is registered:

Endpoint Method Description
/.well-known/oauth-protected-resource GET Protected resource metadata
/.well-known/oauth-authorization-server GET Authorization server metadata
/register POST Client registration (returns client_id)
/oauth/authorize GET Authorization endpoint (redirects to login)
/oauth/token POST Token exchange (code → access/refresh tokens)
/auth/login GET/POST Login page for user authentication

PKCE Support

The OAuth flow uses PKCE (Proof Key for Code Exchange) with S256 challenge method for security. MCP clients that support OAuth (like Chatbox AI) handle PKCE automatically.

Token Flow

Client                     AMSDAL Server
  |                              |
  |-- POST /register ----------->|  (get client_id)
  |<---- client_id --------------|
  |                              |
  |-- GET /oauth/authorize ----->|  (with PKCE challenge)
  |<---- redirect to login ------|
  |                              |
  |  [User logs in]              |
  |                              |
  |<---- authorization code -----|
  |                              |
  |-- POST /oauth/token -------->|  (code + PKCE verifier)
  |<---- access + refresh token -|
  |                              |
  |-- MCP request + Bearer ----->|  (authenticated)
  |<---- response ---------------|

Auth Bridge

The OAuthAuthenticateBridgeListener translates OAuth bearer tokens into internal AMSDAL auth tokens. This ensures that:

  • The MCP request runs in the context of the authenticated user
  • All AMSDAL permission checks apply (class-level, object-level)
  • Audit trails show the actual user, not a service account

Token Refresh

When an access token expires, the client uses the refresh token to get a new pair:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=<token>&client_id=<id>

Refresh tokens are rotated on each use — a new refresh token is issued. Note that old refresh tokens remain valid until their natural JWT expiry.

Disabling OAuth

For development or trusted environments, you can disable OAuth:

export OAUTH_ENABLED=false

Without OAuth, the MCP server is accessible without authentication. Use this only in development.