# Tabfleet auth.md

## Register an agent with an approval link

Use this flow when your agent can make HTTPS requests but has no OAuth browser
callback. It implements the Auth.md `service_auth` identity type. Ask the user
for the Google email they use with Tabfleet. The user must personally sign in,
enter the code you show them, and approve workspace access. Never complete that
approval on the user's behalf. No browser access is issued before approval.

### 1. Discover

- Protected resource metadata: https://tabfleet.com/.well-known/oauth-protected-resource
- Authorization server metadata: https://api.tabfleet.com/.well-known/oauth-authorization-server
- Resource identifier: `https://tabfleet.com/`

Read `agent_auth.identity_endpoint` and `token_endpoint` from the authorization
server metadata. Use `service_auth` for agent registration. For older Auth.md
clients, `register_uri` points to the same endpoint and the request
`{"type":"identity_assertion","assertion_type":"verified_email","assertion":"USER_GOOGLE_EMAIL"}`
starts the same Google sign-in and code approval flow. Its `registration_type`
is `email-verification`; polling and renewal are identical. This compatibility
format does not treat an agent-supplied email as verified: the matching user must
still sign in and approve. Unauthenticated access and external provider assertions
are not supported.

### 2. Start registration

POST https://api.tabfleet.com/agent/identity with `Content-Type: application/json`:

```json
{
  "type": "service_auth",
  "login_hint": "USER_GOOGLE_EMAIL",
  "client_name": "Your agent name",
  "scope": "browser:read browser:control",
  "resource": "https://tabfleet.com/"
}
```

Request `browser:read` alone if control is unnecessary. A successful response
returns `registration_id`, `claim_token`, `claim_token_expires`, and a `claim`
object containing `verification_uri`, `user_code`, `expires_in`, and `interval`.
Keep `claim_token` secret. Show the user the verification link and six-digit code
separately. The link does not contain the code. Requests expire after 10 minutes.
Registration does not require dynamic OAuth client registration or a callback URL.
Before the request expires, you may replace its approval link and code by POSTing
`{"claim_token":"CLAIM_TOKEN","email":"USER_GOOGLE_EMAIL"}` as JSON to
https://api.tabfleet.com/agent/identity/claim (`agent_auth.claim_endpoint`, also
`claim_uri` for older clients). Use the returned `claim_attempt` in place of the
original `claim`. Previous links, codes, and approval forms become invalid.
The original ten-minute deadline and incorrect-code limit do not reset.

### 3. Wait for user approval

The user opens the link, signs in with the matching Google email, enters the
code, and selects workspace and permissions. They can reduce access to view-only.

Poll https://api.tabfleet.com/oauth/token with
`Content-Type: application/x-www-form-urlencoded`:

```text
grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=CLAIM_TOKEN&resource=https%3A%2F%2Ftabfleet.com%2F
```

Use a form encoder. Wait at least `claim.interval` seconds between polls
(initially 5). On `authorization_pending`, keep waiting. On `slow_down`, increase
the interval by at least 5 seconds and honor the returned `interval`.
Stop on `access_denied`. On `expired_token`, ask the user before starting again.
Registration is limited to 10 attempts per IP per hour and 500 per day globally.

After approval, the response includes `access_token`, `token_type: Bearer`,
`expires_in`, `scope`, `identity_assertion`, and `assertion_expires`. Respect the
returned scope. Store both credentials in the agent's secret storage.

### 4. Use and renew access

Send `Authorization: Bearer ACCESS_TOKEN` to https://tabfleet.com/ using the
MCP Streamable HTTP POST transport. Access tokens last at most 10 minutes.

To renew, POST this form to the same token endpoint:

```text
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=IDENTITY_ASSERTION&resource=https%3A%2F%2Ftabfleet.com%2F
```

The service-issued assertion can be re-exchanged until `assertion_expires`, at
most 30 days after approval. This flow does not issue refresh tokens. Renewal
cannot extend the connection lifetime or increase permissions. Restart approval
when it expires or when the user wants different permissions.

### 5. Revoke or disconnect

To revoke one access token, POST a form to
https://api.tabfleet.com/oauth/token with `token=ACCESS_TOKEN` and
`token_type_hint=access_token` (no `grant_type`). Unknown tokens also return 200.
The identity assertion remains usable after revoking an individual access token.

