This is a custom profile page.
Wallet: {address}
return ( ) } ``` ```tsx [Solana (custom)] import { OAuthProvider, useOAuth } from "@openfort/react" import { useSolanaEmbeddedWallet } from "@openfort/react/solana" function SocialLogin() { const { initOAuth, isLoading } = useOAuth() const { isConnected, address } = useSolanaEmbeddedWallet() if (isConnected) returnWallet: {address}
return ( ) } ``` ::: :::warning One `chainType` per provider. An app cannot headlessly OAuth into both EVM and Solana from the same `OpenfortProvider` instance. ::: Working examples: * [Headless EVM quickstart](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/headless) – minimal headless EVM setup * [Headless Solana quickstart](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/solana-headless) – minimal headless Solana setup with `chainType: SVM` [View full documentation →](/docs/products/embedded-wallet/react/hooks/useOAuth) ## Using Wallet Authentication (Ethereum only) Wallet authentication (Sign-In with Ethereum, SIWE) with external wallets (MetaMask, WalletConnect, etc.) is **Ethereum-only** and requires wagmi provider setup. Full setup, provider config, and API are in [useWalletAuth](/docs/products/embedded-wallet/react/hooks/useWalletAuth). :::code-group ```tsx [Prebuilt] import { useUI } from "@openfort/react" function WalletLogin() { const { open } = useUI() return } ``` ```tsx [Custom] import { useWalletAuth } from "@openfort/react/wagmi" import { useState } from "react" function WalletLogin() { const { availableWallets, connectWallet } = useWalletAuth() const [loading, setLoading] = useState(false) const handleConnect = async (walletId: string) => { setLoading(true) try { await connectWallet(walletId, { onConnect: () => console.log("Connected"), onError: (err) => console.error(err), }) } finally { setLoading(false) } } return ( <> {availableWallets.map((w) => ( ))} > ) } ``` ::: [View full documentation →](/docs/products/embedded-wallet/react/hooks/useWalletAuth#usewalletauth-siwe-connection-flow) ## Using Guest Authentication Use [`useGuestAuth`](/docs/products/embedded-wallet/react/hooks/useGuestAuth) for anonymous users and instant onboarding. ```tsx import { useGuestAuth } from "@openfort/react" function GuestLogin() { const { signUpGuest, isLoading } = useGuestAuth() return ( ) } ``` [View full documentation →](/docs/products/embedded-wallet/react/hooks/useGuestAuth) ## Using Your Own Authentication Openfort integrates with external authentication providers like Firebase, Supabase, Auth0, and custom auth systems so you can keep your existing login flow while issuing embedded wallets for users. [View full documentation →](/docs/products/embedded-wallet/react/auth/third-party) # Using Your Own Authentication Openfort integrates with external authentication providers so you can keep your existing login while still issuing embedded wallets for users. :::warning[No UI Components with Third-Party Auth] When using third-party authentication (Firebase, Supabase, etc.), you must handle your own login UI. Openfort's built-in UI components (like `OpenfortButton`) and the `uiConfig` settings in `OpenfortProvider` do not apply—they are designed for Openfort's native authentication methods only. ::: ## Ready-Made Quickstarts Get started quickly with complete working examples that integrate third-party authentication: * [Quickstart w/ Firebase](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/firebase#firebase-quickstart) – Complete Firebase integration example * [Quickstart w/ Supabase](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/supabase#supabase-quickstart) – Complete Supabase integration example * [Quickstart w/ Better Auth](https://github.com/openfort-xyz/openfort-react/tree/main/examples/quickstarts/betterauth#better-auth-quickstart) – Complete Better Auth integration example ## Supported Providers Openfort has built-in support for these third-party authentication platforms: | Provider | Configuration | |----------|---------------| | [**Firebase**](/docs/configuration/external-auth/firebase) | `ThirdPartyOAuthProvider.FIREBASE` | | [**Better-Auth**](/docs/configuration/external-auth/better-auth) | `ThirdPartyOAuthProvider.BETTER_AUTH` | | [**Supabase**](/docs/configuration/external-auth/supabase) | `ThirdPartyOAuthProvider.SUPABASE` | | [**PlayFab**](/docs/configuration/external-auth/playfab) | `ThirdPartyOAuthProvider.PLAYFAB` | | [**AccelByte**](/docs/configuration/external-auth/accelbyte) | `ThirdPartyOAuthProvider.ACCELBYTE` | | [**LootLocker**](/docs/configuration/external-auth/lootlocker) | `ThirdPartyOAuthProvider.LOOTLOCKER` | | [**Custom OIDC**](/docs/configuration/custom-auth/oidc-token) | `ThirdPartyOAuthProvider.OIDC` | | [**Custom Auth**](/docs/configuration/custom-auth/auth-token) | `ThirdPartyOAuthProvider.CUSTOM` | ## Setup Steps ### 1. Configure Your Provider in the Dashboard Before integrating, configure your authentication provider in the [Openfort Dashboard → Providers](https://dashboard.openfort.io/providers): * **For built-in providers** (Firebase, Supabase, etc.): Add your provider's Project ID or credentials * **For OIDC providers** (Auth0, Cognito, etc.): Provide your JWKS URL and audience (`aud`) value * **For custom auth servers**: Set up a verification endpoint and authentication headers [View detailed provider setup guides →](/docs/configuration/external-auth) ### 2. Set up the `thirdPartyAuth` prop in `OpenfortProvider` Wrap your React app with `OpenfortProvider` and specify your authentication provider's `getAccessToken` function. Here's an example using Firebase: ```tsx [Providers.tsx] import React from "react" import { OpenfortProvider, RecoveryMethod, ThirdPartyOAuthProvider } from "@openfort/react" import { auth as firebaseAuth } from "./lib/firebase" export function Providers({ children }: { children: React.ReactNode }) { const firebaseGetAccessToken = async () => { const token = await firebaseAuth.currentUser?.getIdToken(false) return token ?? null } return (Address: {activeWallet.address}
Chain: Ethereum
Address: {activeWallet?.address}
Account ID: {activeWallet?.accountId}
Created at: {activeWallet?.createdAt}
Address: {activeWallet.address}
Cluster: {cluster}
Address: {activeWallet?.address}
Transfer confirmed!
} {error &&Error: {error.message}
}Transfer confirmed!
} {error &&Error: {error.message}
}Signature: {signature}
} {error &&Error: {error.message}
}Signature: {signature}
} {error &&Error: {error.message}
}Error: {error.message}
}
Status: {status}
Send to: {session.paymentMethod.receiverAddress}
{/* render session.paymentMethod.addressUri as a QR, or session.paymentMethod.deeplinks */}Please sign in first
; const handleRequestOtp = async () => { const { error } = await requestPhoneOtp({ phoneNumber }); if (!error) setOtpSent(true); }; const handleLinkPhone = async () => { const { user, error } = await linkPhoneOtp({ phoneNumber, otp }); if (user) console.log('Phone linked successfully'); }; return (Connecting to {walletConnectingTo}…
} {availableWallets.map((w) => ( ))}User ID: {user?.id}
Email: {user?.email}
Linked accounts: {linkedAccounts?.length}
Wallet: {address}
} ``` For granular UI states (loading, recovery prompts, errors) read the `status` discriminated union instead — see [Return type](#return-type). **List and switch wallets** (cluster from provider/context): ```tsx import { useSolanaEmbeddedWallet } from "@openfort/react/solana" function WalletList() { const { wallets, activeWallet, setActive, create } = useSolanaEmbeddedWallet() return (Embedded state: {embeddedState}
User ID: {user?.id}
{getStateMessage()}
; } ``` # `useGrantPermissions` Grant permissions to session keys using EIP-7715 for scoped, time-limited transactions. Both `useGrantPermissions` and `useRevokePermissions` use the Ethereum bridge directly (no SIWE dependency). External wallets (e.g. MetaMask) connected via wagmi work for session key grant/revoke. ## Usage ```tsx import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { useGrantPermissions } from '@openfort/react'; function CreateSessionKey() { const { grantPermissions, isLoading } = useGrantPermissions(); const handleCreate = async () => { const sessionKey = generatePrivateKey(); const sessionAccount = privateKeyToAccount(sessionKey); // Store the session key. You need it later to sign transactions. localStorage.setItem('sessionKey', sessionKey); const result = await grantPermissions({ sessionKey: sessionKey, request: { signer: { type: 'account', data: { id: sessionAccount.address }, }, expiry: 60 * 60 * 24, // 24 hours permissions: [ { type: 'contract-call', data: { address: '0x2522f4fc9af2e1954a3d13f7a5b2683a00a4543a', calls: [], }, policies: [], }, ], }, }); console.log('Permissions granted:', result.address); }; return ; } ``` ## Return type ```ts type UseGrantPermissionsReturn = { grantPermissions(params: GrantPermissionsParams, options?: GrantPermissionsHookOptions): Promise