Tokens & OAuth helpers

@hyperyai/sdk low-level exports — TokenStorage for the stored session and getAuthorizationUrl, exchangeCodeForToken, refreshAccessToken and getUserInfo for a custom OAuth + PKCE flow.

HyperyProvider uses these internally. You only need them to build your own auth flow, read the stored session outside React, or call the gateway from a non-React part of your app. For the protocol itself see OAuth.

TokenStorage

Reads and writes the session the provider stores.

import { TokenStorage } from '@hyperyai/sdk';
 
const storage = new TokenStorage('localStorage'); // same `storage` as your provider config
 
const tokens = storage.getTokens();
if (tokens && !storage.isTokenExpired()) {
  await fetch('https://hypery.ai/api/user/me', {
    headers: { Authorization: `Bearer ${tokens.accessToken}` },
  });
}

new TokenStorage(storageType?: 'localStorage' | 'sessionStorage' | 'memory') — default 'localStorage'. With 'memory', or during server rendering (no window), it uses an in-memory map, so each instance starts empty.

MethodReturnsDescription
saveTokens(tokens: AuthTokens)voidStore tokens with a savedAt timestamp.
getTokens()(AuthTokens & { savedAt: number }) | nullStored tokens.
isTokenExpired()booleantrue when there are no tokens or the access token is within 60 s of expiry.
clearTokens()voidRemove tokens.
saveUser(user: User)voidStore the user.
getUser()User | nullStored user.
clearUser()voidRemove the user.
clear()voidRemove tokens and user.

Storage keys: hypery_auth_tokens and hypery_auth_user.

OAuth helpers

Authorization code + PKCE (S256), no client secret. Between the two steps the PKCE verifier and state are kept under hypery_oauth_verifier / hypery_oauth_state in the configured localStorage / sessionStorage. With memory (tokens in memory) they go to sessionStorage, falling back to an in-memory map when Web Storage is unavailable (popup login only). Both are cleared after the exchange and on logout.

import { getAuthorizationUrl, exchangeCodeForToken, getUserInfo, TokenStorage } from '@hyperyai/sdk';
 
const cfg = {
  clientId: 'your-client-id',
  redirectUri: 'https://yourapp.com/callback',
  gatewayUrl: 'https://hypery.ai',
  storage: 'localStorage' as const,
};
 
// 1. Send the user to Hypery
window.location.href = await getAuthorizationUrl({ ...cfg, scopes: ['read', 'ai:chat'] });
 
// 2. On /callback
const params = new URLSearchParams(location.search);
const tokens = await exchangeCodeForToken(params.get('code')!, { ...cfg, state: params.get('state') });
new TokenStorage('localStorage').saveTokens(tokens);
const user = await getUserInfo(tokens.accessToken, cfg.gatewayUrl);

getAuthorizationUrl

getAuthorizationUrl(config): Promise<string> — creates a PKCE pair and state, stores both, and returns {gatewayUrl}/api/oauth/authorize?....

OptionTypeDescription
clientIdstringRequired.
redirectUristringRequired.
gatewayUrlstringRequired.
scopesstring[]Required. Joined with spaces.
storage'localStorage' | 'sessionStorage' | 'memory'Required. Where the verifier + state are kept (memory uses sessionStorage, else an in-memory map).
statestringOAuth state. Random if omitted; stored either way so the callback can be verified.
prompt'login' | 'select_account' | 'consent'Optional prompt parameter.
provider'google' | 'github'Optional. Skip Hypery's hosted login page and go straight to this identity provider.

exchangeCodeForToken

exchangeCodeForToken(code, { clientId, redirectUri, gatewayUrl, storage, state? }): Promise<AuthTokens> — when state is passed (the state from the callback URL, including null) it is checked against the stored one first; a mismatch throws OAuth state mismatch: … before any request. It then reads the stored verifier, calls POST /api/oauth/token with grant_type=authorization_code, and clears the stored verifier + state. Throws OAuth verifier not found if there's no verifier, or the gateway's error_description on failure. Always pass state in a custom callback.

refreshAccessToken

refreshAccessToken(refreshToken, { clientId, gatewayUrl }): Promise<AuthTokens>POST /api/oauth/token with grant_type=refresh_token. Throws on failure. It doesn't store the result; call saveTokens yourself.

getUserInfo

getUserInfo(accessToken, gatewayUrl): Promise<{ id, email, name, image? }>GET /api/user/me. Throws Failed to fetch user info on a non-2xx response.

AuthTokens is { accessToken, refreshToken, expiresIn, tokenType } (expiresIn in seconds).

Next steps