Skip to Content
GuideReact Integration
View .md

Alien Solana SSO React Integration: AlienSolanaSsoProvider Guide

This guide shows how to integrate Alien Solana SSO into React applications using the React SDK with Solana wallet adapters.

Solana SSO React Requirements

  • React 19.1.1 or higher
  • React DOM 19.1.1 or higher
  • @solana/web3.js ^1.95.0 or higher
  • @solana/wallet-adapter-react ^0.15.0 or higher
  • A modern web browser with JavaScript enabled
  • localStorage and sessionStorage support
  • A registered provider from the dev portal, with provider address

Install Alien Solana SSO React Package

npm install @alien-id/sso-solana-react @solana/web3.js @solana/wallet-adapter-react

The React SDK requires Solana wallet adapter packages as peer dependencies.

Wrap Your App with AlienSolanaSsoProvider

Alien Solana SSO Provider

Wrap your app with both wallet adapter providers and AlienSolanaSsoProvider:

import { AlienSolanaSsoProvider } from '@alien-id/sso-solana-react'; function App() { return ( <WalletContextProvider> <AlienSolanaSsoProvider config={{ ssoBaseUrl: 'https://sso.alien.com', providerAddress: 'your-provider-address' }} > <YourApp /> </AlienSolanaSsoProvider> </WalletContextProvider> ); } export default App;

Configuration Options

  • ssoBaseUrl (required): Base URL of the SSO service
  • providerAddress (required): Your provider address from dev portal
  • pollingInterval (optional): Polling interval in milliseconds (default: 5000)
  • credentialSignerProgramId (optional): Credential Signer program ID
  • sessionRegistryProgramId (optional): Session Registry program ID
  • sasProgramId (optional): SAS program ID

Use the useSolanaAuth Hook

The useSolanaAuth() hook provides access to Solana authentication state and methods.

import { useSolanaAuth } from '@alien-id/sso-solana-react'; function Dashboard() { const { auth, wallet, logout } = useSolanaAuth(); if (!auth.sessionAddress) { return <div>Not authenticated</div>; } return ( <div> <p>Wallet: {wallet.publicKey?.toBase58()}</p> <p>Session: {auth.sessionAddress}</p> <button onClick={logout}>Logout</button> </div> ); }

Auth State

The auth object contains:

{ sessionAddress: string | null; }

Available Properties and Methods

