Docs/Getting started/Authentication

Authentication

How browsers connect, how private channels are authorized, and how servers sign publish requests.

Guide· 6 min read

Two credential domains

EmitWave keeps browser credentials and server credentials strictly separate. A public application key identifies an app but grants no private channel access; a connection token permits a socket but grants no private channel access by itself.

CredentialHeld byGrants
ew_pk_…BrowserIdentifies the application; safe to expose
End-user Bearer tokenBrowserAuthenticates the user to EmitWave
Connection tokenSDK (auto)Permission to open the socket
Subscription tokenSDK (auto)Access to one private or presence channel
Server key + secretTrusted serverPermission to publish (HMAC-signed)

Browser connection flow

Pass an authHeaders callback; the SDK invokes it before every token request so a renewed session is picked up without recreating the client.

connect.ts
const emitwave = new Emitwave('ew_pk_live_your_public_key', {
  // Runs before every connect-token and channel-auth request,
  // so a refreshed token is used without recreating the client.
  authHeaders: async () => ({
    Authorization: `Bearer ${await getEndUserToken()}`,
  }),
})

await emitwave.connect()
  1. Your app authenticates the end user and gets a Bearer token EmitWave recognizes.
  2. connect() POSTs the public key to /connect-token with that token. Required for every connection, even public-only ones.
  3. Public and public-cache channels subscribe immediately.
  4. Private, presence, cache, and encrypted channels first call /channel-auth.

Channel authorization

Authenticated channel types deny access unless a registered callback matches. Private callbacks return a truthy value; presence callbacks must return the member identity.

channels.php
// Private: return a truthy value to allow
Emitwave::channel('private-account.{account}', fn ($user, $account) =>
    (string) $user->account_id === $account
);

// Presence: return the member identity
Emitwave::channel('presence-room.{room}', fn ($user, $room) => [
    'id' => (string) $user->id,
    'info' => ['name' => $user->name],
]);
A bare true is insufficient for a presence channel — EmitWave needs an id to populate the member set. Member identity always comes from the server callback, never the client.

Server publish signing

For every publish, a server SDK hashes the exact JSON body and HMAC-signs the HTTP method, path, canonical query, and body hash with HMAC-SHA256. The gateway rejects unknown keys, revoked credentials, stale timestamps, and invalid signatures. See Publishing and the error codes.

Management API tokens

The management API under /api/platform/* uses bearer tokens with organization RBAC (owner > admin > developer > viewer). Mint one from an account's credentials:

token.sh
TOKEN=$(curl -fsS -X POST https://api.emitwave.com/api/platform/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"email":"[email protected]","password":"…","device_name":"cli"}' \
  | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')

See the API reference for the management endpoints this token unlocks.