Skip to content

Add InPageReactStrategy for component-based authentication #1080

@jchris

Description

@jchris

Problem

Currently, Fireproof's authentication strategies require either:

  1. SimpleTokenStrategy - Pre-configured tokens (no user auth flow)
  2. RedirectStrategy - Popup windows that can be blocked and redirect to external dashboard
  3. IframeStrategy - Incomplete implementation with broken waitForToken()

This creates friction for React applications that want to:

  • Integrate authentication naturally into their existing UI
  • Use their preferred auth providers (Clerk, Auth0, Firebase, etc.)
  • Avoid popup blockers and external redirects
  • Maintain consistent UX within their application

Proposed Solution

Create an InPageReactStrategy that allows consumers to provide their own React authentication component while maintaining the TokenStrategie interface.

Design Overview

export class InPageReactStrategy implements TokenStrategie {
  constructor(AuthComponent: React.ComponentType<AuthComponentProps>) {
    this.authComponent = AuthComponent;
  }
  
  open() {
    // Render consumer's auth component into DOM
    ReactDOM.render(createElement(this.authComponent, {
      deviceId,
      onToken: (tokenAndClaims) => this.handleToken(tokenAndClaims),
      onClose: () => this.cleanup()
    }), containerElement);
  }
  
  // ... implement other TokenStrategie methods
}

Consumer Usage

// Consumer provides their own auth component
function MyAuthComponent({ deviceId, onToken, onClose }: AuthComponentProps) {
  const { getToken } = useAuth(); // Clerk, Auth0, etc.
  
  const handleAuth = async () => {
    const providerToken = await getToken();
    
    // Exchange via consumer's backend
    const response = await fetch('/api/fireproof-token', {
      headers: { Authorization: `Bearer ${providerToken}` }
    });
    const { token } = await response.json();
    
    onToken({ token, claims: decodeJwt(token) });
  };
  
  return (
    <div className="my-auth-modal">
      <h2>Sign in to continue</h2>
      <button onClick={handleAuth}>Authenticate</button>
    </div>
  );
}

// Use with Fireproof  
const strategy = new InPageReactStrategy(MyAuthComponent);
const { database } = useFireproof("mydb", { strategy });

Benefits

  1. Framework Native - Works naturally with React patterns
  2. Provider Agnostic - Consumer chooses any auth provider
  3. No Popup Blockers - Renders inline components
  4. Consistent UX - Matches application's design system
  5. Clean Separation - Fireproof handles token interface, consumer handles auth provider
  6. Backend Token Exchange - Secure server-side token exchange pattern

Implementation Details

Interface Definition

interface AuthComponentProps {
  deviceId: string;
  onToken: (token: TokenAndClaims) => void;
  onClose: () => void;
  ledger?: string;
  tenant?: string;
}

Strategy Implementation

  • open() - Render React component into DOM container
  • tryToken() - Return cached token if available
  • waitForToken() - Return Promise that resolves when component calls onToken
  • stop() - Cleanup DOM and unmount component

Token Exchange Flow

  1. Consumer's React component handles auth provider integration
  2. Component gets provider token (Clerk, Auth0, etc.)
  3. Component calls consumer's API endpoint with provider token
  4. Backend verifies provider token and exchanges for Fireproof token
  5. Component calls onToken() with Fireproof token
  6. Strategy resolves waitForToken() Promise

Migration Path

This approach moves auth provider integration (like Clerk) from the Fireproof dashboard to the consumer side, providing:

  • Better separation of concerns
  • More flexibility for consumers
  • Reduced complexity in Fireproof core
  • Provider-agnostic authentication strategy

Files to Modify

  • use-fireproof/in-page-react-strategy.ts - New strategy implementation
  • use-fireproof/index.ts - Export new strategy
  • Documentation and examples

Related

This addresses authentication UX issues while maintaining the existing TokenStrategie interface established in core/types/protocols/cloud/gateway-control.ts:19.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions