@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.