Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Sign in with 1auth
Skip to content

Sign in with 1auth

Add passkey authentication to your app with a single method call. Users authenticate with Face ID or Touch ID - no passwords, no seed phrases.

Authentication

import { OneAuthClient } from '@rhinestone/1auth';
 
const client = new OneAuthClient({
  providerUrl: 'https://passkey.1auth.box',
});
 
// Open the authentication modal
const result = await client.authWithModal();
 
if (result.success) {
  console.log('Connected as:', result.user?.username);
  console.log('Address:', result.user?.address); // typed `0x${string}`
}

How It Works

  1. User clicks sign in - Your app calls authWithModal()
  2. 1auth modal opens - User enters their username or creates a new account
  3. Passkey prompt - Device prompts for Face ID / Touch ID
  4. Success - You receive user details and wallet address

The entire flow happens in a secure iframe. Your app never sees the passkey credentials.

Message Signing

Request the user to sign a message for verification:

const result = await client.signMessage({
  username: 'alice',
  message: `Sign in to MyApp\nTimestamp: ${Date.now()}`,
  description: 'Verify your identity',
});
 
if (result.success) {
  console.log('Signature:', result.signature);
  // Verify signature on your backend
}

SignMessageOptions

PropertyTypeRequiredDescription
usernamestringYesUsername of the signer
messagestringYesHuman-readable message to sign
descriptionstringNoDescription shown in the signing dialog
metadataRecord<string, unknown>NoAdditional data to display

AuthResult

authWithModal() returns an AuthResult:

import type { AuthResult } from '@rhinestone/1auth';
 
interface AuthResult {
  success: boolean;
  /** Authenticated user (present when success is true) */
  user?: {
    id: string;
    username?: string;
    address: `0x${string}`;
  };
  /** Error details when success is false */
  error?: {
    code: string;    // e.g. "USER_CANCELLED"
    message: string;
  };
}

Challenge-Based Authentication

Use authenticate() for server-verified login. It returns an AuthenticateResult — the same shape as AuthResult plus a challenge object with the cryptographic signature.

const result = await client.authenticate({
  challenge: `Login to MyApp\nTimestamp: ${Date.now()}\nNonce: ${crypto.randomUUID()}`
});
 
if (result.success && result.challenge) {
  // Send signature + signedHash to your backend for verification
  await fetch('/api/verify', {
    method: 'POST',
    body: JSON.stringify({
      username: result.user?.username,
      address: result.user?.address,
      signature: result.challenge.signature,
      signedHash: result.challenge.signedHash,
    }),
  });
}

AuthenticateResult

authenticate() returns an AuthenticateResult, which extends AuthResult with a challenge field:

import type { AuthenticateResult } from '@rhinestone/1auth';
 
interface AuthenticateResult extends AuthResult {
  /** Present when a challenge was provided in the options */
  challenge?: {
    signature: WebAuthnSignature;
    signedHash: `0x${string}`;
  };
}

Example: Protected Route

import { useState, useEffect } from 'react';
import { OneAuthClient } from '@rhinestone/1auth';
 
const client = new OneAuthClient({
  providerUrl: 'https://passkey.1auth.box',
});
 
function App() {
  const [user, setUser] = useState(null);
 
  const handleSignIn = async () => {
    const result = await client.authWithModal();
    if (result.success && result.user) {
      setUser({ username: result.user.username, address: result.user.address });
    }
  };
 
  if (!user) {
    return (
      <button onClick={handleSignIn}>
        Sign in with 1auth
      </button>
    );
  }
 
  return (
    <div>
      <p>Welcome, {user.username}!</p>
      <p>Address: {user.address}</p>
    </div>
  );
}