# OAuth with your own client

> For vendors that issue tokens through a consent rather than a key, Graft runs the flow against a client you register. The agent guides, the console takes the secret.

Source: https://docs.getgraft.ai/graft/connections/oauth-with-your-own-client

Gmail, Slack user tokens, Notion and most Google APIs do not hand out API keys: you sign in at the vendor and consent, and the vendor issues tokens to a **client** somebody registered. Graft runs that flow against a client you register yourself. Graft operates no OAuth client of its own for these vendors.

> **Note**
>
> On Graft Cloud, Gmail does not take this path. It connects with one click through Pipedream Connect, whose client is the one you sign in to, and the token stays with Pipedream. See [One click on Graft Cloud](https://docs.getgraft.ai/graft/connections/connecting-a-vendor.md#one-click-on-graft-cloud). This page is for a vendor Pipedream does not cover, and for self-hosted Graft without a Pipedream project of its own.

The agent is the guide. It reads the vendor's OAuth documentation, proposes the endpoints and scopes, and tells you what to create and where to paste the one value only Graft knows. The client secret and the tokens never pass through it; you enter the secret in the console and the consent runs in a popup there.

## What the agent proposes

The agent calls `request_connection` with the scheme `oauth_authorization_code` and, from the vendor's documentation, the **Authorize URL**, the **Token URL** and the **Scopes** the task needs, as narrow as the task allows. It leaves the client id out, because it cannot know it. The answer carries the handoff link and a `redirectUri`, and the agent relays both with three sentences: where to create the client, what to name it, and which redirect URI to paste.

## Registering the client

### Step 1: Create an OAuth client at the vendor

In the vendor's developer console, create an OAuth client of the **web application** kind. Name it with "Graft" in it, `Graft (my laptop agent)`, so you recognise it in the vendor's list a year from now.

### Step 2: Paste the redirect URI

The redirect URI is your Graft deployment's origin plus `/api/oauth/callback`. The form shows it with a **Copy** button, fetched from the server so it is the exact URI the callback answers on. Paste it into the client's authorized redirect URIs exactly; a character off and the vendor refuses the consent with `redirect_uri_mismatch`.

### Step 3: Enter the client on the form

Open the handoff link. The form is pre-filled with the agent's proposal and asks for two things the agent could not know: the **Client id**, as a required parameter, and the **Client secret**, as the one secret. The redirect URI is shown beside them.

### Step 4: Connect

**Connect** stores the client and opens the vendor's consent page in a popup. Complete the consent there. The form waits and says so; when the vendor sends the browser back, the tokens are stored encrypted, the card settles, and the agent's waiting call answers `connected`. If the browser blocks the popup, the form offers a link to open the consent page yourself. **Stop waiting** returns the form to Connect if you change your mind; the client id and secret are kept.

Once connected, the proxy injects the access token on every call and refreshes it when it expires. Your tools call `ctx.fetch` as for any other scheme and never see a token.

## Google

Google is the worked example the skill carries, and it has one wart.

- A Google Cloud project starts in **Testing mode**. Add your own Google account under **OAuth consent screen → Test users**, or the consent page refuses you.
- Create the client under **APIs & Services → Credentials → Create credentials → OAuth client ID**, type **Web application**, after enabling the API the scopes belong to (Gmail API for Gmail) under **Library**.
- Gmail's read scope is `https://www.googleapis.com/auth/gmail.readonly`; the host is `gmail.googleapis.com`; the endpoints are `https://accounts.google.com/o/oauth2/v2/auth` and `https://oauth2.googleapis.com/token`.

> **Warning**
>
> Whenever a host on the form is Google's, the form shows this notice: *A Google Cloud project in Testing mode issues refresh tokens that expire after seven days, so this connection will ask you to reconnect weekly; publishing the app removes that, but a published app that reads Gmail needs Google's verification and a CASA assessment.*

## When a call fails later

A vendor `401` on an OAuth connection usually means the refresh token died: the seven-day expiry above, or you revoked the app at the vendor. Graft has already tried to refresh once and passed the vendor's own `401` to the tool. The connection card then reads **needs re-consent** and offers **Reconnect**, which runs the consent again with the client secret still in place; nothing is typed, and no approval is touched.

The agent can start this for you with `request_credential`. For an OAuth connection the card asks you to reconnect, not to type anything, unless the connection was revoked in the console, in which case you enter the client secret first and the consent follows.

## The connection's states

The card under **Connections** shows where an OAuth connection stands: **awaiting client secret** before the secret is entered, **awaiting consent** once it is and the consent has not completed (with **Connect**), **needs re-consent** after a refused refresh (with **Reconnect**), and **connected**, with when you consented and when the token was last refreshed. Tokens are never shown.

## Try it

```text
Connect my Gmail so you can read subject lines. Walk me through registering the client.
```

```text
Which redirect URI do I paste into the Google Cloud client?
```

```text
The Gmail tool is returning 401 again. Get me reconnected.
```
