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
- 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
- Pass the token to SeggWat - Include it in the portal URL/embed, or hand it to the widget via
setUser(chat) - SeggWat validates the signature - SeggWat verifies the token hasn't been tampered with and is bound to your project
- User identity is confirmed - The user votes, suggests, comments, and chats with their verified identity
Setting Up Authentication
1. Enable Authentication in Project Settings
- Go to your project settings in the SeggWat dashboard
- Find the End-User Authentication section
- Select Signed tokens (JWT)
- Click Generate Secret to create your signing secret
Important: The signing secret is only shown once! Copy it immediately and store it securely in your backend environment variables.
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:
{
"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
}The aud (audience) claim must equal your project key. Tokens with a missing or mismatched aud are rejected.
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:
<!-- 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
// 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.
The session cookie is first-party and HttpOnly (not readable from JavaScript). It's used only to keep the visitor signed in to their own board — never for cross-site tracking. To sign a visitor out, send DELETE /api/v1/p/{project_key}/session.
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
tokenparameter in the URL - Verify the token hasn't expired
- Check that the
project_keyin the token matches the portal
"Invalid token" Error
The token signature verification failed.
Solutions:
- Verify you're using the correct signing secret
- Ensure the
audclaim 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.
