Skip to content
On this page

Miniapp Identity Token — Validation Guide

Request the token

From the miniapp, call the Application service intent get-identity-token to obtain a signed JWT proving the current user's identity.

Intent reference

FieldValue
ServiceApplication
Actionget-identity-token
AvailabilityDeveloper

Parameters: None — the target application is inferred from the calling mini-app.

JWT claims returned: sub = userId, aud = callingApplicationId, iss = platform, exp = 5 min from now.

Usage example

javascript
import { ValuApi } from "@arkeytyp/valu-api";

let valuApi = globalThis.valuApi;
if (!valuApi) {
  valuApi = globalThis.valuApi = new ValuApi();
}

async function fetchIdentityToken() {
  const appService = await valuApi.getApi('Application');
  const token = await appService.run('get-identity-token');

  // Send the token to your backend with each request
  const res = await fetch('https://your-backend.example.com/api/data', {
    headers: { Authorization: `Bearer ${token}` },
  });
  return res.json();
}

WARNING

The token is valid for 5 minutes. You can reuse it for multiple requests within that window — just make sure to request a fresh one before it expires.

Fetch the public keys

Your backend fetches the JWKS once and caches it (keys change only on platform restart):

GET https://<platform-host>/.well-known/jwks.json
json
{
  "keys": [{
    "kty": "RSA",
    "use": "sig",
    "alg": "RS256",
    "kid": "<key-id>",
    "n": "...",
    "e": "AQAB"
  }]
}

Validate the token

Match the JWT kid header to the correct key in the JWKS, then verify:

CheckExpected value
Signature algorithmRS256
issPlatform issuer (e.g. https://api.roomful.net)
audYour miniapp ID
expMust be in the future

The sub claim contains the verified platform user ID.

Node.js example (using jose)

javascript
import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://<platform-host>/.well-known/jwks.json")
);

async function verifyIdentityToken(token) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: "https://<platform-host>",
    audience: "YOUR_APP_ID",
  });
  return payload.sub; // platform user ID
}

Security notes

DANGER

Never validate tokens client-side; signature verification must happen on your backend.

  • Always verify aud — a token issued for a different miniapp must be rejected.
  • Cache JWKS with a TTL (e.g. 1 hour) but re-fetch when you encounter an unknown kid.
  • Do not accept expired tokens — the 5-minute window is intentional; reject anything with exp in the past.