Skip to main content
@lit-protocol/login-modal is currently experimental and focuses on a minimal, modular API. Expect breaking changes as it hardens.

Install

npm i @lit-protocol/login-modal

Quickstart

Wrap your app with LitAuthProvider, then call showAuthModal() when you want to prompt login.
import { LitAuthProvider, useLitAuth } from "@lit-protocol/login-modal";

function App() {
  const { isAuthenticated, showAuthModal, logout, user } = useLitAuth();

  return (
    <div>
      {isAuthenticated ? (
        <>
          <pre>{JSON.stringify(user?.pkpInfo, null, 2)}</pre>
          <button onClick={logout}>Logout</button>
        </>
      ) : (
        <button onClick={showAuthModal}>Sign in</button>
      )}
    </div>
  );
}

export default function Root() {
  return (
    <LitAuthProvider appName="my-app" enabledAuthMethods={["eoa"]}>
      <App />
    </LitAuthProvider>
  );
}

Auth services (required for non-EOA methods)

If you enable any auth method other than eoa, you must provide:
  • services.authServiceUrls (per network)
  • services.loginServerUrl (Google/Discord)
  • services.discordClientId (Discord)
import { LitAuthProvider } from "@lit-protocol/login-modal";

export function Root() {
  return (
    <LitAuthProvider
      appName="my-app"
      supportedNetworks={["naga-dev", "naga-test", "naga-proto", "naga"]}
      enabledAuthMethods={["eoa", "google", "discord", "webauthn"]}
      services={{
        authServiceUrls: {
          "naga-dev": "https://naga-dev-auth-service.getlit.dev",
          "naga-test": "https://naga-test-auth-service.getlit.dev",
          "naga-proto": "https://naga-proto-auth-service.getlit.dev",
          naga: "https://naga-auth-service.getlit.dev",
        },
        // Optional: required only if your Auth Service gates requests.
        authServiceApiKey: "YOUR_OPTIONAL_API_KEY",
        loginServerUrl: "https://login.litgateway.com",
        discordClientId: "YOUR_DISCORD_CLIENT_ID",
      }}
    >
      {/* ... */}
    </LitAuthProvider>
  );
}

EOA wallet provider integration (RainbowKit / Wagmi, etc.)

By default, the EOA flow uses window.ethereum. If your app uses a wallet framework (Wagmi, WalletConnect, custom EIP-1193 provider), pass an EOA wallet provider so the modal can authenticate with the already connected wallet client.
import { ConnectButton } from "@rainbow-me/rainbowkit";
import { useWalletClient } from "wagmi";
import { LitAuthProvider } from "@lit-protocol/login-modal";

export function Root() {
  const { data: walletClient } = useWalletClient();

  return (
    <LitAuthProvider
      appName="my-app"
      enabledAuthMethods={["eoa"]}
      eoa={{
        getWalletClient: async () => {
          if (!walletClient) throw new Error("Connect a wallet first.");
          return walletClient;
        },
        renderConnect: () => <ConnectButton showBalance={false} />,
      }}
    >
      {/* ... */}
    </LitAuthProvider>
  );
}

Any EIP-1193 provider (WalletConnect / Web3Modal / Privy / Dynamic, etc.)

If your connection layer gives you an EIP-1193 provider, you can adapt it to the modal using createEoaWalletProvider.
import { LitAuthProvider, createEoaWalletProvider } from "@lit-protocol/login-modal";

export function Root() {
  const eoa = createEoaWalletProvider({
    getEip1193Provider: async () => {
      // Return the connected EIP-1193 provider from your wallet stack.
      // For injected wallets, this could be `window.ethereum`.
      return window.ethereum!;
    },
    // Optional connect UI:
    // renderConnect: () => <YourConnectButton />,
  });

  return (
    <LitAuthProvider appName="my-app" enabledAuthMethods={["eoa"]} eoa={eoa}>
      {/* ... */}
    </LitAuthProvider>
  );
}

Minting PKPs (EOA vs Auth Service)

  • EOA (enabledAuthMethods includes eoa): minting is on-chain by default (no Auth Service). The user’s connected wallet signs the transaction, so it must have gas / test tokens.
    • Optional: if you run an Auth Service, the modal can also do a sponsored mint via POST /pkp/mint (useful when the user has no gas). This requires services.authServiceUrls (and services.authServiceApiKey if your Auth Service gates requests).
  • Non-EOA methods (Google/Discord/WebAuthn/Stytch, etc.): minting happens via the Auth Service (POST /pkp/mint), so you must provide services.authServiceUrls (and any required API key configuration).

Custom UI

Use components to override specific parts of the modal:
  • components.PkpSelection: replace the default PKP selection UI
  • components.FundingPanel: replace the default Ledger funding UI
This is how the Explorer app customises the PKP selection and funding experiences.