WireSocket primarily uses OAuth 2 Machine-to-Machine (M2M) client credentials flow to authenticate applications. For interactive management (like the dashboard), the platform uses the Resource Owner Password flow through trusted applications.
Obtaining a Token
Call the token endpoint from your backend server only. Never expose your client_secret in browser or mobile code.
curl -X POST https://api.wiresocket.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=WireSocket.API offline_access"
Response:
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900
}
| Field | Value |
|---|
expires_in | 900 seconds (15 minutes) |
scope | WireSocket.API offline_access |
offline_access scope is required to receive a refresh_token. Without it
you cannot renew sessions without re-authenticating with your client_secret.
Required Scopes & Audience
The WireSocket Data Plane strictly enforces identity verification using the standard aud (Audience) and scope claims. Your JWT must meet these criteria or the connection will be rejected with a 401 Unauthorized error.
1. Audience Enforcement
The aud claim must be exactly WireSocket.API. This ensures the token was intended for the Data Plane and not for another service.
{
"aud": "WireSocket.API"
}
2. Scope Validation
The token must include WireSocket.API in either the scope or scp claim. This claim is typically a space-delimited string.
{
"scope": "WireSocket.API offline_access"
}
The Data Plane validates this by splitting the string and checking for the required value. If neither scope nor scp contains WireSocket.API, authentication fails.
3. Client Implementation
When your backend requests a token from the Dashboard using the client_credentials grant, you must request the WireSocket.API scope explicitly:
curl -X POST https://api.wiresocket.com/connect/token \
-d "grant_type=client_credentials" \
-d "scope=WireSocket.API" \
...
JWT Claims
The access token is a signed JWT. Your backend can decode it to inspect the claims — the dataplane reads these directly with no database lookup.
{
"iss": "https://api.wiresocket.com",
"sub": "prod_wiresocket_abc123",
"aud": "WireSocket.API",
"scope": "WireSocket.API offline_access",
"tenantid": "3f9a6c6e-2d9e-4c3e-a1f1-3b2c99e6b111",
"appId": "7b1c0d8c-2d01-4c7c-b3b1-111aaa222bbb",
"licenseRegionCode": "aws-us-east-1",
"dbCode": "shard-01-us-east-1",
"allowed_domain_1": "example.com",
"allowed_domain_2": "staging.example.com",
"allowed_domain_3": "localhost:3000",
"limits": {
"maxConnections": 100,
"maxDocuments": 500,
"maxUsersPerDoc": 50,
"opsPerMinute": 10000
},
"exp": 1740470000,
"iat": 1740466400,
"jti": "unique-token-id"
}
Claim Reference
| Claim | Description |
|---|
sub | Your client_id |
tenantid | Your tenant GUID — used for multi-tenant isolation |
appId | Your application GUID |
licenseRegionCode | The base region for your metadata (e.g., aws-us-east-1) |
dbCode | The specific database shard identifier (e.g., shard-01-us-east-1) |
allowed_domain_1/2/3 | Domains permitted to connect to the dataplane |
limits | Native JSON object containing your plan limits |
Plan Limits
The limits claim contains your plan’s resource caps:
| Limit | Description |
|---|
maxConnections | Total concurrent WebSocket connections allowed |
maxDocuments | Total concurrent documents allowed |
maxUsersPerDoc | Maximum users in a single document session |
opsPerMinute | Maximum CRDT operations per minute |
Token Renewal
Access tokens expire after 15 minutes. Use the refresh token to obtain a new access token without re-authenticating with your client_secret.
curl -X POST https://api.wiresocket.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=YOUR_REFRESH_TOKEN" \
-d "client_id=YOUR_CLIENT_ID"
Every refresh issues a new refresh token and invalidates the old one.
Store the latest refresh token after every renewal.
Refresh Token Expiry
Refresh tokens are valid for 7 days. If a refresh token expires, you must re-authenticate using your client_id and client_secret to start a new session.
Access token expires (15 min)
↓
Renew using refresh token
↓
New access token + new refresh token issued
↓
Repeat until refresh token expires (7 days)
↓
Re-authenticate with client_id + client_secret
Passing the Token to the Dataplane
When connecting your Yjs provider, pass the access token using one of two methods. Both are supported in all regions.
const provider = new WebsocketProvider(
'wss://eu-central-1.wiresocket.net',
'your-document-id',
ydoc,
{
protocols: ['access_token', 'YOUR_ACCESS_TOKEN']
}
)
Preferred — keeps the token out of server access logs and browser history. const provider = new WebsocketProvider(
'wss://eu-central-1.wiresocket.net?token=YOUR_ACCESS_TOKEN',
'your-document-id',
ydoc
)
Allowed Domains
Each app supports up to 3 allowed domains. This is a critical security feature designed to prevent Token Theft in browser-based applications.
How it works
- Origin Enforcement: When a client connects to a node, the Data Plane checks the browser’s
Origin header.
- JWT Validation: The node compares this
Origin against the allowed_domain claims baked into your JWT.
- Automatic Rejection: If the domain does not match (e.g., a token stolen and used on
evil.com), the connection is immediately rejected.
Configuration Rules
- Normalization: The Dashboard automatically strips protocols (
https://) and trailing slashes. Entering https://myapp.com/ results in myapp.com.
- Development Support: You can add
localhost or localhost:port to your slots during development.
- Strict Format: Domains are validated against standard regex patterns before saving.
| Slot | Recommended Use |
|---|
allowed_domain_1 | Production (e.g., myapp.com) |
allowed_domain_2 | Staging (e.g., staging.myapp.com) |
allowed_domain_3 | Local development (e.g., localhost:3000) |
Plan Cancellation & Revocation
If a plan is cancelled or an app is deleted, existing connections are not immediately terminated. Active sessions continue until the current access token expires. No new tokens can be issued after cancellation.
This means tenants have up to 15 minutes of continued access after a plan
change takes effect. Plan accordingly if you need immediate revocation.
Replace {tenantId} with your tenant GUID, available in the tenantid claim of your JWT. For a deep-dive into how we secure these keys, see our Security & Hardening guide.
Key Rotation & Multiple Keys
WireSocket periodically rotates your tenant’s signing key. During rotation, the endpoint returns multiple public keys to facilitate a seamless transition:
| Key | Description |
|---|
| Active key | Signs all new tokens |
| Retired key | Previous key, valid for a short window after rotation |
If you are caching the JWKS response locally, re-fetch it when signature validation fails to pick up a newly rotated key.
Validate against all keys returned in the response, not just the first.
Pinning to a single key will cause verification failures during the rotation
window.
This endpoint is rate limited to 20 requests per 10 minutes. Local caching
is strongly recommended.