SDK
Player accounts and tokens
Players can play every game as guests. Players with a Smaz Games account get account saves and can be identified by your own servers. Your game never sees a player's email address, sign-in details, session cookie, exact age, uploaded picture or friends. It sees only whether the player is under 18.
Player details
const player = await OpenArcade.getUser();
if (player) {
label.textContent = player.name; // or player.username
}getUser() resolves to null for guests, or:
| Field | Meaning |
|---|---|
playerId | Stable ID for this player in your game only. The same person has a different playerId in every game, so games cannot match players with each other |
username | Public handle: 3 to 24 lowercase letters, numbers or _. Players can change it |
name | Display name. Players can change it |
avatar | The preset avatar the player picked (rocket, ghost, cat, bolt, planet, controller), or custom for an uploaded picture. Uploaded pictures are not shared with games |
minor | true unless the account belongs to an adult |
Use playerId as the key in your own database. Never use username or name as an identifier: they change. Show the current name or username each time the game starts.
The values from getUser() come from the player's browser, so a modified browser could change them. To trust who a player is on your server, use a token.
Asking players to sign in
signInButton.onclick = async () => {
await saveProgressNow();
await OpenArcade.promptSignIn(); // opens the site's sign-in dialog
};After signing in, the game frame reloads with the player's account, and init() reports the player. Call promptSignIn() only from a button the player pressed, such as Sign in to save online. Never block play behind sign-in, and do not build your own sign-in screens that ask for Smaz Games details.
Player tokens
getPlayerToken() gives your game a signed token that proves who the player is to your own server, such as a multiplayer server or leaderboard.
const { token } = await OpenArcade.getPlayerToken();
const socket = new WebSocket('wss://play.example.com/join');
socket.onopen = () => socket.send(JSON.stringify({ type: 'hello', token }));- The token is a JWT signed with ES256. It is valid for 10 minutes.
- Request a fresh token for each connection. Do not store tokens.
- Guests get a
401error. Offer guest play without online features, or ask the player to sign in. - List your server under Outside addresses on the upload form, or the browser blocks the connection.
Token contents
{
"iss": "https://smazgames.com",
"aud": "smaz:3f6c2a6e-0b7d-4f4e-9d0a-5d1d1f5f7a21",
"sub": "Zq3V8f1mQe2y0x9Kp4bA7w",
"game": "3f6c2a6e-0b7d-4f4e-9d0a-5d1d1f5f7a21",
"username": "pixel_fox",
"name": "Pixel Fox",
"minor": false,
"iat": 1761200000,
"nbf": 1761199995,
"exp": 1761200600,
"jti": "8d1e2b0a-6a9a-4b67-9d3e-4c0f0b3c7e11"
}| Claim | Meaning |
|---|---|
iss | Always https://smazgames.com |
aud | smaz: followed by your game ID. Your game ID is shown on each game in the developer dashboard |
sub | The player's playerId for your game |
game | Your game ID |
username, name | The player's current public names |
minor | true unless the account belongs to an adult. Apply the chat rules |
iat, nbf, exp | Issued, not-before and expiry times, in seconds |
jti | Unique token ID. Store recent IDs if you want to reject replays |
Verifying tokens
The public keys are published as a JSON Web Key Set at:
https://smazgames.com/api/sdk/jwks.jsonVerify the signature, the issuer, the audience and the expiry on your server. With Node.js and the jose library:
import { createRemoteJWKSet, jwtVerify } from 'jose';
const JWKS = createRemoteJWKSet(new URL('https://smazgames.com/api/sdk/jwks.json'));
const GAME_ID = '3f6c2a6e-0b7d-4f4e-9d0a-5d1d1f5f7a21';
export async function verifyPlayer(token) {
const { payload } = await jwtVerify(token, JWKS, {
issuer: 'https://smazgames.com',
audience: 'smaz:' + GAME_ID,
algorithms: ['ES256'],
clockTolerance: 30
});
return { playerId: payload.sub, name: payload.name, minor: payload.minor };
}In Python with PyJWT:
import jwt
jwks = jwt.PyJWKClient("https://smazgames.com/api/sdk/jwks.json")
def verify_player(token, game_id):
key = jwks.get_signing_key_from_jwt(token)
payload = jwt.decode(token, key.key, algorithms=["ES256"],
audience="smaz:" + game_id, issuer="https://smazgames.com", leeway=30)
return payload["sub"], payload["name"], payload["minor"]- Cache the key set; the libraries above do this for you. Keys are identified by
kid. If a token has an unknownkid, fetch the key set again. - Reject tokens with a different
aud. A token for another game must not work on your server. - Use a token only to check who the player is. Do not send tokens to anyone else, sell them, log them, store them after checking them or put them in URLs your server records.
Testing
In local test mode, ?smazUser=test signs in a test player and getPlayerToken() returns the string local-test-token, which does not verify. Accept it only in your own development builds. In private previews, tokens are real and use your game ID, so you can test your server before release.
Player data rules
- Collect only what your game needs. Do not ask for email addresses, phone numbers, real names or locations.
- Do not try to match players across games or sites, or to find out who a player is outside your game.
playerIdis different in every game on purpose. - If your game stores player data on your servers, declare it on the upload form (Collects personal data on its own servers), publish a privacy policy that covers it and follow the privacy laws that apply to you and your players.
- Never ask for a player's Smaz Games password, and never show a login form that looks like the site's.