const { client, // Direct access to AlienSolanaSsoClient instance auth, // Authentication state wallet, // Solana wallet adapter connectionAdapter, // Solana connection from context queryClient, // React Query client instance generateDeeplink, // Generate authentication deep link pollAuth, // Poll for authentication status verifyAttestation, // Verify on-chain attestation logout, // Clear authentication state openModal, // Open built-in Solana sign-in modal closeModal, // Close sign-in modal isModalOpen // Modal open state } = useSolanaAuth();

Using Pre-built Components

SolanaSignInButton

A pre-styled button that opens the Solana sign-in modal.

import { SolanaSignInButton } from '@alien-id/sso-solana-react'; import { useWallet } from '@solana/wallet-adapter-react'; import { WalletMultiButton } from '@solana/wallet-adapter-react-ui'; function LoginPage() { const { connected } = useWallet(); if (!connected) { return ( <div> <h1>Connect Your Wallet</h1> <WalletMultiButton /> </div> ); } return ( <div> <h1>Sign In with Alien</h1> <SolanaSignInButton /> </div> ); }

SolanaSignInModal

The modal is automatically rendered by AlienSolanaSsoProvider and handles:

  • QR code display
  • Polling for authentication
  • Transaction building and signing
  • On-chain attestation creation

Control it via the useSolanaAuth() hook:

import { useSolanaAuth } from '@alien-id/sso-solana-react'; function CustomButton() { const { openModal } = useSolanaAuth(); return <button onClick={openModal}>Sign In</button>; }

Complete Example

import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'; import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui'; import { AlienSolanaSsoProvider, useSolanaAuth, SolanaSignInButton } from '@alien-id/sso-solana-react'; import { useWallet } from '@solana/wallet-adapter-react'; import { clusterApiUrl } from '@solana/web3.js'; import { useMemo } from 'react'; import '@solana/wallet-adapter-react-ui/styles.css'; function App() { const endpoint = useMemo(() => clusterApiUrl('mainnet-beta'), []); return ( <ConnectionProvider endpoint={endpoint}> <WalletProvider wallets={[]} autoConnect> <WalletModalProvider> <AlienSolanaSsoProvider config={{ ssoBaseUrl: 'https://sso.alien.com', providerAddress: 'your-provider-address', }} > <Dashboard /> </AlienSolanaSsoProvider> </WalletModalProvider> </WalletProvider> </ConnectionProvider> ); } function Dashboard() { const { connected } = useWallet(); const { auth, logout } = useSolanaAuth(); if (!connected) { return ( <div> <h1>Connect Wallet</h1> <WalletMultiButton /> </div> ); } if (!auth.sessionAddress) { return ( <div> <h1>Sign In</h1> <SolanaSignInButton /> </div> ); } return ( <div> <h1>Dashboard</h1> <p>Session: {auth.sessionAddress}</p> <button onClick={logout}>Logout</button> </div> ); } export default App;

Custom Authentication Flow

If you want to implement a custom UI:

import { useSolanaAuth } from '@alien-id/sso-solana-react'; import { useWallet } from '@solana/wallet-adapter-react'; import { useState, useEffect } from 'react'; import QRCode from 'react-qr-code'; function CustomAuth() { const { wallet, generateDeeplink, pollAuth } = useSolanaAuth(); const [deepLink, setDeepLink] = useState<string | null>(null); const [pollingCode, setPollingCode] = useState<string | null>(null); const handleSignIn = async () => { if (!wallet.publicKey) return; const response = await generateDeeplink(wallet.publicKey.toBase58()); setDeepLink(response.deep_link); setPollingCode(response.polling_code); }; useEffect(() => { if (!pollingCode) return; const interval = setInterval(async () => { const response = await pollAuth(pollingCode); if (response.status === 'authorized') { clearInterval(interval); // The provider will automatically handle transaction creation and signing setDeepLink(null); setPollingCode(null); } else if (response.status === 'rejected' || response.status === 'expired') { clearInterval(interval); alert(`Authentication ${response.status}`); setDeepLink(null); setPollingCode(null); } }, 5000); return () => clearInterval(interval); }, [pollingCode, pollAuth]); if (deepLink) { return ( <div> <h2>Scan QR Code</h2> <QRCode value={deepLink} /> </div> ); } return <button onClick={handleSignIn}>Sign In with Alien</button>; }

Protected Routes

Create a protected route component:

import { useSolanaAuth } from '@alien-id/sso-solana-react'; import { useWallet } from '@solana/wallet-adapter-react'; import { Navigate } from 'react-router-dom'; function ProtectedRoute({ children }: { children: React.ReactNode }) { const { connected } = useWallet(); const { auth } = useSolanaAuth(); if (!connected) { return <Navigate to="/connect-wallet" />; } if (!auth.sessionAddress) { return <Navigate to="/sign-in" />; } return <>{children}</>; } // Usage <Route path="/dashboard" element={ <ProtectedRoute> <Dashboard /> </ProtectedRoute> } />

Grace Period Mechanism

The Solana provider implements a 60-second grace period after attestation creation to handle RPC indexing delays:

// After successful attestation creation // Session address is cached for 60 seconds // verifyAttestation() returns cached value immediately // Background verification runs after grace period expires

Storage keys:

  • alien-sso_solana_authed_address - Authenticated Solana address
  • alien-sso_session_address - Session address
  • alien-sso_attestation_created_at - Timestamp of attestation creation

Verifying Attestation on Mount

import { useSolanaAuth } from '@alien-id/sso-solana-react'; import { useWallet } from '@solana/wallet-adapter-react'; import { useEffect, useState } from 'react'; function App() { const { wallet } = useWallet(); const { verifyAttestation, auth } = useSolanaAuth(); const [isVerifying, setIsVerifying] = useState(true); useEffect(() => { const verify = async () => { if (wallet.publicKey) { await verifyAttestation(wallet.publicKey.toBase58()); } setIsVerifying(false); }; verify(); }, [wallet.publicKey]); if (isVerifying) { return <div>Verifying authentication...</div>; } return auth.sessionAddress ? <Dashboard /> : <LoginPage />; }

TypeScript Support

The React SDK is fully typed:

import type { SolanaAuthState, AlienSolanaSsoClient } from '@alien-id/sso-solana-react'; const auth: SolanaAuthState = useSolanaAuth().auth; const client: AlienSolanaSsoClient = useSolanaAuth().client;

Next Steps

Last updated on