Skip to Content
⚙️ Core SDKClient Authentication

Authentication

JWT token management, login flows, and authenticated requests with @embarkai/core/auth.

The auth module handles the full authentication lifecycle: logging in via multiple providers, managing JWT tokens with automatic refresh, and making authenticated API requests.

Configuration

Configure the JWT module with your TSS service URL and (optionally) a project ID. The module manages tokens via a singleton jwtTokenManager with its own storage; pick storage explicitly only when you create a custom manager (see JwtTokenManager below).

import { configureJwtModule } from '@embarkai/core' configureJwtModule({ tssUrl: 'https://api.embarkai.io', projectId: 'your-project-id', // optional })

In React apps, Provider from @embarkai/ui-kit calls configureJwtModule for you — don’t call it manually in frontend code.

Login Methods

Login with User ID

The simplest login method — authenticates directly with a user identifier:

import { loginWithUserId } from '@embarkai/core' const response = await loginWithUserId('user_abc123') console.log('Access Token:', response.accessToken) console.log('Has Keyshare:', response.hasKeyshare) console.log('Is New User:', response.isNewUser)

Login with Email

Two-step email verification flow:

import { loginWithEmail } from '@embarkai/core' // Step 1: Request a verification code (sent to user's inbox) // Step 2: Submit the code const response = await loginWithEmail('user@example.com', '123456') console.log('User ID:', response.userId)

Login with Telegram

Authenticate using Telegram login widget data:

import { loginWithTelegram } from '@embarkai/core' const response = await loginWithTelegram({ id: 123456789, first_name: 'Alice', last_name: 'Doe', // optional username: 'alice', // optional photo_url: 'https://...', // optional auth_date: 1700000000, hash: 'telegram_auth_hash...', }) // Suppress automatic token persistence (useful for server-side flows) await loginWithTelegram( { id: 123456789, first_name: 'Alice', auth_date: 1700000000, hash: 'telegram_auth_hash...' }, { skipTokenSave: true }, )

All login helpers (loginWithUserId, loginWithEmail, loginWithTelegram) accept an optional { skipTokenSave?: boolean } second argument.

Login Response

All login methods return a LoginResponse:

FieldTypeDescription
accessTokenstringShort-lived JWT for API calls
refreshTokenstringLong-lived token for refreshing access
userIdstringUnique user identifier
expiresInnumberToken TTL in seconds
hasKeysharebooleanWhether the user has a TSS keyshare on the server
isNewUserboolean | undefinedtrue on first login
avatarstring | nullUser avatar URL
displayNamestring | nullUser display name
providersstring[]Linked auth providers

Token Management

JwtTokenManager

The JwtTokenManager class stores tokens and handles automatic refresh. Use the singleton or create your own instance:

import { jwtTokenManager, createJwtTokenManager, MemoryStorage } from '@embarkai/core' // Singleton (uses built-in default storage) const isLoggedIn = jwtTokenManager.isAuthenticated() const header = jwtTokenManager.getAuthHeader() // → 'Bearer eyJ...' or null when logged out // Custom instance with explicit storage backend const manager = createJwtTokenManager(new MemoryStorage())

Key methods:

MethodReturnsDescription
getAccessToken()string | nullCurrent access token
getRefreshToken()string | nullCurrent refresh token
getUserId()string | nullAuthenticated user ID
getHasKeyshare()boolean | nullWhether the server holds a keyshare for the user
getAvatar() / getDisplayName()string | nullProfile fields from the last login
getProviders()string[]Linked auth providers
getTokens()JwtTokens | nullFull token set, including expiresAt
setTokens(response)Promise<void>Store a LoginResponse (e.g. after a server-side login)
isTokenExpired()booleanCheck if access token is expired
isAuthenticated()booleanCheck if user has a non-expired access token
refreshAccessToken()Promise<boolean>Force a token refresh; false if the session is dead or the service is unavailable
refreshTokens()Promise<RefreshOutcome>Same, but returns 'refreshed' | 'session_dead' | 'unavailable'
getAuthHeader()string | nullAuthorization header value (Bearer …)
clearTokens()Promise<void>Remove all stored tokens

Token Storage

Implement the TokenStorage interface for custom storage backends:

import type { TokenStorage } from '@embarkai/core' class SecureStorage implements TokenStorage { async getItem(key: string): Promise<string | null> { return await encrypted.get(key) } async setItem(key: string, value: string): Promise<void> { await encrypted.set(key, value) } async removeItem(key: string): Promise<void> { await encrypted.delete(key) } }

Built-in adapters: LocalStorageAdapter (browser localStorage) and MemoryStorage (in-memory, non-persistent — pass it to createJwtTokenManager(new MemoryStorage()) for tests or server-side flows).

Utility Functions

Verify a Token

import { verifyToken } from '@embarkai/core' const result = await verifyToken() // null when there is no stored token or the request failed if (result?.valid) { console.log('User:', result.userId) console.log('Session:', result.sessionId) console.log('Has Keyshare:', result.hasKeyshare) }

Ensure Valid Token

Automatically refreshes the token if expired. Resolves to false (does not throw) if the refresh fails:

import { ensureValidToken, ensureFreshSession } from '@embarkai/core' const ok = await ensureValidToken() if (!ok) { // session is dead or the auth service is unavailable — ask the user to log in again } // Same check with the exact outcome const outcome = await ensureFreshSession() // 'valid' | 'refreshed' | 'session_dead' | 'unavailable'

Get Valid Tokens

Returns current tokens, refreshing first if needed:

import { getValidTokens } from '@embarkai/core' const tokens = await getValidTokens() if (tokens) { console.log('User:', tokens.userId) console.log('Expires at:', new Date(tokens.expiresAt * 1000)) } else { // refresh failed, user needs to re-authenticate }

Authenticated Fetch

A drop-in wrapper around fetch that injects the Authorization header and auto-refreshes expired tokens:

import { authenticatedFetch } from '@embarkai/core' const res = await authenticatedFetch('https://api.embarkai.io/me') const user = await res.json()

Logout

Clears all stored tokens:

import { logout } from '@embarkai/core' await logout()

logout, verifyToken, ensureValidToken, ensureFreshSession, getValidTokens, syncKeyshareStatus and authenticatedFetch operate on the singleton jwtTokenManager by default; pass a custom manager as the last argument to use your own instance.

Sync Keyshare Status

Re-checks whether the server holds a keyshare for the current user and updates stored token metadata. Returns the fresh hasKeyshare value:

import { syncKeyshareStatus } from '@embarkai/core' const hasKeyshare = await syncKeyshareStatus()

Next Steps

  • Server Wallets — create and manage MPC wallets after authentication
  • Vault Backup — back up keyshares with password encryption
  • Bundler — submit UserOperations with authenticated sessions
Last updated on