Identity
Use anonymous sessions by default, or map your signed-in users to Gleam with a short-lived HS256 signed identity token.
Anonymous Sessions Work By Default
When start() runs without an existing authenticated session, Gleam creates or restores a stable anonymous SDK identity for the device. Users can submit and follow feedback before your app asks them to sign in.
The anonymous identifier is stored by the SDK. Do not replace it with an account ID; use signed identity when the host app knows the current user.
Signed Identity
For signed-in users, generate a short-lived JWT on your backend and pass it to identify(signedIdentityToken:). The token must be signed with HS256 using the project identity secret configured on the Gleam server.
Never generate this token in the iOS app. The signing secret is server-only.
Why not pass a raw user ID?
A user ID sent directly from the iOS app is only a client assertion and can be modified. A backend-signed token proves your server has authenticated the user, keeps the identity secret off the device, lets Gleam accept only the intended profile fields, and expires quickly if a token is leaked.
| Claim | Required | Meaning |
|---|---|---|
| sub | Yes | Stable user ID from your product. |
| exp | Yes | Unix timestamp in seconds. Keep it short, for example five minutes. |
| aud | Recommended | Gleam project ID, slug, or portal subdomain. |
| name, display_name, or displayName | Optional | Display name copied into the Gleam profile. |
| avatar_url, avatarUrl, or picture | Optional | Avatar URL copied into the Gleam profile. |
| Optional | User email stored on the managed Gleam profile. |
Backend signing helpers
Use the same HS256 claim shape from any backend runtime. Keep the identity secret server-only.
import { createHmac } from "node:crypto";
function base64urlJson(value: unknown) {
return Buffer.from(JSON.stringify(value)).toString("base64url");
}
export function createGleamIdentityToken(input: {
identitySecret: string;
projectId: string;
user: {
id: string;
name?: string | null;
avatarUrl?: string | null;
email?: string | null;
};
}) {
const header = { alg: "HS256", typ: "JWT" };
const payload = {
sub: input.user.id,
aud: input.projectId,
exp: Math.floor(Date.now() / 1000) + 5 * 60,
name: input.user.name ?? undefined,
avatar_url: input.user.avatarUrl ?? undefined,
email: input.user.email ?? undefined,
};
const unsigned = base64urlJson(header) + "." + base64urlJson(payload);
const signature = createHmac("sha256", input.identitySecret)
.update(unsigned)
.digest("base64url");
return unsigned + "." + signature;
}Exchange in Swift
let signedIdentityToken = try await backend.fetchGleamIdentityToken()
let capabilities = try await Gleam.shared.identify(
signedIdentityToken: signedIdentityToken
)
if capabilities.authenticated {
// Portal UI and notification APIs now run as the signed-in user.
}Logout Order
Unregister the current APNs token before clearing the session. The SDK stores the token with the session that registered it, so unregisterCurrentDeviceToken() still works during logout.
Clear a signed-in SDK session
try await Gleam.shared.unregisterCurrentDeviceToken()
try Gleam.shared.clearSession()
try await Gleam.shared.refreshSession()