> ## Documentation Index
> Fetch the complete documentation index at: https://docs.horizon.prefect.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> How MCP clients authenticate to servers served through Horizon, and how users and automation authenticate to Horizon itself.

export const openAuthenticationPlans = "Developer and Enterprise";

Authentication in Horizon provides a shared identity layer for MCP servers
served through the gateway. The gateway verifies callers before requests reach
server code, so hosted servers can use the same OAuth-compatible MCP client
sign-in, API key validation, organization membership checks, and request
outcomes.

This moves authentication policy out of individual server implementations and
into the platform path. Security and platform teams can define how protected
server endpoints accept callers, then apply that behavior consistently across
servers. When a hosted server needs to own authentication itself, disabling
Horizon authentication lets Horizon forward requests without validating the
caller at the gateway.

Authentication in Horizon has two related paths:

| Path                      | Caller                                                        | Target                                                         | Main question                              |
| ------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------ |
| Connecting to MCP servers | An MCP client, agent, or automation calling a server endpoint | A hosted, remix, or external MCP server served through Horizon | Who is trying to use this MCP server?      |
| Signing in to Horizon     | A user, script, CI job, service account, or Terraform run     | The Horizon dashboard or REST API                              | Who is trying to manage Horizon resources? |

The same Horizon identity can appear in both paths, but the request paths
are different. Authenticating to a Horizon-served MCP endpoint lets a client
call tools, resources, and prompts exposed by that server. Signing in to the
Horizon dashboard lets a user manage servers, members, keys, and settings.

<Info>
  A Horizon API key can authenticate a REST API request or an MCP request. The
  target URL determines which path applies: platform management for REST API
  routes, server usage for MCP endpoint routes.
</Info>

Authorization is separate. After Horizon identifies the caller, authorization
decides what that caller can see, manage, or invoke. For role and access
resolution, see [Authorization](/platform/authorization).

<Note>
  Authentication is enabled by default for hosted MCP server endpoints.
  Disabling it for a hosted server is available on {openAuthenticationPlans}.
</Note>

## Connecting to MCP servers

Use this path when the caller is trying to use a server through its MCP
endpoint. This includes agents, MCP clients, scripts, and tools that send
requests to a Horizon deployment URL.

Hosted server traffic passes through the Horizon gateway. The gateway identifies
the deployment, reads the server's authentication mode, verifies the caller when
required, checks server access, and only then forwards the request to your MCP
server.

This layer protects the server endpoint. It is separate from the dashboard and
REST API sign-in path used to manage that server.

A hosted server's authentication settings expose one control: **Horizon
Authentication**, which is either enabled or disabled.

| Horizon Authentication | What callers must provide                                                                                    | When to use it                                                         |
| ---------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| Enabled                | A valid Horizon bearer credential, such as a user token from an MCP client sign-in flow or a Horizon API key | Default for shared and production servers                              |
| Disabled               | No Horizon bearer credential. Your server may still require its own credentials.                             | Public endpoints or servers that perform all authentication themselves |

<Info>
  When a server is protected by Horizon, the endpoint is scoped to the
  server's Horizon organization. A caller must authenticate as a user or service
  account in that organization before the request can reach your server.
  Authorization settings can then narrow access further. To share a protected
  server with another person, invite them to the server's organization and grant
  the appropriate access.
</Info>

When a server is protected by Horizon, callers must authenticate with a bearer
credential:

```http theme={null}
Authorization: Bearer <token>
```

Horizon accepts two categories of bearer credentials for protected MCP traffic:

<AccordionGroup>
  <Accordion title="MCP client sign-in tokens">
    MCP clients that support authenticated server connections can use the
    Horizon deployment URL and complete sign-in in the client. Horizon accepts
    the resulting bearer token as the signed-in user and checks that user
    against organization and server access.

    If your client does not support interactive sign-in, use a Horizon API key
    as the bearer token instead.
  </Accordion>

  <Accordion title="Horizon API keys">
    Non-interactive clients can send a Horizon API key as the bearer token.
    Horizon API keys start with `fmcp_`, are shown only when created, and can be
    revoked independently. For key management, see [API keys](/api-keys).
  </Accordion>
