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

# Authentication

> Consile uses standard MCP authorization: RFC 9728 discovery followed by OAuth 2.1. Your token authenticates you to Consile, not to the underlying data source.

Consile follows **MCP's standard authorization**. An MCP-aware client does all of
this automatically; here is the flow if you implement it yourself.

## The flow at the protocol level

<Steps>
  <Step title="Call a connector endpoint without a token → 401">
    A call to e.g. `/gsc/mcp` without a valid token responds `401 Unauthorized`
    with a `WWW-Authenticate` header that points to the resource metadata document.
  </Step>

  <Step title="Fetch the protected-resource metadata (RFC 9728)">
    `GET /.well-known/oauth-protected-resource` returns (publicly) which
    **authorization server** belongs to this endpoint.
  </Step>

  <Step title="OAuth 2.1 against the authorization server">
    The client registers (dynamic client registration where supported), takes the
    user through login and consent with **PKCE**, and exchanges the result for an
    access token.
  </Step>

  <Step title="Call a connector endpoint with your token">
    Send `Authorization: Bearer <access_token>` on every call to the connector's
    own URL (e.g. `/gsc/mcp`). The token determines the account and connectors.
  </Step>
</Steps>

<Note>
  The access token's audience is Consile's authorization-server **project
  identifier** (from the dynamic-client-registration flow), not the MCP resource
  URL. Verify against that audience if you inspect the token yourself.
</Note>

## Two tokens: keep them separate

The most important thing to understand:

<CardGroup cols={2}>
  <Card title="Your token → Consile" icon="key">
    The access token your client holds authenticates you **to Consile's MCP
    server**. It is the only token your client ever sees.
  </Card>

  <Card title="Consile's token → the data source" icon="lock">
    Access to e.g. Google is held by **Consile** as a separate, encrypted token.
    It is never handed to your client (no token passthrough).
  </Card>
</CardGroup>

<Note>
  This means your MCP token can never be used to reach the underlying data source
  directly. It can only call Consile's tools on your own account.
</Note>

## Scopes & access

* **Connector capability:** some connectors (Google Search Console, Uniconta,
  Dinero) are read-only: your AI can read your data but never modify, create,
  or delete anything. Others (e-conomic, Shopify, HubSpot, LinkedIn Ads, Meta Ads)
  expose additional write tools behind guardrails; see
  [Handlinger & guardrails](/essentials/handlinger-og-guardrails).
* **Upstream scope:** for Google Search Console the upstream OAuth scope is
  `webmasters.readonly`. For Meta Ads the token covers the ad account scopes you
  approved at connect time. For LinkedIn Ads: `r_ads`, `rw_ads`, `r_ads_reporting`.
* **Subscription determines tools:** `tools/list` returns only the tools for the
  connectors your account is subscribed to. Activate a new connector and its tools
  appear with no extra setup.
* **Per-call check:** your access is verified on **every** `tools/call`.

<Note>
  Connecting the **upstream** account is a separate flow that varies by connector:
  OAuth login (Google Search Console, Meta Ads, LinkedIn Ads), an API-key form
  (Uniconta) or hosted app consent (e-conomic). See
  [Forbind din konto](/connect/forbind-din-konto).
</Note>

## Token renewal

Follow the expiry and refresh fields the authorization server returns at the token
exchange (standard OAuth). The **upstream** credential Consile holds is refreshed
silently server-side where applicable; your client never handles it. Three
connectors do not use a standard OAuth `refresh_token`:

* **e-conomic (grantToken):** the upstream grant token is static and never expires, so no refresh is needed.
* **Uniconta (apiKey):** credentials are an API key; they do not expire or refresh.
* **Meta Ads (OAuth):** Meta issues a long-lived user access token (valid \~60 days)
  with **no `refresh_token`**. Consile attempts an automatic renewal by re-exchanging
  the current token (`fb_exchange_token`) on the read path, but only within a narrow
  window just before expiry, so in practice you should expect to re-authorize via the
  connect flow in the portal roughly every 60 days.
