Authentication
Learn how to authenticate and secure your pxlpeak account with API keys, OAuth, SSO, and multi-factor authentication.
Overview
pxlpeak provides multiple authentication methods to secure your account and API access. This guide covers user account creation, API key management, OAuth integration, SSO configuration, and security best practices.
User Account Sign-Up
Sign-Up Methods
pxlpeak supports three methods for creating user accounts:
- Email & Password - Traditional email-based registration
- Google OAuth - Sign up with Google account
- GitHub OAuth - Sign up with GitHub account
Email & Password Sign-Up
Password Requirements
For security, passwords must meet the following requirements:
- Minimum 8 characters (recommended: 12+)
- At least one uppercase letter (A-Z)
- At least one lowercase letter (a-z)
- At least one number (0-9)
- At least one special character (!@#$%^&*()_+-=[]|;:,.<>?)
Sign-Up Flow
// Client-side sign-up form
import { signUpWithEmail } from '@/lib/supabase/actions';
const result = await signUpWithEmail(
'user@example.com',
'SecurePassword123!',
'John Doe' // Optional full name
);
if (result.error) {
// Handle error (e.g., email already exists, weak password)
console.error(result.error);
} else {
// Success - user receives confirmation email
console.log(result.message);
// "Check your email for a confirmation link."
}Email Verification
After signing up:
- User receives a confirmation email with a verification link
- User clicks the link to verify their email address
- User is redirected to
/auth/callbackand automatically signed in - User profile is created in the database
Validation & Security
Client-Side Validation:
- Real-time email format validation
- Password strength indicator
- Password confirmation matching
- Field-level error messages
Server-Side Validation:
- Email sanitization and format validation
- Password strength enforcement (Zod schema)
- Input sanitization (XSS protection)
- Rate limiting (prevents abuse)
Security Features:
- Passwords are hashed using bcrypt (handled by Supabase)
- Email addresses are normalized (lowercase, trimmed)
- Full names are sanitized to prevent injection
- All inputs are validated against Zod schemas
OAuth Sign-Up (Google/GitHub)
OAuth sign-up provides a faster, passwordless registration experience:
// Google sign-up
import { signInWithGoogle } from '@/lib/supabase/actions';
await signInWithGoogle();
// User is redirected to Google OAuth consent screen
// After approval, redirected back to /auth/callbackOAuth Benefits:
- No password to remember
- Faster registration (one click)
- Enhanced security (managed by OAuth provider)
- Automatic profile data sync (name, avatar)
Sign-Up Form Features
The sign-up form includes:
- Real-time validation - Instant feedback on input errors
- Password visibility toggle - Show/hide password fields
- Password strength meter - Visual indicator of password strength
- Accessibility - Full ARIA labels, keyboard navigation, screen reader support
- Error handling - Clear, actionable error messages
- Analytics tracking - Sign-up events tracked for conversion analysis
Account Types
After sign-up, users are assigned a role:
| Role | Description | Access Level |
|------|-------------|--------------|
| customer | End-user account | Customer portal access |
| team_member | Agency team member | Admin dashboard access |
| admin | Agency administrator | Full system access |
Roles are assigned automatically based on:
- Sign-up method (OAuth vs email)
- Invitation links (if applicable)
- Admin configuration
Troubleshooting Sign-Up
| Issue | Solution | |-------|----------| | Email already registered | Use "Sign in" instead, or reset password | | Weak password rejected | Ensure password meets all requirements | | Confirmation email not received | Check spam folder, verify email address | | OAuth redirect fails | Check browser popup blockers, cookies enabled | | Validation errors | Review field-level error messages |
Authentication Methods
pxlpeak Authentication Options:
┌─────────────────────────────────────────────────────────────┐
│ Authentication Layer │
├─────────────┬─────────────┬─────────────┬─────────────────┤
│ API Keys │ OAuth │ SSO │ MFA │
│ (Server) │ (Apps) │ (Enterprise)│ (All users) │
├─────────────┼─────────────┼─────────────┼─────────────────┤
│ Server-side │ Third-party │ SAML 2.0 │ TOTP apps │
│ integrations│ applications│ OIDC │ SMS backup │
│ Webhooks │ User auth │ Google SSO │ Recovery codes │
│ SDKs │ OAuth 2.0 │ Okta, Azure │ Hardware keys │
└─────────────┴─────────────┴─────────────┴─────────────────┘API Key Authentication
Types of API Keys
| Key Type | Prefix | Use Case | Permissions |
|----------|--------|----------|-------------|
| Public Key | pk_ | Client-side tracking | Write events only |
| Secret Key | sk_ | Server-side API | Full API access |
| Restricted Key | rk_ | Limited operations | Custom permissions |
Generating API Keys
// Navigate to Dashboard → Settings → API Keys
// Or use the API:
const apiKey = await pxlpeak.admin.createApiKey({
name: 'Production Server Key',
type: 'secret',
// Permissions (for restricted keys)
permissions: [
'events:write',
'users:read',
'analytics:read',
'leads:read',
'leads:write'
],
// Optional restrictions
restrictions: {
ipAllowlist: ['192.168.1.0/24', '10.0.0.1'],
rateLimitOverride: 1000, // requests per minute
expiresAt: '2027-01-01T00:00:00Z'
},
// Environment
environment: 'production' // production, staging, development
});
console.log(apiKey);
// {
// id: 'key_abc123',
// name: 'Production Server Key',
// key: 'sk_live_xxxxxxxxxxxxxxxxxxxxx', // Only shown once!
// type: 'secret',
// createdAt: '2026-01-12T10:00:00Z',
// permissions: ['events:write', 'users:read', ...],
// restrictions: { ... }
// }Using API Keys
// Server-side: Include in Authorization header
const response = await fetch('https://api.pxlpeak.com/v1/events', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PXLPEAK_SECRET_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'purchase_completed',
userId: 'user_123',
properties: { revenue: 99.99 }
})
});
// Using the SDK
import { Pxlpeak } from '@pxlpeak/node';
const pxlpeak = new Pxlpeak({
secretKey: process.env.PXLPEAK_SECRET_KEY
});
await pxlpeak.track({
event: 'purchase_completed',
userId: 'user_123',
properties: { revenue: 99.99 }
});Client-Side Authentication
// Browser tracking uses public keys
import { init } from '@pxlpeak/tracker';
init({
publicKey: 'pk_live_xxxxxxxxxxxxxxxxxxxxx', // Safe to expose
// Options
});
// Public keys can only:
// - Track events
// - Identify users
// - Set user properties
// They CANNOT:
// - Read data
// - Access admin APIs
// - Modify configurationsKey Rotation
// Rotate API keys without downtime
const rotationResult = await pxlpeak.admin.rotateApiKey({
keyId: 'key_abc123',
// Grace period: both old and new keys work
gracePeriod: '24h',
// Notification
notifyOnOldKeyUsage: true,
notificationEmail: 'security@company.com'
});
// {
// newKey: 'sk_live_yyyyyyyyyyyyyyy',
// oldKeyExpiresAt: '2026-01-13T10:00:00Z',
// status: 'rotating'
// }OAuth 2.0 Authentication
Registering an OAuth Application
// Create OAuth app for third-party integrations
const oauthApp = await pxlpeak.admin.createOAuthApp({
name: 'My Integration App',
description: 'Syncs data between pxlpeak and my app',
// Redirect URIs (whitelist)
redirectUris: [
'https://myapp.com/auth/callback',
'https://localhost:3000/auth/callback'
],
// Requested scopes
scopes: [
'read:analytics',
'write:events',
'read:leads',
'read:campaigns'
],
// App type
type: 'confidential', // confidential (server) or public (SPA/mobile)
// Token settings
tokenSettings: {
accessTokenTTL: 3600, // 1 hour
refreshTokenTTL: 2592000, // 30 days
allowRefreshToken: true
}
});
// {
// clientId: 'client_xxxxxxxxxxxxx',
// clientSecret: 'secret_xxxxxxxxxxxxx', // Only for confidential apps
// ...
// }OAuth Authorization Flow
// 1. Redirect user to authorization URL
const authUrl = pxlpeak.oauth.getAuthorizationUrl({
clientId: 'client_xxxxxxxxxxxxx',
redirectUri: 'https://myapp.com/auth/callback',
scopes: ['read:analytics', 'write:events'],
state: generateSecureState(), // CSRF protection
codeChallenge: generateCodeChallenge(), // PKCE for public apps
codeChallengeMethod: 'S256'
});
// Redirect user to authUrl
// https://www.pxlpeak.com/oauth/authorize?client_id=...&redirect_uri=...&scope=...
// 2. Handle callback
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query;
// Verify state matches
if (state !== getStoredState()) {
return res.status(400).json({ error: 'Invalid state' });
}
// 3. Exchange code for tokens
const tokens = await pxlpeak.oauth.exchangeCode({
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
code: code,
redirectUri: 'https://myapp.com/auth/callback',
codeVerifier: getStoredCodeVerifier() // For PKCE
});
// {
// accessToken: 'at_xxxxxxxxxxxxx',
// refreshToken: 'rt_xxxxxxxxxxxxx',
// expiresIn: 3600,
// tokenType: 'Bearer',
// scope: 'read:analytics write:events'
// }
// Store tokens securely
await storeTokens(tokens);
res.redirect('/dashboard');
});
// 4. Use access token for API calls
const response = await fetch('https://api.pxlpeak.com/v1/analytics', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
// 5. Refresh tokens when expired
const newTokens = await pxlpeak.oauth.refreshToken({
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
refreshToken: storedRefreshToken
});OAuth Scopes
| Scope | Description |
|-------|-------------|
| read:analytics | Read analytics data and reports |
| write:events | Track events and conversions |
| read:leads | Access lead profiles and scores |
| write:leads | Create and update leads |
| read:campaigns | View campaign data |
| write:campaigns | Create and modify campaigns |
| read:users | Access user information |
| admin:organization | Organization-level admin access |
Single Sign-On (SSO)
SAML 2.0 Configuration
// Configure SAML SSO (Enterprise plan)
const samlConfig = await pxlpeak.sso.configureSAML({
// Identity Provider settings
idp: {
entityId: 'https://idp.company.com',
ssoUrl: 'https://idp.company.com/sso/saml',
sloUrl: 'https://idp.company.com/sso/logout', // Optional
certificate: `-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1...
-----END CERTIFICATE-----`
},
// Attribute mapping
attributeMapping: {
email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
firstName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname',
lastName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
groups: 'http://schemas.xmlsoap.org/claims/Group'
},
// Role mapping from IdP groups
roleMapping: {
'pxlpeak-admins': 'admin',
'pxlpeak-editors': 'editor',
'pxlpeak-viewers': 'viewer'
},
// Options
options: {
enforceSSO: true, // Require SSO for all users
allowIdpInitiated: true,
signAuthnRequests: true,
wantAssertionsSigned: true,
wantMessagesSigned: false
}
});
// pxlpeak Service Provider metadata
console.log(samlConfig.spMetadata);
// {
// entityId: 'https://www.pxlpeak.com/sso/saml/org_xxx',
// acsUrl: 'https://www.pxlpeak.com/sso/saml/org_xxx/acs',
// sloUrl: 'https://www.pxlpeak.com/sso/saml/org_xxx/slo',
// metadataUrl: 'https://www.pxlpeak.com/sso/saml/org_xxx/metadata'
// }OpenID Connect (OIDC)
// Configure OIDC SSO
const oidcConfig = await pxlpeak.sso.configureOIDC({
// Provider settings
provider: {
issuer: 'https://accounts.google.com',
// Or discovery URL for auto-configuration
discoveryUrl: 'https://accounts.google.com/.well-known/openid-configuration',
// Manual configuration (if not using discovery)
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
tokenEndpoint: 'https://oauth2.googleapis.com/token',
userInfoEndpoint: 'https://openidconnect.googleapis.com/v1/userinfo',
jwksUri: 'https://www.googleapis.com/oauth2/v3/certs'
},
// Client credentials
clientId: process.env.OIDC_CLIENT_ID,
clientSecret: process.env.OIDC_CLIENT_SECRET,
// Scopes
scopes: ['openid', 'profile', 'email'],
// Claim mapping
claimMapping: {
email: 'email',
firstName: 'given_name',
lastName: 'family_name',
picture: 'picture'
},
// Options
options: {
enforceSSO: false, // Allow both SSO and password login
autoCreateUsers: true,
defaultRole: 'viewer'
}
});Pre-built SSO Integrations
// Quick setup for common providers
// Google Workspace
await pxlpeak.sso.enableGoogle({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
hostedDomain: 'company.com', // Restrict to domain
autoCreateUsers: true
});
// Microsoft Azure AD
await pxlpeak.sso.enableAzureAD({
clientId: process.env.AZURE_CLIENT_ID,
clientSecret: process.env.AZURE_CLIENT_SECRET,
tenantId: process.env.AZURE_TENANT_ID,
autoCreateUsers: true
});
// Okta
await pxlpeak.sso.enableOkta({
domain: 'company.okta.com',
clientId: process.env.OKTA_CLIENT_ID,
clientSecret: process.env.OKTA_CLIENT_SECRET,
autoCreateUsers: true
});Multi-Factor Authentication
Enabling MFA for Users
// Enable MFA (TOTP)
const mfaSetup = await pxlpeak.auth.enableMFA({
method: 'totp',
userId: 'user_current'
});
// Returns setup data
// {
// secret: 'JBSWY3DPEHPK3PXP',
// qrCodeUrl: 'otpauth://totp/pxlpeak:user@company.com?secret=...',
// qrCodeImage: 'data:image/png;base64,...',
// backupCodes: ['abc123', 'def456', ...] // 10 codes
// }
// User scans QR code with authenticator app (Google Auth, Authy, etc.)
// Verify setup with a code from the app
await pxlpeak.auth.verifyMFA({
code: '123456'
});MFA Login Flow
// Login with MFA
const loginResult = await pxlpeak.auth.login({
email: 'user@company.com',
password: 'secure_password'
});
if (loginResult.requiresMFA) {
// Prompt user for MFA code
const mfaCode = await promptUserForMFACode();
const session = await pxlpeak.auth.verifyMFALogin({
mfaToken: loginResult.mfaToken,
code: mfaCode
});
// Session created, user is now authenticated
}Organization-Wide MFA
// Enforce MFA for all organization members
await pxlpeak.admin.enforceMFA({
organizationId: 'org_xxx',
// Enforcement options
enforcement: {
required: true,
gracePeriod: '7d', // Users have 7 days to set up MFA
allowedMethods: ['totp', 'sms', 'hardware_key'],
bypassForEmergency: true
},
// Notifications
notifications: {
notifyUsers: true,
reminderDays: [7, 3, 1]
}
});Session Management
Session Configuration
// Configure session settings
await pxlpeak.admin.configureSession({
// Session duration
sessionDuration: '8h', // Default session length
maxSessionDuration: '30d', // Maximum with "remember me"
rememberMeDuration: '30d',
// Security settings
security: {
singleSession: false, // Allow multiple concurrent sessions
logoutOnPasswordChange: true,
logoutOnRoleChange: true,
reauthenticateForSensitiveActions: true,
reauthenticateTimeout: '15m'
},
// Idle timeout
idle: {
enabled: true,
timeout: '30m',
warningBefore: '5m'
},
// IP restrictions
ipRestrictions: {
enabled: false,
allowlist: ['192.168.1.0/24'],
blocklist: []
}
});Active Sessions
// List user's active sessions
const sessions = await pxlpeak.auth.getSessions();
// [
// {
// id: 'session_abc',
// device: 'Chrome on macOS',
// location: 'San Francisco, CA',
// ip: '192.168.1.100',
// lastActive: '2026-01-12T10:30:00Z',
// createdAt: '2026-01-10T08:00:00Z',
// current: true
// },
// ...
// ]
// Revoke a session
await pxlpeak.auth.revokeSession('session_xyz');
// Revoke all sessions (except current)
await pxlpeak.auth.revokeAllSessions({ exceptCurrent: true });Security Best Practices
API Key Security
## API Key Checklist
### Storage
- [ ] NEVER commit API keys to version control
- [ ] Use environment variables for all keys
- [ ] Use secret managers (AWS Secrets Manager, HashiCorp Vault)
- [ ] Encrypt keys at rest
### Access
- [ ] Use least-privilege principle (restricted keys)
- [ ] Set IP allowlists for production keys
- [ ] Set expiration dates on keys
- [ ] Rotate keys regularly (every 90 days)
### Monitoring
- [ ] Enable key usage alerts
- [ ] Monitor for unusual activity
- [ ] Log all API key operations
- [ ] Set up rate limit alertsEnvironment Variables
# .env (local development - NEVER commit)
PXLPEAK_PUBLIC_KEY=pk_test_xxxxxxxxxxxxx
PXLPEAK_SECRET_KEY=sk_test_xxxxxxxxxxxxx
# Production (use secret manager)
# AWS Secrets Manager, HashiCorp Vault, etc.// Next.js environment setup
// next.config.js
module.exports = {
env: {
// Public key - safe for client
NEXT_PUBLIC_PXLPEAK_KEY: process.env.PXLPEAK_PUBLIC_KEY,
}
};
// Server-side only (API routes, getServerSideProps)
const secretKey = process.env.PXLPEAK_SECRET_KEY;Audit Logging
// Authentication events are automatically logged
// Access logs at: Dashboard → Settings → Security → Audit Log
const auditLogs = await pxlpeak.admin.getAuditLogs({
eventTypes: [
'auth.login',
'auth.logout',
'auth.mfa_enabled',
'auth.mfa_disabled',
'auth.password_changed',
'auth.api_key_created',
'auth.api_key_revoked',
'auth.session_revoked'
],
dateRange: {
start: '2026-01-01',
end: '2026-01-31'
},
userId: 'user_xxx' // Optional filter
});Troubleshooting
Common Authentication Errors
| Error Code | Description | Solution |
|------------|-------------|----------|
| auth/invalid-key | Invalid API key | Verify key is correct and not expired |
| auth/key-expired | API key has expired | Generate new key or remove expiration |
| auth/insufficient-permissions | Key lacks required permissions | Use key with correct scopes |
| auth/rate-limited | Too many requests | Wait and retry, or increase limit |
| auth/ip-blocked | IP not in allowlist | Add IP to allowlist or remove restriction |
| auth/mfa-required | MFA verification needed | Complete MFA verification |
| auth/session-expired | Session has expired | Re-authenticate |
Debugging Authentication
// Enable debug mode for authentication issues
pxlpeak.debug.auth({
enabled: true,
logLevel: 'verbose',
// What to log
log: {
requests: true,
headers: true,
responses: true,
errors: true
}
});
// Verify API key
const keyInfo = await pxlpeak.auth.verifyKey(apiKey);
// {
// valid: true,
// type: 'secret',
// permissions: ['events:write', ...],
// restrictions: { ... },
// expiresAt: null
// }Related Documentation: