> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cfosilvia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Discourse integration

# Discourse Integration Guide

This guide explains how to integrate Discourse (community forum) with Silvia, allowing users to log in to the forum using their Silvia account.

## Overview

Silvia implements **Discourse Connect** (formerly DiscourseConnect SSO) to enable single sign-on between the Silvia app and the Discourse forum. When users click "Login" on the forum, they're redirected to Silvia for authentication, then automatically logged in to Discourse.

## Architecture

```
User clicks "Login" on Discourse (community.cfosilvia.com)
    ↓
Discourse redirects to: https://www.cfosilvia.com/api/discourse/sso?sso=[payload]&sig=[signature]
    ↓
Silvia verifies signature and checks if user is logged in
    ↓
If not logged in: redirect to /sign-in
If logged in: build response with user data
    ↓
Silvia signs response and redirects back to Discourse
    ↓
Discourse verifies signature and creates/updates user account
    ↓
User is logged in to Discourse (community.cfosilvia.com)
```

## Setup Instructions

### 1. Generate SSO Secret

Generate a strong random secret (32+ characters):

```bash theme={null}
openssl rand -hex 32
```

Save this secret - you'll need it in both Discourse and Silvia.

### 2. Configure Environment Variables

Add these to your `.env` file:

```env theme={null}
# Discourse SSO Integration
DISCOURSE_SSO_SECRET=your_generated_secret_here
DISCOURSE_URL=https://community.cfosilvia.com
```

### 3. Configure Discourse Settings

In your Discourse admin panel (Settings → Login), configure:

**Required Settings:**

* ✅ `enable discourse connect` - Enable this to activate SSO
* `discourse connect url` - Set to: `https://www.cfosilvia.com/api/discourse/sso`
* `discourse connect secret` - Use the same secret from step 1

**Recommended Settings:**

* ✅ `discourse connect overrides email` - Silvia email takes precedence
* ✅ `discourse connect overrides username` - Silvia username takes precedence
* ✅ `discourse connect overrides name` - Silvia name takes precedence
* ✅ `discourse connect overrides avatar` - Silvia avatar takes precedence

**Optional Settings:**

* ✅ `invite only` - Require users to have a Silvia account
* ✅ `verbose discourse connect logging` - Enable during testing for detailed SSO logs
* `discourse connect allows all return paths` - Allow redirects to any Discourse path
* `logout redirect` - Set to `https://www.cfosilvia.com/api/discourse/logout` for logout sync

### 4. Deploy to Production

Add the same environment variables to your Vercel project:

1. Go to Vercel Dashboard → Your Project → Settings → Environment Variables
2. Add:
   * `DISCOURSE_SSO_SECRET` = Your generated secret
   * `DISCOURSE_URL` = `https://community.cfosilvia.com`
3. Redeploy your application

### 5. Test the Integration

