Skip to content

Last1 Auth Integration - Prompt

Copy this prompt to implement the branded auth page and user sync webhook on Last1.app.


Task: Implement RadioCheck Branded Auth and User Sync

Last1 is the central authentication provider for both last1.app and RadioCheck. We need to implement:

  1. A branded auth page that can display RadioCheck branding when accessed with ?brand=radiocheck
  2. A webhook sender that notifies RadioCheck when users are created/updated

1. Branded Auth Page

Create a new route at GET /auth that supports multiple brands.

Query Parameters: - brand - "radiocheck" or "last1" (default: "last1") - redirect - URL to redirect after successful auth (required) - mode - "login" or "signup" (optional, default: "login")

Branding Configuration:

const BRAND_CONFIG = {
  last1: {
    name: 'Last1',
    logo: '/images/last1-logo.png',
    primaryColor: '#4F46E5',
    tagline: 'Supporting those who served',
  },
  radiocheck: {
    name: 'Radio Check',
    logo: 'https://radiocheck.app/logo.png', // Or host locally
    primaryColor: '#D4AF37', // Gold
    tagline: 'Never leave a veteran behind',
  },
};

Auth Page Behavior: 1. Display logo and colors based on brand parameter 2. Show login or signup form based on mode parameter 3. Authenticate user with Supabase Auth 4. On success, redirect to: {redirect}?token={access_token}&refresh_token={refresh_token}&user_id={user_id} 5. On failure, show error message with brand styling

Example URLs: - https://last1.app/auth?brand=radiocheck&redirect=https://radiocheck.app/checkout&mode=signup - https://last1.app/auth?brand=last1&redirect=https://last1.app/dashboard

Implementation Notes: - The access token should be a short-lived JWT (5 minutes) - Include user metadata in the redirect (user_id, email) - Support "Remember me" functionality for persistent sessions

2. User Sync Webhook Sender

When a user is created or updated on Last1, send a webhook to RadioCheck to sync the user.

Webhook Endpoint: POST https://<radiocheck-supabase-project>.supabase.co/functions/v1/sync-user-from-last1

Events to Send: - user.created - When a new user signs up - user.updated - When user profile is updated - user.deleted - When user account is deleted - user.email_verified - When email is verified

Webhook Payload:

interface UserWebhookPayload {
  event: 'user.created' | 'user.updated' | 'user.deleted' | 'user.email_verified';
  timestamp: string; // ISO 8601
  user_id: string;   // UUID
  email: string;
  display_name?: string;
  phone?: string;
  metadata?: {
    source?: string;        // 'last1' or 'radiocheck'
    email_verified?: boolean;
    created_at?: string;
    // Any other relevant user metadata
  };
}

Security - HMAC Signature: Sign the payload with HMAC-SHA256 using a shared secret.

import crypto from 'crypto';

function signWebhook(payload: object, secret: string): string {
  const payloadString = JSON.stringify(payload);
  return crypto
    .createHmac('sha256', secret)
    .update(payloadString)
    .digest('hex');
}

// When sending the webhook:
const payload = { event: 'user.created', ... };
const signature = signWebhook(payload, process.env.RADIOCHECK_WEBHOOK_SECRET);

await fetch(webhookUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Last1-Signature': signature,
    'X-Last1-Timestamp': new Date().toISOString(),
  },
  body: JSON.stringify(payload),
});

Implementation Options:

Option A: Supabase Database Webhook (Recommended) Use Supabase's built-in database webhooks to trigger on auth.users changes:

  1. Go to Last1 Supabase Dashboard > Database > Webhooks
  2. Create webhook for auth.users table on INSERT, UPDATE, DELETE
  3. Point to an Edge Function that formats and sends to RadioCheck

Option B: Application-Level Hook Add hooks in your auth routes:

// After successful signup
async function onUserCreated(user: User) {
  await sendWebhookToRadioCheck('user.created', user);
}

// After profile update
async function onUserUpdated(user: User) {
  await sendWebhookToRadioCheck('user.updated', user);
}

3. Environment Variables

Add to your Last1 environment:

# RadioCheck Webhook Integration
RADIOCHECK_WEBHOOK_URL=https://<radiocheck-project>.supabase.co/functions/v1/sync-user-from-last1
RADIOCHECK_WEBHOOK_SECRET=<shared-secret-from-radiocheck>

4. CORS Configuration

Ensure Last1's Supabase allows requests from radiocheck.app:

-- In Supabase SQL Editor (if needed)
-- Usually handled by Supabase automatically for auth endpoints

5. Email Templates

Update email templates to support branding:

  1. Go to Last1 Supabase Dashboard > Authentication > Email Templates
  2. Update templates to include dynamic branding based on user metadata
  3. Example: If user.user_metadata.source === 'radiocheck', use RadioCheck branding

Confirmation Email Template (example):

<h2>Welcome to {{ if .UserMetaData.source == "radiocheck" }}Radio Check{{ else }}Last1{{ end }}!</h2>
<p>Click the link below to confirm your email:</p>
<a href="{{ .ConfirmationURL }}">Confirm Email</a>


Testing

  1. Test branded auth page:
  2. Visit https://last1.app/auth?brand=radiocheck&redirect=http://localhost:3000/test
  3. Verify RadioCheck branding appears
  4. Complete signup/login flow
  5. Verify redirect with token

  6. Test webhook sync:

  7. Create a new user on Last1
  8. Check RadioCheck Supabase users table for new record
  9. Update user profile on Last1
  10. Verify changes sync to RadioCheck

Summary

After implementing this: - Users can sign up for RadioCheck via last1.app/auth with RadioCheck branding - All user accounts are stored in Last1's Supabase (single source of truth) - User data syncs to RadioCheck's Supabase via webhook - RadioCheck mobile app and radiocheck.app both authenticate against Last1