To disconnect the registration and stop all renewal, the owner revokes the
connection in **Connected apps** at https://app.tabfleet.com. On `invalid_grant`
or an MCP 401, stop using rejected credentials; do not repeatedly retry renewal.
Never log claim tokens, access tokens, or identity assertions.

## Connect an agent using OAuth

Tabfleet supports OAuth authorization code with S256 PKCE for its remote MCP server.
The user signs into Tabfleet with Google, chooses their workspace, reviews the
client identity and permissions, and explicitly approves access. Google tokens
are never passed through to the agent. Tabfleet issues its own opaque tokens.

- MCP resource: https://tabfleet.com/
- Protected resource metadata: https://tabfleet.com/.well-known/oauth-protected-resource
- Authorization server issuer: https://api.tabfleet.com
- Authorization server metadata: https://api.tabfleet.com/.well-known/oauth-authorization-server
- Authorization endpoint: https://api.tabfleet.com/oauth/authorize
- Token and token-revocation endpoint: https://api.tabfleet.com/oauth/token
- Optional dynamic client registration: https://api.tabfleet.com/oauth/register

Client ID Metadata Documents are supported for HTTPS client identifiers. Dynamic
registration is available for compatible clients; it registers software, not a
Tabfleet workspace, and grants no browser access by itself. Registration requires
a client name and supported redirect URIs. HTTPS, HTTP localhost/loopback-IP redirects, and the exact native callback
`cursor://anysphere.cursor-mcp/oauth/callback` are supported. Every authorization request requires S256 PKCE, even for confidential
clients. Implicit, password, anonymous agent registration, and client-credentials
flows are not supported.

## OAuth permissions and tokens

Request `browser:read` for inspection or `browser:read browser:control` for browser
automation. The user may reduce access to view-only during consent. View access
includes page snapshots, screenshots, usage, and view-only live links. Control
also permits launch, close, navigation, interaction, and embedding-policy changes.
`offline_access` is accepted; renewable connections last at most 30 days.

Access tokens expire after at most 10 minutes. Refresh tokens rotate on renewal;
clients must store the newly returned refresh token. The provider permits the
previous refresh token for retry compatibility. Reusing an authorization code
revokes its grant. Reconnect through consent to change permissions.

Send tokens only in `Authorization: Bearer ACCESS_TOKEN` over HTTPS to the MCP
resource. Tokens are audience-bound to https://tabfleet.com/ and cannot be
used with the REST API or account-management endpoints.

The owner can revoke an app in **Connected apps** at https://app.tabfleet.com.
New MCP operations fail immediately after dashboard revocation. Existing live
connections are checked periodically. Browser sessions continue until explicitly
closed or expired. Workspace allowance and concurrency limits still apply.

## API-key provisioning

API keys remain supported for REST, MCP clients without OAuth, and unattended
services. The owner signs into https://app.tabfleet.com, creates a workspace, and
creates a key in **API keys**. Store the key in the agent client's secret settings.
Use `Authorization: Bearer YOUR_TABFLEET_API_KEY`. REST: https://api.tabfleet.com.
API keys can be revoked independently from OAuth connections.

Never put keys or tokens in public source, browser JavaScript, URLs, logs, or
screenshots. Temporary signed viewer URLs are also credentials: share them only
with intended recipients.

- [MCP setup](https://tabfleet.com/docs/mcp)
- [Authentication](https://tabfleet.com/docs/authentication)
- [REST API](https://tabfleet.com/docs/api)

## Endpoint behavior

https://tabfleet.com/ serves the public homepage for HTML and Markdown GETs and
authenticated MCP for POSTs. Use the exact resource identifier `https://tabfleet.com/`
in authorization and token requests. Requests for JSON or event streams receive
MCP authentication challenges. Browser cookies do not authenticate MCP requests.

The earlier endpoint https://mcp.tabfleet.com/ remains available as a separate
resource. To use it, authorize and request tokens for `https://mcp.tabfleet.com/`.
Tokens issued for one endpoint cannot be used at the other. Its discovery
metadata remains at https://mcp.tabfleet.com/.well-known/oauth-protected-resource.
