A Xero OAuth 2.0 prototype built with Next.js, xero-node SDK, and Supabase to meet Xero's Practice Manager scope application requirements.
- ✅ Xero OAuth 2.0 authentication flow (using xero-node SDK)
- ✅ Encrypted token storage (AES-256-GCM)
- ✅ Supabase database integration
- ✅ Automatic token refresh
- ✅ Connection management (via updateTenants())
- Next.js 14 (App Router, TypeScript)
- xero-node (Official Xero SDK)
- Supabase (PostgreSQL + encrypted storage)
- Node.js crypto (AES-256-GCM encryption)
pnpm installCopy env.example to .env.local and fill in your configuration:
cp env.example .env.localRequired variables:
XERO_CLIENT_ID: Your Xero application client IDXERO_CLIENT_SECRET: Your Xero application client secretXERO_REDIRECT_URI: Callback URL (http://localhost:3000/api/xero/callback)XERO_TOKEN_ENC_KEY: 32-byte Base64 encryption keySUPABASE_URL: Your Supabase project URLSUPABASE_SERVICE_ROLE_KEY: Supabase service role key
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"Run the SQL statements in supabase-schema.sql file in the Supabase SQL editor.
pnpm devVisit http://localhost:3000 to get started.
- Click "Connect to Xero" button
- Complete Xero OAuth authentication
- System automatically saves encrypted tokens to Supabase
- View connection information and organization data
GET /api/xero/connect- Start OAuth flow (XPM-only scopes)GET /api/xpm/connect- Explicit XPM-only consentGET /api/xero/callback- OAuth callback handlingGET /api/xero/demo?tenantId=xxx- Get connections via /connectionsGET /api/xpm/invoices?tenantId=xxx&from=YYYY-MM-DD&to=YYYY-MM-DD- XPM invoices
- 🔒 Tokens encrypted and stored in Supabase
- 🔒 Service role key used only on server-side
- 🔒 Automatic token refresh
- 🔒 Row-level security policies
src/
├── app/
│ ├── api/xero/
│ │ ├── connect/route.ts # OAuth connection endpoint
│ │ ├── callback/route.ts # OAuth callback handling
│ │ └── demo/route.ts # Demo API
│ ├── xero/connected/
│ │ └── page.tsx # Connection success page
│ └── page.tsx # Main page
└── lib/
├── crypto.ts # Encryption utilities
├── supabaseAdmin.ts # Supabase admin client
└── xero.ts # Xero client and token management
- Ensure your Xero application has the correct redirect URI configured
- Current base scopes:
openid profile email offline_access accounting.settings - After Practice Manager scope approval, add
practicemanagerscope - All sensitive information managed through environment variables
- Encryption key error: Ensure
XERO_TOKEN_ENC_KEYis a 32-byte Base64 string - Supabase connection failed: Check
SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEY - Xero authentication failed: Verify
XERO_CLIENT_ID,XERO_CLIENT_SECRET, andXERO_REDIRECT_URI