SDK Reference
Complete API reference for @mwen/js-sdk.
MwenClient
Import: import { MwenClient } from '@mwen/js-sdk'
Framework-agnostic core class. MwenProvider (React) wraps this internally. Use MwenClient directly for non-React frameworks — see Using MwenClient Without React.
Constructor
new MwenClient(config: MwenClientConfig): MwenClient
See Configuration for the full MwenClientConfig shape.
detectExtension()
client.detectExtension(): Promise<boolean>
Checks whether the mwen.io browser extension is installed by querying window.mwen.isInstalled. Caches the result — subsequent calls return the cached value.
Call this on page load. If it returns false, direct the user to install the extension before calling authenticate().
const installed = await client.detectExtension();
if (!installed) {
// Show install prompt
}
hasExtension
client.hasExtension: boolean
Synchronous accessor for the cached extension detection result. Returns false until detectExtension() has been called.
authenticate()
client.authenticate(): Promise<AuthenticateResult>
Initiates the "Sign in with mwen.io" flow. Internally:
- Generates an ephemeral P-256 key pair for JWE encryption.
- Generates a cryptographic nonce and CSRF state parameter.
- Builds an
AuthRequestV2with your config'sclientId,scopes, andappName. - Calls
window.mwen.authenticate(authRequest)— the extension popup opens. - Validates the CSRF state on response.
- Verifies the returned SD-JWT and/or BBS+ credentials locally.
- Persists the
VerifiedSessiontolocalStorage. - Schedules auto-refresh at 75% of credential remaining lifetime.
Throws:
| Error class | When |
|---|---|
MwenExtensionNotFoundError | Extension not installed or window.mwen not available |
MwenUserDeniedError | User clicked Deny on the consent screen |
MwenStateMismatchError | CSRF state mismatch — possible replay attack |
MwenCredentialNotFoundError | vct is set, vctRequired: true, and no matching credential in wallet |
MwenCredentialRevokedError | vct is set, vctRequired: true, and the matching credential has been revoked |
Error | All other failures (network, verification, etc.) |
Returns: AuthenticateResult
refreshCredential()
client.refreshCredential(): Promise<AuthenticateResult>
Refreshes the credential without a full re-authentication. If the extension has an active delegation grant covering your app's scopes, this completes silently (no popup). Otherwise, it falls back to a full authenticate().
Called automatically by the auto-refresh scheduler at 75% of credential lifetime. You can also call it manually if you need fresh claims.
Throws: MwenExtensionNotFoundError, MwenStateMismatchError, or Error.
getSession()
client.getSession(): VerifiedSession | null
Reads the current session from localStorage. Returns null if no session exists or the session has expired (based on sessionTtlMs).
Use on page load to restore a previous session without re-authenticating.
const session = client.getSession();
if (session) {
// User already authenticated — restore state
}
clearSession()
client.clearSession(): void
Removes the verified session from localStorage. Does not cancel the auto-refresh timer (call signOut() for that).
signOut()
client.signOut(): void
Cancels any pending auto-refresh timer and clears the session from localStorage. Use this for explicit sign-out actions.
requestAsyncAttestation()
client.requestAsyncAttestation(): Promise<string>
Submits an async attestation request to the relay endpoint. Returns the request_id of the queued request. The extension polls the relay endpoint every 5 minutes and fulfils the request when the user is available.
Requires an active verified session. See Async Attestations & Relay.
MwenProvider
Import: import { MwenProvider } from '@mwen/js-sdk/react'
React context provider. Wrap your application (or the authenticated portion) in this component.
Props
interface MwenProviderProps {
config: MwenClientConfig;
children: React.ReactNode;
}
On mount, MwenProvider:
- Constructs a
MwenClientinstance. - Calls
detectExtension(). - Attempts to restore an existing session via
getSession(). - Listens for cross-tab revocation via the
storageevent. - Listens for cross-tab session updates.
useMwen()
Import: import { useMwen } from '@mwen/js-sdk/react'
useMwen(): MwenContextValue
Must be used inside a MwenProvider. Throws if called outside.
MwenContextValue
interface MwenContextValue {
/** The mwen.io client instance. */
client: MwenClient;
/** True if the mwen.io extension is detected. */
hasExtension: boolean;
/** True while detectExtension() or authenticate() is in progress. */
isLoading: boolean;
/** The current verified session, or null if not authenticated. */
session: VerifiedSession | null;
/** The last authentication error, or null. */
error: Error | null;
/** Initiate the sign-in flow. */
authenticate: () => Promise<void>;
/** Refresh the credential. */
refreshCredential: () => Promise<void>;
/** Sign out and clear the session. */
signOut: () => void;
/** Submit an async attestation relay request. */
requestAsyncAttestation: () => Promise<string>;
}
verifyAccessTokenFromHeader()
Import: import { verifyAccessTokenFromHeader } from '@mwen/js-sdk/server'
verifyAccessTokenFromHeader(
authHeader: string,
audience: string,
options?: { clockSkewSeconds?: number }
): Promise<AccessTokenVerificationResult>
Server-side utility for verifying the access_token from the Authorization: Bearer <token> header.
Parameters:
| Parameter | Type | Description |
|---|---|---|
authHeader | string | The full Authorization header value (e.g. "Bearer eyJ...") |
audience | string | Your clientId (must match the aud claim in the token) |
options.clockSkewSeconds | number | Allowed clock skew in seconds. Default: 0. |
Returns:
interface AccessTokenVerificationResult {
valid: boolean;
payload?: {
sub: string; // User's did:jwk (stable per-app identifier)
iss: string; // Issuer DID
aud: string; // Audience (your clientId)
iat: number; // Issued at (Unix seconds)
exp: number; // Expires at (Unix seconds)
scope?: string; // Space-delimited granted scopes
};
error?: string; // Present when valid === false
}
Type: VerifiedSession
interface VerifiedSession {
appIdentity: string; // User's did:jwk for your app — use as primary key
verified: true;
scopes: string[]; // Scopes granted in this session
holder: string; // Same as appIdentity
timestamp: number; // When the session was created (Unix ms)
expiresAt?: number; // Credential expiry (Unix ms)
access_token?: string; // Signed AT+JWT (3600 s TTL)
refresh_token?: string; // Signed RT+JWT (86400 s TTL, rotated on use)
issuerDID?: string; // did:jwk of the issuing key
claims?: Record<string, { value: unknown; format: string; zkProof?: boolean }>;
disclosedClaims?: string[]; // Names of claims the user chose to disclose
}
VerifiedSession is persisted to localStorage under the key mwen_verified_session.
Type: AuthenticateResult
interface AuthenticateResult {
subjectDID: string; // User's did:jwk
issuerDID: string; // Issuing key DID
claims: Record<string, ClaimValue>; // Verified disclosed claims
expiresAt?: number; // Credential expiry (Unix ms)
access_token?: string;
refresh_token?: string;
sdJwt?: {
verification: VerificationResult;
disclosedClaims: string[];
rawToken: string;
presentation: string;
};
bbs?: {
verification: BBSVerificationResult;
rawToken: string;
};
requestedCredentials: string[]; // VCT URIs from config.vct, or []
presentedCredentials: string[]; // VCT URIs actually presented, or [] if fell back to self-attestation
}
presentedCredentials is empty when vctRequired: false and the wallet fell back to self-attestation. See Credential Gating.
Error classes
All are importable from @mwen/js-sdk.
// Extension not installed
class MwenExtensionNotFoundError extends Error {}
// User clicked Deny on the consent screen
class MwenUserDeniedError extends Error {}
// CSRF state parameter mismatch
class MwenStateMismatchError extends Error {}
// vct is set, vctRequired: true, and no matching credential in the wallet
class MwenCredentialNotFoundError extends Error {}
// vct is set, vctRequired: true, and the matching credential has been revoked
class MwenCredentialRevokedError extends Error {}