Reference
API reference
Overview · React Native and Expo · Android · iOS · Register an app · API reference · Errors and security · Changelog
Coming soon @seletech/seleid-client is not on npm yet. These pages describe version 0.1.0 so you can plan an integration. See the roadmap.
Package @seletech/seleid-client 0.1.0. Exports ./ and ./testing. No side effects at import time, no secrets, no node: or Expo imports.
SeleIdClient
new SeleIdClient(options?: SeleIdClientOptions)
| Option | Default | Meaning |
|---|---|---|
baseUrl | https://auth.seleid.dev | SeleID origin |
fetch | globalThis.fetch (looked up lazily) | Inject for tests or React Native |
timeoutMs | 4000 | Hard timeout per attempt (timer race, so a fetch that ignores signal still cannot hang) |
retries | 2 | Retries for idempotent calls only, exponential backoff with jitter |
budgetMs | 10000 | Total time for one logical operation |
contextTimeoutMs | 3000 | Timeout and budget for sessionContext |
useDiscovery | true | Read endpoints from the discovery document (origin-checked) |
expectedIssuer | https://auth.seleid.dev | Issuer the verifier requires |
onEvent | none | Telemetry callback |
Methods
| Method | Returns | Notes |
|---|---|---|
discovery() | OpenIdConfiguration | Cached; issuer and endpoints must belong to the configured origin |
jwks() | Jwk[] | |
createVerifier({ audience, issuer?, clockSkewSeconds?, crypto?, staleIfErrorMs? }) | AccessTokenVerifier with .keys | RS256, typ at+jwt, checks iss, aud, exp, iat, sv; 60 s skew; JWKS cache 300 s, unknown kid refetches once, at most one refetch per 60 s. Planned server side. |
exchangeCode({ clientId, code, redirectUri, codeVerifier }) | TokenSet | Never retried. A rejected code is unauthenticated, not revoked |
refresh(clientId, refreshToken) | TokenSet | Never retried (tokens rotate). Prefer TokenManager |
sessionContext(accessToken) | SessionContext | GET /v1/session/context, 3 s total, one in-flight call per token. Planned server side. |
listSessions(accessToken) | DeviceSession[] | GET /v1/account/sessions. Planned server side. |
revokeSession(accessToken, id), revokeAllSessions(accessToken, { keepCurrent? }) | RevokeResult | Never retried. Planned server side. |
getPreferences(accessToken), patchPreferences(accessToken, patch) | AccountPreferences | Patch accepts marketing, product, selerank and ifVersion. Security notices cannot be turned off. Planned server side. |
listEvents(accessToken, { after?, limit? }) | SeleIdAccountEvent[] | Limit 1 to 100. Planned server side. |
Token endpoint note: the SDK accepts the camelCase body SeleID returns today and the standard snake_case body planned for the future.
TokenManager
new TokenManager({ client, store, clientId, refreshSkewMs = 30000 })
await tokens.setTokens(tokenSet)
await tokens.getTokens() // TokenSet | null
await tokens.getAccessToken({ forceRefresh?, correlationId? })
await tokens.clear()
Concurrent callers share one refresh (single flight). The rotated refresh token is written to the store before anyone uses it. A timeout, network error or outage keeps the tokens. A definitive refusal (revoked, disabled, deleted) clears them. An unreadable stored blob is cleared and treated as signed out.
SessionGuard
new SessionGuard({ client, tokens, verifier })
const { claims, context, source } = await guard.check({
sensitive?: boolean, // online context required, answer at most 30 s old, fails closed
withContext?: boolean, // ask for context but allow a recent good answer on outage
correlationId?: string,
})
source is local, online, cached or last_good. For a sensitive check the context must be active and its generation must equal the token’s sgen; anything else is revoked. last_good reuses a recent active answer for at most min(validFor, 900) seconds, only for non-sensitive checks.
Token storage ports
interface TokenStore { get(): Promise<string | null>; set(value: string): Promise<void>; clear(): Promise<void>; }
new MemoryTokenStore() // tests, short-lived processes
new SecureStoreTokenStore(SecureStore, key?) // expo-secure-store shape; key defaults to 'seleid.tokens.v1'
Types
interface TokenSet { accessToken: string; refreshToken: string; idToken: string; scope: string; expiresAt: number /* ms epoch */ }
interface AccessTokenClaims { iss; sub; aud: string | string[]; iat; exp; jti; scope; client_id; sgen: number; sv: number }
interface SessionContext {
schemaVersion: 1; subjectId: string; kind: 'person' | 'page_host';
flags: { emailConfirmed; passwordRecoveryPending; minor; staff: boolean };
verification: { level: 'none' | 'email' | 'identity' | 'official'; updatedAt: string | null };
consent: { marketing; selerankPersonalization; selerankCrossApp: boolean; version: number };
generation: number;
status: 'active' | 'recovering' | 'suspended' | 'banned' | 'disabled' | 'deleted';
pageHost?: { pageId: string; role: 'owner' | 'admin' | 'editor' | 'analyst' };
issuedAt: string; validFor: number /* seconds */;
}
Telemetry
onEvent receives { type, op, correlationId, attempt, durationMs, errorKind?, code? } where type is start, retry, success, failure, timeout or stuck. The shape is closed on purpose: tokens, emails, subject ids and response bodies cannot appear in it.
Testing helpers
@seletech/seleid-client/testing exports FakeSeleId (create, fetch, rotateKey, issueAccessToken, issueRefreshToken, revokeRefreshToken, bumpGeneration, setStatus, failNext, count, plus hang, delayMs and ignoreAbort to simulate slow servers).