# Social media studio auth.md

This guide is for AI agents, MCP clients, and automation tools registering a client or provisioning credentials to act for a Social media studio workspace. The API and OAuth issuer are `https://api.so-me.studio`. User sign-in and workspace management are at `https://app.so-me.studio`.

Social media studio supports **user-approved OAuth client registration** for MCP and **user-approved CLI device provisioning** for REST API keys. A human account and workspace authorization are required before an agent can access workspace data or publish content.

## 1. Discover authentication

Fetch [OAuth Protected Resource Metadata](https://api.so-me.studio/.well-known/oauth-protected-resource). The same document is discoverable from [the service root](https://so-me.studio/.well-known/oauth-protected-resource).

The default protected resource is `https://api.so-me.studio/mcp`. For a narrower MCP surface, fetch its own metadata:

- [Posting MCP metadata](https://api.so-me.studio/.well-known/oauth-protected-resource/mcp/posting)
- [Directory MCP metadata](https://api.so-me.studio/.well-known/oauth-protected-resource/mcp/directory)

Read `resource`, `authorization_servers`, `scopes_supported`, and `bearer_methods_supported`. Follow the advertised issuer to its [OAuth Authorization Server metadata](https://api.so-me.studio/.well-known/oauth-authorization-server), and verify that `issuer` matches the authorization server URL. If a protected request returns a `WWW-Authenticate` header with `resource_metadata`, use that document for the requested resource.

The `agent_auth` extension describes the existing `user_authorization` method: `skill` points to this guide, `register_uri` registers an OAuth client, `authorization_uri` starts human consent, and `token_uri` exchanges or refreshes credentials. Its nested method block lists PKCE S256, authorization-code and refresh grants, public-client authentication (`none`), and access/refresh token credential types. This is the service's existing OAuth workflow; ID-JAG assertions, verified-email assertions, anonymous accounts, and claim-later registration are not supported or advertised.

## 2. Register an MCP client

Use an existing registered client when available. Otherwise, register a public client with an allowed callback. The following example uses a local callback listener controlled by your client:

```http
POST /oauth/register HTTP/1.1
Host: api.so-me.studio
Content-Type: application/json

{
  "client_name": "My Social media studio agent",
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

Save the returned `client_id` and registered `redirect_uris`. Hosted callback URLs must be allowed by the service; an arbitrary HTTPS callback may be rejected. Client registration creates a client identifier, not a user account or an authorized workspace credential.

## 3. Obtain user approval and exchange the code

Generate a fresh, cryptographically random PKCE verifier and `state`. Compute `code_challenge` as the unpadded base64url SHA-256 hash of the verifier. Open the discovered authorization endpoint in the user's browser with these query parameters:

```text
response_type=code
client_id=<registered client_id>
redirect_uri=http://127.0.0.1:8765/callback
code_challenge=<S256 challenge>
code_challenge_method=S256
state=<random state>
scope=mcp
resource=https://api.so-me.studio/mcp
```

URL-encode all values. The user signs in and approves access to their workspace on the service's consent page. Users who need an account can [sign up](https://app.so-me.studio/signup) and complete account setup there. Handle cancellation without exchanging a code. At the callback, validate `state` and the returned `iss` against the discovered issuer.

Exchange the authorization code once, using the same callback, client, verifier, and exact resource:

```http
POST /oauth/token HTTP/1.1
Host: api.so-me.studio
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=<client_id>&code=<code>&redirect_uri=<encoded_callback>&code_verifier=<verifier>&resource=<encoded_resource>
```

The response contains `access_token`, `token_type: "Bearer"`, `expires_in: 3600`, `refresh_token`, and `scope: "mcp"`. These tokens authorize the approved workspace and resource. A token issued for `/mcp/posting` cannot be reused for `/mcp` or `/mcp/directory`.

## 4. Use and refresh MCP credentials

Send the access token in the HTTP header on requests to the chosen MCP resource:

```http
Authorization: Bearer <access_token>
```

The `mcp` scope is the supported OAuth scope; tool availability also depends on the selected MCP surface, workspace permissions, plan, and quotas. Treat tokens as secrets and keep them out of URLs and logs.

Refresh through the same token endpoint with form-encoded `grant_type=refresh_token`, `client_id`, `refresh_token`, and the same `resource`. Refresh tokens rotate: replace both stored tokens with the returned pair. Refresh tokens expire after 30 days. If credentials expire, are rejected, or the user disconnects the client, restart the user-approved authorization flow.

## 5. Provision a REST API key through the CLI flow

For the REST API at `https://api.so-me.studio/v1`, use an owner-created workspace API key. An owner can create one in the application's API settings, or use the CLI's device provisioning workflow. This workflow uses its own JSON endpoints; it is not a `device_code` grant at `/oauth/token`.

Start provisioning only when the user wants to connect the client:

```http
POST /auth/device/code HTTP/1.1
Host: api.so-me.studio
Content-Type: application/json

{}
```

The response supplies `device_code`, `user_code`, `verification_uri`, `expires_in` (600 seconds), and `interval` (5 seconds). Show the returned verification URL and user code to the user. They sign in and approve in the browser; the service UI submits the authenticated approval to `/auth/device/authorize`.

Poll with the device code at the returned interval until approval or expiry:

```http
POST /auth/device/token HTTP/1.1
Host: api.so-me.studio
Content-Type: application/json

{"device_code":"<device_code>"}
```

While waiting, `status` is `authorization_pending`. On success it is `authorized`, with account details and, when provisioning succeeds, an `api_key`. An authorized result without an `api_key` is not a usable REST credential; ask the workspace owner to resolve access eligibility or create a key in API settings. Device provisioning does not create anonymous accounts or bypass workspace permissions.

Use the key on REST requests:

```http
GET /v1/settings/profile HTTP/1.1
Host: api.so-me.studio
X-API-Key: <api_key>
```

API keys are workspace credentials with no per-key scope selection. They are distinct from the MCP OAuth access and refresh tokens.

## 6. Disconnect and recover

Users can disconnect an OAuth client through the application's AI app connections settings, invalidating its existing access and refresh tokens. API keys can be revoked in API settings. This service does not advertise a standard OAuth token-revocation endpoint or ID-JAG revocation events.

For an invalid callback or client, correct the registration before retrying. For an expired authorization code or device code, restart that flow. For `401`, verify the credential and resource, then reconnect if needed. For `403`, check workspace permissions and access eligibility. Respect rate limits and retry guidance on `429`.

## Passive discovery

Scanners should read this guide and the public OAuth metadata with GET or HEAD. Do not probe registration, device-code, token, consent, or claim endpoints during a passive scan: those operations can create client records or issue credentials.

Further documentation: [MCP setup](https://docs.so-me.studio/mcp/overview), [API authentication](https://docs.so-me.studio/authentication), and [CLI authentication](https://docs.so-me.studio/cli/auth).
