# MCP OAuth (/docs/buyer-guide/oauth)



The Voidnet acts as an OAuth 2.0 authorization server, issuing JWT access tokens for production systems.

## Token types [#token-types]

### JWT access tokens [#jwt-access-tokens]

Access tokens are JSON Web Tokens (JWTs) signed with RS256. They are three base64url-encoded segments separated by dots:

```
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature
```

Each token contains:

* **`sub`** — Buyer UUID
* **`scope`** — Permission scope (e.g. `mcp:tools`)
* **`exp`** — Expiration time (default 1 hour)
* **`iat`** — Issued at time
* **`iss`** — Voidnet issuer URL
* **`aud`** — Voidnet issuer URL (fixed at mint time; no client-controlled audience input)
* **`kid`** — Key ID identifying the signing key in the JWKS

### API keys [#api-keys]

The Voidnet also accepts API keys (`vnb-sk-*`) as a simpler alternative. See the [Buyer Guide](https://docs.openvoidnet.com/docs/buyer-guide/mcp) for API key management.

## Grant types [#grant-types]

### client\_credentials [#client_credentials]

Exchange your API key for a short-lived JWT:

```bash
curl -X POST https://api.openvoidnet.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=vnb-sk-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6"
```

Successful response:

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "mcp:tools"
}
```

The returned `access_token` is a JWT usable in any `Authorization: Bearer` header.

**Notes:**

* No separate `client_secret` is needed — the API key itself is the secret
* An optional `scope` parameter may be provided (defaults to `mcp:tools`)
* The `aud` claim is always the Voidnet issuer URL — the token endpoint accepts no client-controlled audience input

## Using tokens [#using-tokens]

All requests to the Voidnet use the `Authorization: Bearer` header:

```bash
# API key
curl -X POST https://api.openvoidnet.com/v1-beta/mcp/acmecorp/weather-tools \
  -H "Authorization: Bearer vnb-sk-..." \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -H "Mcp-Name: tools/list" \
  -d '{"jsonrpc": "2.0", "id": "1", "method": "tools/list"}'

# JWT access token
TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -X POST https://api.openvoidnet.com/v1-beta/mcp/acmecorp/weather-tools \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -H "Mcp-Name: tools/list" \
  -d '{"jsonrpc": "2.0", "id": "1", "method": "tools/list"}'
```

The Voidnet auto-detects the credential type — three dot-separated segments means JWT, otherwise API key.

### Token expiration [#token-expiration]

Tokens have an `exp` claim. When a token expires, the Voidnet returns `api_key_expired` (401):

1. Detect the `401` response
2. Request a new token from `POST /oauth/token`
3. Retry the request with the new token

## Publisher authentication [#publisher-authentication]

When the Voidnet proxies a request to a publisher's server, it authenticates using the publisher's API key (`vnp-sk-*`):

```
Authorization: Bearer vnp-sk-27fc6268dc64a9ba2c4cb92489e9175cbf404e260beb268b976f1a56582eff3
```

Publisher keys are:

* Generated in the Console when publishing an app
* The Voidnet always sends `vnp-sk-*` regardless of how the buyer authenticated
* Sent to the publisher server on every proxied request

## Endpoints [#endpoints]

## OAuth endpoints [#oauth-endpoints]

The Voidnet acts as an OAuth 2.0 authorization server:

| Endpoint                                      | Description                               |
| --------------------------------------------- | ----------------------------------------- |
| `POST /oauth/token`                           | Issue access tokens (client\_credentials) |
| `GET /.well-known/oauth-authorization-server` | RFC 8414 AS metadata                      |
| `GET /.well-known/oauth-protected-resource`   | RFC 9728 resource metadata                |
| `GET /.well-known/jwks.json`                  | Voidnet's public signing keys             |

## Credential management [#credential-management]

**API keys** are managed through the Voidnet:

* **Generate** — Create a new key from the API Keys section
* **Revoke** — Immediately invalidate a compromised key
* **Rotate** — Generate a new key, update your configuration, revoke the old one

**OAuth access tokens** are obtained programmatically:

* **client\_credentials** — Exchange an API key for a JWT at `POST /oauth/token`
* Tokens expire after a configurable period (default 1 hour)

## Credential security best practices [#credential-security-best-practices]

* Store API keys and tokens in environment variables, not in code
* Use a secrets manager in production
* Rotate API keys periodically
* Revoke compromised keys immediately
* Never expose credentials in client-side code, logs, or version control
* Use short-lived JWT access tokens in production systems instead of raw API keys
