Skip to content

TypeScript SDK

View as Markdown

The TypeScript SDK is split into small packages under the @sudomimus/* scope. The packages are usable from Node.js and browser-capable runtimes when the surrounding flow is appropriate for that environment.

PackageUse it for
@sudomimus/connectConnect inquiry lifecycle: establish, statusPoll, redeem, info, plus token verification through application metadata.
@sudomimus/sessionRefresh-token rotation, introspection, logout, revoke-all, and helper token stores.
@sudomimus/deviceDevice authorization: deviceAuthorize, deviceToken, and automatic polling helpers.
@sudomimus/nativeSteam ticket and AccessKey direct-issue.
joseStandards-based JWT parsing and cryptographic verification.

Install only the packages your integration needs:

Terminal window
pnpm add @sudomimus/connect @sudomimus/session
npm install @sudomimus/connect @sudomimus/session
yarn add @sudomimus/connect @sudomimus/session
import { ConnectClient, RETURN_METHOD } from "@sudomimus/connect";
const client = new ConnectClient({
clientAuth: {
applicationAnchor: "your-app-anchor",
privateKeyPem: process.env.SUDOMIMUS_CLIENT_AUTH_PRIVATE_KEY!,
},
});
const inquiry = await client.establish({
applicationAnchor: "your-app-anchor",
returnMethods: [{ type: RETURN_METHOD.STATUS_POLL, payload: {} }],
});
const status = await client.statusPoll({
exposureKey: inquiry.exposureKey,
hiddenKey: inquiry.hiddenKey,
});
if (status.status === "REALIZED") {
const tokens = await client.redeem({
exposureKey: inquiry.exposureKey,
hiddenKey: inquiry.hiddenKey,
confirmationKey: status.confirmationKey,
});
}

/establish requires a client-auth JWT with audience sudomimus-connect. Passing clientAuth lets the SDK sign those requests internally.

import {
InMemoryTokenStore,
RotatingSessionClient,
SessionClient,
} from "@sudomimus/session";
const store = new InMemoryTokenStore();
const session = new RotatingSessionClient(new SessionClient(), store);
await session.seed({
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
});
const accessToken = await session.refresh();
await session.logout();

revokeAll is an application-backend operation and requires client-auth signing with audience sudomimus-session.

import { DeviceClient, DeviceTokenApiError } from "@sudomimus/device";
const device = new DeviceClient({ baseUrl: "https://device-api.sudomimus.com" });
const auth = await device.deviceAuthorize({ applicationAnchor: "your-app-anchor" });
console.log(auth.userCode, auth.verificationUriComplete);
while (true) {
try {
const tokens = await device.deviceToken({ deviceCode: auth.deviceCode });
break;
} catch (error) {
if (
error instanceof DeviceTokenApiError
&& (error.error === "authorization_pending" || error.error === "slow_down")
) {
await new Promise((resolve) => setTimeout(resolve, (error.interval ?? auth.interval) * 1000));
continue;
}
throw error;
}
}

Use @sudomimus/session after device authorization succeeds; the Device API returns ordinary Sudomimus access and refresh tokens.

Token verification is independent of Connect. Fetch the application’s JWK Set from Session API at GET /applications/{applicationAnchor}/jwks.json, cache it according to Cache-Control, and select the exact key named by the token’s kid. Refresh the set once on an unknown kid. Use a standards-based JOSE implementation such as jose for JWT parsing and cryptographic verification; do not use Connect /info as a key source.

After successful verification, read the application-visible user key from payload sub, the logical session from payload sid, and the bearer instance from payload jti. Access tokens contain no profile fields; refresh tokens contain no user identifier and add only rotationVersion. Fetch current profile data from Session /userinfo. Offline verification cannot observe a later logout or authority change, so call Session /introspect when an operation requires live session state.