</AccordionGroup>

An identity provider token is not a substitute for either credential. When a
member signs in through SSO, WorkOS validates the identity provider flow and
Horizon issues the identity used at its gateway. A bearer token issued directly
by Entra ID, Okta, or another provider is not accepted by a Horizon-protected MCP
endpoint.

If your server must validate an externally issued token itself, use a hosted
server with Horizon Authentication disabled. Your server then owns token
validation and application authorization, and Horizon cannot apply identity-based
server or capability access to those requests.

If the credential is valid, the gateway forwards the request with the verified
caller identity available to downstream platform checks and request
observability. Missing, malformed, expired, revoked, or wrong-organization
credentials stop at the gateway.

<Info>
  The gateway runs before your server code. A rejected authentication request
  stops before server compute starts or your Python handler runs.
</Info>

## Changing a hosted server's authentication

Configure hosted server authentication from the server's authentication page.

<Steps>
  <Step title="Open authentication">
    Go to the server, then open <b>Access</b> and <b>Authentication</b>.
  </Step>

  <Step title="Enable or disable Horizon Authentication">
    Enabled means clients must prove identity to Horizon before the request
    reaches the server. Disabled means Horizon passes requests through without a
    Horizon authentication check.
  </Step>

  <Step title="Save and redeploy">
    Authentication changes apply on the next deployment. Existing live traffic
    continues using the setting attached to the currently deployed artifact until
    a new deployment applies the change.
  </Step>
</Steps>

<Warning>
  Disabling Horizon authentication removes Horizon's gateway authentication and
  server access checks for that hosted server. Do so only when the endpoint is
  intentionally public or your server implements its own authentication and
  authorization. Any credentials your server requires are handled by your server,
  not by Horizon gateway authentication.
</Warning>

If you want clients to authenticate with an OAuth provider or token system that
your server controls, implement that authentication in your server and disable
Horizon authentication. Horizon then does not validate the caller's credential
before forwarding the request, and your server is responsible for rejecting
unauthenticated or unauthorized requests.

Remix servers and external servers always keep Horizon authentication enabled.
It cannot be disabled for them.

## External authentication

External authentication adds a second credential after Horizon identifies the
caller. External servers use it when Horizon calls the remote MCP endpoint.
Hosted servers can use delegated authorization to exchange the identified user
for an upstream credential before hosted code runs.

The Horizon credential and downstream credential protect different boundaries.
A valid Horizon sign-in does not guarantee that the caller has authorized the
remote provider. A missing, expired, or revoked downstream credential can fail
after Horizon authentication and server access checks have succeeded.

Horizon supports per-user OAuth, per-user API keys, and organization-shared API
keys for the downstream boundary. To choose a mode, configure its credentials,
and understand hosted delegated exchange, see
[External authentication](/platform/external-authentication).

## Common MCP endpoint outcomes

<AccordionGroup>
  <Accordion title="The request succeeds">
    Horizon identified the deployment, accepted the caller's credential, found
    the caller in the expected organization, and authorization allowed the
    request to continue.
  </Accordion>

  <Accordion title="The request returns 401">
    The request omitted a bearer credential, used another `Authorization`
    scheme, sent an empty token, sent an expired user token, or used an API key
    that is invalid, inactive, or revoked.
  </Accordion>

  <Accordion title="The request returns 403">
    Horizon authenticated the caller, but authorization denied access to the
    organization, server, or requested capability. Check organization
    membership, server access, custom server roles, and tool-level access
    settings. For the role model, see
    [Authorization](/platform/authorization).
  </Accordion>

  <Accordion title="The request returns 404">
    The deployment URL maps to no live server, or Horizon intentionally conceals
    a server from an authenticated caller that lacks discovery access.
  </Accordion>

  <Accordion title="The request reaches the server and then fails">
    Authentication and gateway routing succeeded. Check your server logs,
    request logs, and your server's own application-level authentication or
    authorization logic.
  </Accordion>
