End-User Authentication

Give your signed-in users a verified identity with signed tokens — the one mechanism behind board voting, live chat, and private feedback threads

End-user authentication gives your signed-in users a verified identity on SeggWat. Your backend mints a short-lived signed JWT for the logged-in user, SeggWat validates it, and from then on their actions count as authenticated. This single mechanism powers everything that needs to know who a visitor is:

  • Public board — votes, feature-request submissions, and comments count as verified (and bypass the email-verification requirement). The visitor also gets a personal My activity view of their own contributions.
  • Live chat — the Chat with us tile only appears once a token is passed, keeping each conversation private to its owner. See Live Chat.
  • Private feedback threads — submitters can follow up on their own feedback items from the board.

Without it, the public board falls back to your public-voting policy (anonymous or email-verification), and the identified-only surfaces (live chat, private threads) stay hidden.

How It Works

  1. You generate tokens server-side - When a signed-in user loads a page with your embedded board or the feedback widget, your backend generates a signed JWT containing their identity
  2. Pass the token to SeggWat - Include it in the portal URL/embed, or hand it to the widget via setUser (chat)
  3. SeggWat validates the signature - SeggWat verifies the token hasn't been tampered with and is bound to your project
  4. User identity is confirmed - The user votes, suggests, comments, and chats with their verified identity

Setting Up Authentication

1. Enable Authentication in Project Settings

  1. Go to your project settings in the SeggWat dashboard
  2. Find the End-User Authentication section
  3. Select Signed tokens (JWT)
  4. Click Generate Secret to create your signing secret

2. Generate Tokens Server-Side

Generate JWT tokens in your backend when users access the feature portal.

Token Payload

Tokens use the following payload structure:

json
{
  "sub": "user-123",              // Required: User's unique ID in your system
  "email": "user@example.com",    // Optional: User's email
  "name": "Jane Doe",             // Optional: User's display name
  "iat": 1706496400,              // Required: Issued at timestamp (Unix epoch)
  "exp": 1706500000,              // Required: Expiration timestamp (Unix epoch)
  "project_key": "abc123-...",    // Required: Your SeggWat project key
  "aud": "abc123-..."             // Required: Must equal your SeggWat project key
}

JWT Token Generation

const jwt = require('jsonwebtoken');

function generateSeggwatToken(userId, userEmail, projectKey, signingSecret) {
  return jwt.sign(
    {
      sub: userId,
      email: userEmail,
      project_key: projectKey,
      aud: projectKey
    },
    signingSecret,
    {
      algorithm: 'HS256',
      expiresIn: '1h'
    }
  );
}

// Usage
const token = generateSeggwatToken(
  user.id,
  user.email,
  process.env.SEGGWAT_PROJECT_KEY,
  process.env.SEGGWAT_SIGNING_SECRET
);

3. Embed the Portal with Token

Pass the token to the feature portal via URL parameter:

html
<!-- Direct link -->
<a href="https://seggwat.com/p/YOUR_PROJECT_KEY?token=GENERATED_TOKEN">
  Feature Portal
</a>

<!-- Iframe embed -->
<iframe
  src="https://seggwat.com/p/YOUR_PROJECT_KEY?token=GENERATED_TOKEN&embed=true"
  width="100%"
  height="600"
  frameborder="0">
</iframe>

Dynamic Embedding Example

javascript
// Server-side: generate a fresh token for each page load
app.get('/features', (req, res) => {
  const token = generateSeggwatToken(
    req.user.id,
    req.user.email,
    process.env.SEGGWAT_PROJECT_KEY,
    process.env.SEGGWAT_SIGNING_SECRET
  );

  res.render('features', {
    portalUrl: `https://seggwat.com/p/${process.env.SEGGWAT_PROJECT_KEY}?token=${token}&embed=true`
  });
});

Sessions and Token Lifetime

The token you mint is a one-time bridge, not the session itself. The first time a visitor opens the board with a valid ?token=, SeggWat exchanges it for a first-party board session — an sw_bs_<project_key> cookie (HttpOnly, SameSite=Lax, ~30 days). From then on the visitor is recognized by that session, so a refresh or in-app navigation that drops ?token= from the URL keeps them signed in.

This has two practical consequences:

  • Returning visitors stay signed in for up to 30 days — even after the short-lived token has expired. You don't need to keep a live token in every link.
  • A token expiring mid-session won't sign them out. The 1–4 h token lifetime only governs the initial hand-off; the session cookie carries them after that.

In practice the simplest integration is to mint a fresh token on every server-rendered page load (as in the examples above) and let the cookie handle persistence — the token is cheap to generate and never needs to outlive the request.

Security Considerations

Token Expiration

  • Recommended: 1-4 hours
  • Maximum allowed: 24 hours
  • Short-lived tokens reduce risk if compromised

Project Key Validation

Tokens include the project_key claim. SeggWat validates this matches the portal being accessed, preventing tokens from being reused across different projects.

Secret Storage

  • Store your signing secret in environment variables
  • Never expose it in client-side code
  • Rotate secrets periodically using the "Regenerate" button in settings

Troubleshooting

"Authentication required" Error

The portal requires a valid token but none was provided or it was invalid.

Solutions:

  • Ensure you're passing the token parameter in the URL
  • Verify the token hasn't expired
  • Check that the project_key in the token matches the portal

"Invalid token" Error

The token signature verification failed.

Solutions:

  • Verify you're using the correct signing secret
  • Ensure the aud claim equals your project key
  • Confirm you're using the HS256 algorithm

"Token has expired" Error

The token's exp claim is in the past.

Solutions:

  • Generate fresh tokens for each page load
  • Increase token lifetime if needed (up to 24 hours)

What Authentication Unlocks

When authentication is enabled and a valid token is supplied, users can vote on features, suggest new ideas, and leave comments with their verified identity. The same token is what makes the Live Chat tile appear in the feedback widget and lets submitters follow up on their own private feedback threads — both are identified-only and stay hidden for anonymous visitors.

When authentication is disabled, the public board falls back to your public-voting policy (set under Public Board → Public visitor voting), and the identified-only surfaces (live chat, private threads) are unavailable. See Live Chat for the widget-side setup.

Navigation