1. **Log out** of both Silvia and Discourse
2. **Navigate** to your Discourse forum: [https://community.cfosilvia.com](https://community.cfosilvia.com)
3. **Click "Login"** - you'll be redirected to the custom community sign-in page at `/community-signin`
4. **Sign in** with your credentials (or create an account)
5. **Verify** you're automatically redirected back to Discourse and logged in

**Note:** The forum is private until you publicly announce it, so you can safely test in production.

**Custom Sign-In Page:** Users who aren't logged in will see a branded community sign-in page at `/community-signin` with:

* Custom welcome message and community branding
* List of community benefits
* Clerk authentication component
* Seamless redirect back to the forum after login

### 6. Verify User Data Sync

Check that the following data syncs correctly:

* ✅ Email address
* ✅ Username
* ✅ Full name
* ✅ Avatar/profile picture
* ✅ User is created on first login
* ✅ User data updates on subsequent logins

## User Data Mapping

Silvia sends the following user data to Discourse:

| Discourse Field | Silvia Source | Example |
| - | - | - |
| `external_id` | Clerk User ID | `user_2abc123xyz` |
| `email` | Primary email | `user@example.com` |
| `username` | Clerk username or email prefix | `johnsmith` |
| `name` | First + Last name | `John Smith` |
| `avatar_url` | Clerk profile image | `https://img.clerk.com/...` |

## Security Considerations

### HTTPS Required

Both Silvia and Discourse **must** use HTTPS in production. The SSO flow involves redirects with sensitive signed payloads.

### Secret Management

* Store the SSO secret in environment variables (never commit to git)
* Use the same secret in both Silvia and Discourse
* Rotate the secret periodically (requires updating both systems)

### Signature Verification

* Silvia verifies Discourse's signature before processing requests
* Discourse verifies Silvia's signature before logging in users
* Invalid signatures are rejected with a 403 error

### Return URL Validation

The `return_sso_url` from Discourse should be validated to prevent open redirects. Currently, we trust Discourse to only send valid return URLs.

## Troubleshooting

### "Invalid signature" Error

**Cause:** The SSO secret doesn't match between Silvia and Discourse.

**Solution:**

1. Verify `DISCOURSE_SSO_SECRET` in your `.env` matches the `discourse connect secret` in Discourse settings
2. Ensure there are no extra spaces or newlines in either secret
3. Restart your Silvia server after changing the secret

### "Missing SSO parameters" Error

**Cause:** The request from Discourse is missing the `sso` or `sig` parameters.

**Solution:**

1. Verify the `discourse connect url` in Discourse settings is correct
2. Check that Discourse is actually sending the SSO request (check Discourse logs)

### Users Not Being Created in Discourse

**Cause:** The response payload might be invalid or missing required fields.

**Solution:**

1. Check the Silvia server logs for the SSO response payload
2. Verify the user has a valid email address in Clerk
3. Check Discourse logs for any errors processing the SSO response

### Redirect Loop

**Cause:** The SSO endpoint might be redirecting back to itself.

**Solution:**

1. Ensure the `/api/discourse/sso` route checks for Clerk authentication correctly
2. Verify that the `redirect_url` parameter doesn't create a loop
3. Check browser cookies are enabled (required for Clerk authentication)

### Avatar Not Syncing

**Cause:** Discourse might not be fetching external avatar URLs.

**Solution:**

1. Enable `download remote images to local` in Discourse settings
2. Verify `discourse connect overrides avatar` is enabled
3. Check that the avatar URL is publicly accessible

## Advanced Configuration

### Custom User Fields

To sync custom user data to Discourse:

1. Create custom user fields in Discourse (Admin → Customize → User Fields)
2. Add the field mappings to the SSO response in `/app/api/discourse/sso/route.ts`:

```typescript theme={null}
const responsePayload = new URLSearchParams({
  // ... existing fields ...
  'custom.user_field_1': user.unsafeMetadata?.phoneNumber || '',
  'custom.user_field_2': user.unsafeMetadata?.country || '',
});
```

### Group Membership

To automatically add users to Discourse groups based on their Silvia subscription:

```typescript theme={null}
// In /app/api/discourse/sso/route.ts

// Fetch user's subscription from database
const subscription = await getSubscriptionForUser(userId);

const responsePayload = new URLSearchParams({
  // ... existing fields ...
  add_groups: subscription?.tier === 'pro' ? 'pro_members' : 'free_members',
});
```

### Logout Sync

To log users out of Silvia when they log out of Discourse:

1. Enable `logout redirect` in Discourse settings
2. Set it to: `https://www.cfosilvia.com/api/discourse/logout`
3. Modify `/app/api/discourse/logout/route.ts` to redirect to `/sign-out`

## Monitoring

### Success Metrics to Track

* Number of successful SSO logins per day
* Average time to complete SSO flow
* Failed SSO attempts (invalid signatures, missing users, etc.)
* New vs. returning users via SSO

### Logging

The SSO endpoints log important events:

* ✅ Successful SSO completions
* ❌ Invalid signatures
* ❌ Missing parameters
* ❌ User not found errors

Check your server logs for entries like:

```
✅ Discourse SSO successful for user: user_2abc123xyz
❌ Invalid Discourse SSO signature
```

## API Endpoints

### GET /api/discourse/sso

Main SSO endpoint that handles authentication requests from Discourse.

**Parameters:**

* `sso` - Base64-encoded payload from Discourse
* `sig` - HMAC-SHA256 signature of the sso parameter

**Returns:**

* Redirect to Discourse with signed user data
* Or redirect to /sign-in if user not authenticated

**Production URL:** `https://www.cfosilvia.com/api/discourse/sso`

### GET /api/discourse/logout

Optional endpoint for handling logout requests from Discourse.

**Parameters:**

* `sso` - Base64-encoded payload from Discourse
* `sig` - HMAC-SHA256 signature

**Returns:**

* JSON success response
* Or redirect to /sign-out to log out of Silvia

**Production URL:** `https://www.cfosilvia.com/api/discourse/logout`

## References

* [Discourse Connect (SSO) Official Documentation](https://meta.discourse.org/t/discourseconnect-official-single-sign-on-for-discourse-sso/13045)
* [Clerk Authentication Documentation](https://clerk.com/docs)
* [HMAC-SHA256 Signing Reference](https://en.wikipedia.org/wiki/HMAC)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.