Auth API
The Auth API provides 6 methods for authenticating users via email OTP or wallet signature, refreshing sessions, fetching the current user, and signing out.
Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
sendEmailOtp(email) | email: string | ApiResponse<{ sent: boolean }> | Sends a one-time password to the given email address. |
verifyEmailOtp(email, otp) | email: string, otp: string | ApiResponse<EngineAuthResponse> | Verifies the OTP and returns tokens plus user profile. |
authWithWallet(walletAddress, signature, message) | walletAddress: string, signature: string, message: string | ApiResponse<EngineAuthResponse> | Authenticates via a signed message from the user's wallet. |
refreshToken(refreshToken) | refreshToken: string | ApiResponse<EngineAuthResponse> | Exchanges a refresh token for a new access/refresh token pair. |
getCurrentUser() | -- | ApiResponse<User> | Returns the profile of the currently authenticated user. |
signOut() | -- | ApiResponse<{ success: boolean }> | Invalidates the current session on the server. |
Types
EngineAuthResponse
interface EngineAuthResponse {
/** JWT access token. Pass to engine.setAccessToken(). */
accessToken: string;
/** Refresh token for obtaining new access tokens. */
refreshToken: string;
/** Access token expiry in seconds from now. */
expiresIn: number;
/** Authenticated user profile. */
user: User;
}
User
interface User {
id: string;
email?: string;
walletAddress?: string;
displayName?: string;
avatarUrl?: string;
role: 'user' | 'admin';
createdAt: string;
updatedAt: string;
}
Email OTP Flow
Step 1 -- Send OTP
const res = await engine.sendEmailOtp('user@example.com');
if (res.success) {
console.log('OTP sent');
} else {
console.error('Failed to send OTP:', res.error);
}
Step 2 -- Verify OTP
const authRes = await engine.verifyEmailOtp('user@example.com', '482901');
if (authRes.success && authRes.data) {
// Store tokens
engine.setAccessToken(authRes.data.accessToken);
// Persist refresh token for later
await secureStore.set('refreshToken', authRes.data.refreshToken);
console.log('Welcome', authRes.data.user.displayName);
}
Wallet Signature Flow
// 1. Generate a sign-in message (app-defined)
const message = `Sign in to ONE\nNonce: ${crypto.randomUUID()}`;
// 2. Have the user sign the message with their wallet
const signature = await walletClient.signMessage({ message });
// 3. Send to the engine for verification
const authRes = await engine.authWithWallet(
walletClient.account.address,
signature,
message
);
if (authRes.success && authRes.data) {
engine.setAccessToken(authRes.data.accessToken);
}
Token Refresh
Access tokens expire after expiresIn seconds. Use the refresh token to obtain new credentials without requiring the user to re-authenticate.
const stored = await secureStore.get('refreshToken');
const res = await engine.refreshToken(stored);
if (res.success && res.data) {
engine.setAccessToken(res.data.accessToken);
await secureStore.set('refreshToken', res.data.refreshToken);
}
Get Current User
Fetch the authenticated user's profile at any time:
const userRes = await engine.getCurrentUser();
if (userRes.success && userRes.data) {
console.log('User ID:', userRes.data.id);
console.log('Email:', userRes.data.email);
console.log('Role:', userRes.data.role);
}
Sign Out
Invalidate the current session server-side:
const res = await engine.signOut();
if (res.success) {
// Clear local state
engine.setAccessToken('');
await secureStore.delete('refreshToken');
}
Error Cases
| Scenario | error String |
|---|---|
| Invalid or expired OTP | "invalid_otp" |
| Email not found | "user_not_found" |
| Invalid wallet signature | "invalid_signature" |
| Expired refresh token | "token_expired" |
| No access token set | "unauthorized" |
Next Steps
- Wallet API -- query balances and submit transactions.
- Engine Client -- how
setAccessTokenworks under the hood.