Skip to content
Scalekit Docs
Talk to an EngineerDashboard

Bring your own auth into your MCP server

Federated authentication system with Scalekit's OAuth 2.1 authorization layer for MCP servers

If you already have an authentication system in place, you can use Scalekit as a drop-in OAuth 2.1 authorization layer for your MCP servers. This federated approach allows you to maintain your existing auth infrastructure while adding standards-compliant OAuth 2.1 authorization for MCP clients.

Why use federated authentication?

  • Preserve existing auth: Keep your current authentication system and user management
  • Standards compliance: Add OAuth 2.1 authorization without rebuilding your auth layer
  • Seamless integration: Users authenticate with your familiar login experience
  • Centralized control: Maintain full control over user authentication and policies

When an MCP client initiates authentication, Scalekit acts as a bridge between the MCP client and your existing authentication system. The flow involves redirecting users to your login endpoint, validating their identity, and passing user information back to Scalekit to complete the OAuth 2.1 flow.

MCP ClientScalekitYour App GET /oauth/authorize 302 to /login?login_request_id=<reqid>&state=<state> Auth user with existing auth system POST /auth-requests/<login_request_id>/user 200 OK 302 to /partner:callback?state=<state> Consent, code, token exchange, tokens
  1. When the MCP client starts the authentication flow by calling /oauth/authorize on Scalekit, Scalekit redirects the user to your configured login endpoint with two critical parameters:

    • login_request_id string : Unique identifier for this login request
    • state string : OAuth state parameter to maintain security across requests

    Example redirect URL:

    https://<SCALEKIT_ENVIRONMENT_URL>/login?login_request_id=<reqid>&state=<state>

    The login request and its state stay valid for approximately 10 minutes. Complete authentication and send the callback to Scalekit within that window. If the request expires, Scalekit shows an invalid_state error page and the connection must be restarted from the MCP client.

  2. When the user lands on your login page, process authentication using your existing logic?whether that’s username/password, SSO, biometric authentication, or any other method your system supports.

    After successful authentication, make a secure backend-to-backend POST request to Scalekit with the authenticated user’s information.

    Send user details to Scalekit
    curl --location '<SCALEKIT_ENVIRONMENT_URL>/api/v1/connections/<connection_id>/auth-requests/<login_request_id>/user' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <access_token>' \
    --data-raw '{
    "sub": "1234567890",
    "email": "alice@example.com",
    "given_name": "Alice",
    "family_name": "Doe",
    "email_verified": true,
    "phone_number": "+1234567890",
    "phone_number_verified": false,
    "name": "Alice Doe",
    "preferred_username": "alice.d",
    "picture": "https://example.com/avatar.jpg",
    "gender": "female",
    "locale": "en-US"
    }'
    User attribute descriptions

    Required attributes:

    • sub string ? Unique identifier for the user in your system (subject)
    • email string ? User’s email address

    Optional attributes:

    • given_name string ? User’s first name
    • family_name string ? User’s last name
    • email_verified boolean ? Whether email has been verified
    • phone_number string ? User’s phone number in E.164 format
    • phone_number_verified boolean ? Whether phone has been verified
    • name string ? User’s full name
    • preferred_username string ? Preferred username
    • picture string ? URL to user’s profile picture
    • gender string ? User’s gender
    • locale string ? User’s locale preference (e.g., “en-US”)
  3. After receiving a successful response from Scalekit confirming the user details were accepted, redirect the user back to Scalekit’s callback endpoint with the state parameter.

    Callback URL format:

    <SCALEKIT_ENVIRONMENT_URL>/sso/v1/connections/<connection_id>/partner:callback?state=<state_value>

    The state_value must match the state parameter you received in step 1. This ensures the authentication flow’s integrity and prevents CSRF attacks.

  4. After processing the callback from your authentication system, Scalekit automatically handles the remaining OAuth 2.1 flow steps:

    • Displays the consent screen to the user (if required)
    • Generates the authorization code
    • Handles token exchange requests from the MCP client
    • Issues access tokens with appropriate scopes

    The MCP client receives valid OAuth 2.1 tokens and can now access your MCP server with the authenticated user’s identity.

Your MCP server now supports federated authentication with your existing auth system

invalid_state error page after login

Scalekit returns error=invalid_state when the login request has expired or the returned state does not match the value from step 1. The login request stays valid for approximately 10 minutes.

Treat the two causes separately:

  • Expired request: First-time signup often takes longer than 10 minutes. Restart the connection from the MCP client. The default error page cannot be replaced with a custom page.
  • Mismatched state: Confirm your application stores the state value from step 1 and returns it unchanged. Do not drop, overwrite, or rewrite it. Keep state validation enabled. Restarting the MCP connection does not fix a mismatch.
The handoff request times out with a gateway timeout error

Create the Scalekit client once at application startup and reuse that single instance across requests. Constructing a new client on every request re-runs the full bootstrap, which opens a fresh connection and fetches a new access token before the request can proceed. That extra work adds latency and can exceed the request deadline, which surfaces as a deadline_exceeded gateway timeout on the user-details call. A shared client caches its token and refreshes it internally.