Skip to content

OAuth2 PKCE Flow Extension for MCP Clients #7432

@cstns

Description

@cstns

Summary

Extend the existing OAuth2 PKCE flow in forge/routes/auth/oauth.js to handle MCP agent clients. This adds an mcp-agent client path alongside the existing ff-plugin path, with localhost redirect URI validation, MCP-specific scope handling, and token issuance that produces scoped PATs (from #7411).

Prerequisites

Requirements

MCP client registration (hardcoded)

  • Add mcp-agent as a recognized client_id in the OAuth flow, following the ff-plugin pattern
  • No database record, no AuthClient model changes

/account/authorize extension

  • When client_id=mcp-agent:
    • Validate redirect_uri is a loopback address: http://localhost or http://127.0.0.1, any port, any path (per RFC 8252 Section 7.3)
    • Accept an MCP-specific scope value (e.g. mcp-agent)
    • Redirect to an MCP consent page route (frontend implementation in a separate task). The route pattern should be distinct from the existing /account/request/:requestId and /account/request/:requestId/editor paths.

/account/complete/:code extension

  • When the request originates from an mcp-agent client:
    • Skip the project/device ownership checks (MCP is user-scoped, not resource-scoped)
    • Admin user rejection is still under discussion in Add PAT (Personal Acces Tokens) scopes #7411. The implementation should account for this being toggled on or off depending on the outcome of that decision.
    • Generate the authorization code and redirect to the client's redirect_uri as normal

/account/token extension

  • When client_id=mcp-agent and grant_type=authorization_code:
    • Validate PKCE code_verifier as normal
    • Issue a scoped PAT (from Add PAT (Personal Acces Tokens) scopes #7411) tied to the user, with the scope tier that was approved during consent
    • Return access_token, expires_in, refresh_token
  • When client_id=mcp-agent and grant_type=refresh_token:
    • Refresh the token following the existing refresh pattern

Tests

  • Full OAuth flow: authorize -> consent -> complete -> token exchange returns a valid scoped PAT
  • Redirect URI validation: localhost and 127.0.0.1 on various ports are accepted, non-loopback URIs are rejected
  • Invalid scope is rejected at the authorize step
  • PKCE verification works correctly for MCP client
  • Refresh token flow works for MCP-issued tokens
  • Existing ff-plugin and dynamic client flows are unaffected

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions