Configurations & SettingsSingle Sign-On (SSO)

Single Sign-On (SSO)

Let your users sign in to the public portal using your existing login system. Configure a JWT redirect flow so ProductBridge hands off authentication to your app — no password required on the ProductBridge side.

Overview

ProductBridge SSO uses a redirect-based JWT flow. When a user visits your portal and clicks Sign In, ProductBridge sends them to your login page. After they authenticate, your server generates a signed JWT and redirects them back. ProductBridge verifies the token and creates an authenticated session.

How It Works

  1. User clicks Sign In on your ProductBridge portal

  2. ProductBridge redirects to your configured login page with redirect, organizationId, and returnTo query parameters

  3. Your server authenticates the user and generates a signed JWT

  4. Your server redirects back to the ProductBridge SSO callback with ssoToken and organizationId

  5. ProductBridge verifies the JWT signature and creates a 30-day session

The JWT is signed with your Widget API Secret — the same key used for widget identity verification. Your secret never leaves your server.


Configure SSO Redirect

Go to Settings → SSO → SSO Redirect to configure the three steps below.

Step 1 — Set Your Redirect URL

Enter the URL of your login page. This is the page on your application where users will be sent when they click Sign In on your portal.

https://yourapp.com/login

ProductBridge appends these query parameters when redirecting to your login page:

ParameterDescription
redirectThe ProductBridge SSO callback URL to redirect back to after login
organizationIdYour ProductBridge organization ID
returnToThe portal page the user was trying to reach

Your login page should read these parameters, authenticate the user, generate a JWT, and redirect to redirect?ssoToken=JWT&organizationId=organizationId.

Step 2 — Test the Redirect Flow

Click Test Redirect Flow to verify the complete loop before going live. ProductBridge opens a popup, sends a test request to your login page, and waits for a valid JWT callback.

Click Test Redirect Flow

ProductBridge opens a popup window and redirects to your configured login page with test=true appended to the query parameters.

Complete authentication in the popup

Your login page receives the request, authenticates the test, and sends a JWT back to the ProductBridge callback URL.

See the result

If the JWT is valid, the popup closes and the SSO Tested badge turns green. If verification fails, an error message describes what went wrong.

You must complete a successful test before you can enable SSO. The Enable SSO toggle is locked until the test passes.

Step 3 — Enable SSO

After a successful test, two toggles become available (visible at the bottom of the screenshot at the top of this section).

Enable Single Sign-On Redirect — When on, all portal Sign In clicks redirect to your login page instead of showing the ProductBridge login form.

Disable ProductBridge Login — When on, the native ProductBridge login form is hidden entirely. Users can only sign in via your SSO redirect. Enable this only after confirming SSO works correctly.

Enabling "Disable ProductBridge Login" locks out all users who previously signed in with a ProductBridge password. Make sure SSO is fully working before turning this on. You can always disable SSO from the dashboard to restore access.


Generate the SSO JWT

Your login page must generate a signed JWT and redirect back to ProductBridge. Sign the token with your Widget API Secret using HS256.

Get Your API Secret

Go to Settings → SSO → API Keys. If no key exists yet, click Generate Private Key.

After generation, the full secret is shown once. Copy it immediately and store it in your server environment.

PRODUCTBRIDGE_WIDGET_SECRET=your_64_char_hex_secret

The full secret is displayed only once at generation time. If you lose it, click Regenerate to issue a new key — but be aware this immediately invalidates every existing JWT signed with the old secret.

Generate the JWT

const jwt = require('jsonwebtoken');
// npm install jsonwebtoken

const PRODUCTBRIDGE_SECRET = process.env.PRODUCTBRIDGE_WIDGET_SECRET;

// Called after your own auth succeeds
function handleSSOCallback(req, res) {
  const { redirect, organizationId, returnTo } = req.query;
  const user = req.user; // your authenticated user

  const token = jwt.sign(
    {
      // Required
      email: user.email,

      // Recommended
      name: user.name,
      id: String(user.id),
      avatarURL: user.avatarUrl,

      // Optional: company & plan data
      company_name: user.companyName,
      company_id: String(user.companyId),
      company_mrr: user.mrr,
      customer_status: user.status,     // "active" | "trial" | "churned"
      renewal_date: user.renewalDate,   // ISO date string
      renewal_risk: user.renewalRisk,   // "low" | "medium" | "high"
    },
    PRODUCTBRIDGE_SECRET,
    { expiresIn: '1h', algorithm: 'HS256' }
  );

  // Redirect back to ProductBridge
  const callbackUrl = new URL(redirect);
  callbackUrl.searchParams.set('ssoToken', token);
  callbackUrl.searchParams.set('organizationId', organizationId);
  if (returnTo) callbackUrl.searchParams.set('returnTo', returnTo);

  res.redirect(callbackUrl.toString());
}

JWT Payload Reference

FieldTypeRequiredDescription
emailstringYesUser's email — used as the primary identity anchor
namestringRecommendedDisplay name shown in the ProductBridge dashboard
idstringRecommendedYour internal user ID for deduplication
avatarURLstringNoProfile picture URL
company_namestringNoUser's company name
company_idstringNoYour internal company / account ID
company_mrrnumberNoMonthly recurring revenue in USD
customer_statusstringNoactive, trial, churned, or any custom value
renewal_datestringNoISO date string of the next renewal
renewal_riskstringNolow, medium, or high
account_owner_idstringNoInternal ID of the account owner or CSM
account_owner_emailstringNoEmail of the account manager or CSM
external_user_idstringNoAny external system ID (CRM, Salesforce, etc.)

Only email is required. Start there and add company and plan fields later when you want user segmentation and revenue-weighted prioritization in your dashboard.


Widget Auth Settings

Go to Settings → SSO → Widget Auth to control how the in-app widget handles user identity.

Require identify() for Widget

When enabled, anonymous users see a locked state in the widget instead of the default feedback form. The widget only accepts submissions from users who have been identified via ProductBridge.init({ userToken }) or ProductBridge.identify(token).

Use this when you want every piece of widget feedback linked to a verified user account.

Require User Hash

When enabled, ProductBridge also validates an HMAC-SHA256 hash of the user ID included in the JWT. This prevents a user from crafting a token that impersonates another user — even if they somehow obtain a valid API secret.

Generate the hash on your server and include it in the JWT payload:

const crypto = require('crypto');

const userHash = crypto
  .createHmac('sha256', process.env.PRODUCTBRIDGE_WIDGET_SECRET)
  .update(String(user.id))
  .digest('hex');

// Include user_hash in your JWT payload
jwt.sign(
  { email: user.email, id: String(user.id), user_hash: userHash },
  PRODUCTBRIDGE_SECRET,
  { expiresIn: '1h' }
);

Identify Mode

Controls what happens when the widget receives an identify() call for a user who does not exist in ProductBridge yet.

ModeBehavior
Upsert (default)Creates a new user record if the email is not found. Use for self-serve products where any authenticated user can submit feedback.
Update OnlyRejects identify calls for unknown emails. Use when you want to restrict widget feedback to a pre-imported user list only.

Portal Auth Methods

Go to Settings → SSO → Portal to see the SSO callback URL and your portal URL.

FieldValue
Portal URLYour public portal address (subdomain or custom domain)
SSO Callback URLThe URL your login page redirects back to — always /api/redirects/sso on your portal host

Copy the SSO Callback URL and allowlist it on your OAuth provider or CSRF whitelist if your login system enforces origin checking.


Troubleshooting