Skip to main content
Bedrock supports OAuth 2.1 authorization code flow with PKCE for third-party integrations like Microsoft 365 Copilot, ChatGPT, and Claude. OAuth lets external AI agents authenticate to the Bedrock API on behalf of an organization.

When to Use OAuth vs API Keys

API KeysOAuth 2.0
Use caseDirect API access, scripts, CI/CDThird-party integrations (Copilot, ChatGPT, Claude)
Who creates credentialsYou, in the Bedrock dashboardAutomated via dynamic registration or pre-configured
Token lifetimeLong-lived (with optional rotation)Short-lived access (1 hour) + refresh token
AuthenticationAuthorization: Bearer sk_...Authorization: Bearer oat_...

Discovery (MCP Auth Spec)

AI copilots discover Bedrock’s OAuth configuration automatically using well-known metadata endpoints.

Protected Resource Metadata

GET /.well-known/oauth-protected-resource
Returns:
{
  "resource": "https://api.bedrock.cv",
  "authorization_servers": ["https://api.bedrock.cv"],
  "scopes_supported": ["read", "write"],
  "bearer_methods_supported": ["header"]
}

Authorization Server Metadata

GET /.well-known/oauth-authorization-server
Returns:
{
  "issuer": "https://api.bedrock.cv",
  "authorization_endpoint": "https://app.bedrock.cv/oauth/authorize",
  "token_endpoint": "https://api.bedrock.cv/oauth/token",
  "registration_endpoint": "https://api.bedrock.cv/oauth/register",
  "revocation_endpoint": "https://api.bedrock.cv/oauth/revoke",
  "scopes_supported": ["read", "write"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["none"],
  "code_challenge_methods_supported": ["S256"]
}

WWW-Authenticate Header

Unauthenticated requests to protected endpoints return:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.bedrock.cv/.well-known/oauth-protected-resource"

Client Registration

Bedrock supports three methods for registering OAuth clients:

Static Clients

Pre-registered for known partners (e.g., Microsoft Copilot). These are seeded in the database with a fixed slug as the client_id.

Dynamic Client Registration (RFC 7591)

Clients like Claude self-register by POSTing to /oauth/register:
POST /oauth/register
Content-Type: application/json

{
  "client_name": "Claude",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
Response:
{
  "client_id": "550e8400-e29b-41d4-a716-446655440000",
  "client_name": "Claude",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

Client ID Metadata Documents (CMID)

Clients like ChatGPT use a URL as their client_id. When Bedrock encounters a URL-based client_id, it fetches the metadata document to validate the client and its redirect URIs.

Authorization Code Flow with PKCE

1. AI copilot discovers OAuth config via well-known endpoints
2. Copilot registers as a client (DCR or CMID)
3. Copilot redirects user to Bedrock consent screen
4. User logs in, selects organization, and authorizes
5. Consent screen signs an authorization code and redirects to copilot callback
6. Copilot exchanges code + PKCE verifier for access token
7. Copilot uses access token to call Bedrock API
8. When token expires, copilot uses refresh token to get a new one

Step 1: Authorization

The copilot redirects the user to the consent screen:
https://app.bedrock.cv/oauth/authorize
  ?response_type=code
  &client_id=550e8400-e29b-41d4-a716-446655440000
  &redirect_uri=https://claude.ai/api/mcp/auth_callback
  &scope=read
  &state=random_csrf_token
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
The user logs in (if needed), sees the client name and requested permissions, selects an organization, and clicks Authorize or Deny. On approval, the consent screen signs a PKCE-bound authorization code and redirects directly to the client’s callback:
302 redirect to redirect_uri?code=...&state=...

Step 2: Token Exchange

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

grant_type=authorization_code
&code=abc123
&redirect_uri=https://claude.ai/api/mcp/auth_callback
&client_id=550e8400-e29b-41d4-a716-446655440000
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Response:
{
  "access_token": "oat_a1b2c3...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "ort_d4e5f6...",
  "scope": "read"
}

Step 3: Use the Access Token

curl https://api.bedrock.cv/mcp \
  -H "Authorization: Bearer oat_a1b2c3..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"list_projects","arguments":{}},"id":1}'

Step 4: Refresh

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

grant_type=refresh_token
&refresh_token=ort_d4e5f6...
&client_id=550e8400-e29b-41d4-a716-446655440000
Returns a new access/refresh token pair. The old refresh token is revoked.

Step 5: Revoke

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

token=oat_a1b2c3...
Always returns 200 OK, even if the token was already revoked or not found (per RFC 7009).

Scopes

ScopePermissions
readRead projects, drawings, sheets, blocks, features, overlays, jobs, organizations
writeCreate/update projects, drawings, files, jobs

Platform Compatibility

ChatGPTClaude.ai / CoworkClaude CodeMicrosoft Copilot
RegistrationCMID preferred, DCR fallbackDCRDCR or pre-configuredPre-registered (static)
PKCERequired (S256)Required (S256)Required (S256)Optional

Security

  • All tokens are stored as SHA-256 hashes (never in plaintext)
  • Access tokens expire after 1 hour
  • Refresh tokens expire after 30 days
  • PKCE (S256) is required for all authorization requests
  • Authorization codes expire after 10 minutes
  • Tokens are scoped to a specific organization (selected during consent)