</AccordionGroup>

## Signing in to Horizon

Use this path when the caller is managing Horizon itself: opening the dashboard,
calling the REST API, creating API keys, deploying servers, inviting members, or
changing access settings.

<CardGroup cols={3}>
  <Card title="Dashboard" icon="user">
    Human users sign in to Horizon, choose an organization, and manage servers,
    members, keys, builds, and settings according to their role.
  </Card>

  <Card title="REST API" icon="code">
    API clients authenticate with a bearer credential or an active browser
    session. API requests are checked against the authenticated user's or
    service account's access.
  </Card>

  <Card title="Automation" icon="terminal">
    Service accounts and user-owned API keys authenticate scripts, CI/CD, and
    other machine workflows.
  </Card>
</CardGroup>

## Actor identities

Every authenticated platform request resolves to an actor. An actor is the
Horizon identity that can own API keys, belong to an organization, and receive
access grants.

| Actor type      | Used for                                                    | Authentication methods                                   |
| --------------- | ----------------------------------------------------------- | -------------------------------------------------------- |
| User            | Humans using the dashboard, API, playground, or MCP clients | Horizon sign-in, user access tokens, user-owned API keys |
| Service account | Automation, CI/CD, Terraform, and other machine clients     | Service-account API keys                                 |

API keys can belong to users or service accounts. This means a machine workflow
can authenticate as a service account while participating in the same
organization and server access model as a human user.

## REST API authentication

Authenticated REST API routes accept the following credentials:

| Credential        | Header or source                 | Typical use                                                               |
| ----------------- | -------------------------------- | ------------------------------------------------------------------------- |
| API key           | `Authorization: Bearer fmcp_...` | Scripts, CI/CD, service accounts, Terraform                               |
| User access token | `Authorization: Bearer <token>`  | User-scoped API calls from clients that already completed Horizon sign-in |
| Browser session   | Horizon session cookie           | Dashboard-originated API requests                                         |

If both an `Authorization` header and a browser cookie are present, the bearer
credential takes precedence. Invalid or missing credentials return `401`.

For scripts, CI/CD, Terraform, and other direct API clients, use a bearer
credential. Browser sessions are intended for dashboard-originated API requests.

API keys inherit access from the user or service account that owns them. If the
owning actor loses organization or server access, requests made with that key
lose the same access. Revoked keys no longer authenticate.

All successful REST API authentication resolves to an actor identity. Horizon
uses that actor identity to check organization, server, and feature access.

## Operational guidance

For production servers, keep Horizon authentication enabled and use server
access controls to decide who can call the server. Prefer service accounts and
API keys for automation, and user sign-in for interactive MCP clients.

Rotate API keys by creating a new key, updating the client, and revoking the old
key after traffic has moved. Because API keys are shown only at creation time,
store them in your secret manager before closing the creation dialog.

Disable Horizon authentication only when you have a clear public-access
requirement or an independent authentication layer inside the server. When it is
disabled, Horizon request logs can still show gateway traffic, but Horizon no
longer identifies the caller before forwarding the request.

## Related docs

<CardGroup cols={2}>
  <Card title="Authorization" icon="shield" href="/platform/authorization">
    Learn how roles and access grants decide what authenticated actors can do.
  </Card>

  <Card title="Gateway" icon="route" href="/gateway">
    Learn how requests move through routing, authentication, access checks, and
    MCP session handling.
  </Card>

  <Card title="API keys" icon="key" href="/api-keys">
    Create, rotate, and revoke keys for users and automation.
  </Card>

  <Card title="External authentication" icon="arrows-rotate" href="/platform/external-authentication">
    Configure downstream OAuth and API-key credentials for external and hosted
    servers.
  </Card>
</CardGroup>
