Single Sign-On
Single sign-on (SSO) lets users sign in to your public FeedbackJar board through your own authentication system. When a user clicks Log in on your board, FeedbackJar redirects them to your SSO endpoint. After you authenticate them, you send them back to FeedbackJar with a signed JWT.
This is for public board login — a visitor clicking “Log in” on your feedback portal. It’s separate from auto-login, which silently carries an already-identified widget user into the portal without a redirect round-trip.
Enable SSO
- Open Settings → SSO in your project dashboard.
- Toggle Enable SSO on.
- Enter your SSO redirect URL — the endpoint on your own backend that authenticates the user.
- Copy your Project ID and Project secret.
Your SSO redirect URL must use https://. During local development, use an HTTPS tunnel (e.g. ngrok) if you need to test the full redirect flow.
How the flow works
When a user clicks Log in on your board, FeedbackJar redirects their browser to your configured SSO redirect URL. The only query parameter your endpoint needs is state:
https://yourapp.com/sso/feedbackjar?state=OPAQUE_STATE_FROM_FEEDBACKJAR Your endpoint should:
- Read the
statequery parameter. - Authenticate the user in your app.
- Create a JWT signed with your FeedbackJar project secret.
- Redirect to
https://api.feedbackjar.com/auth/sso/callbackwithjwtand the originalstate.
Do not modify the state value — FeedbackJar uses it to verify that the login was started by the same browser session, and to prevent replay. It is one-time-use and expires after 15 minutes.
If the user isn’t signed in yet, send them through your normal login flow first, then return them to this same SSO endpoint with the original query parameters.
JWT payload
The JWT must be signed with HS256 using your FeedbackJar project secret.
At minimum, send the user ID, issuer, audience, and expiration. You can also include an email address and profile fields.
| Claim | Required | Description |
|---|---|---|
sub | Yes | Stable user ID from your system |
email | No | User’s email address |
iss | Yes | Exact FeedbackJar Project ID |
aud | Yes | Exact string feedbackjar |
exp | Yes | Unix expiration timestamp |
iat | No | Unix issued-at timestamp |
firstName | No | Given profile field |
lastName | No | Family profile field |
avatar | No | Avatar URL |
Use a short expiration window — 5 to 15 minutes is a good default.
If email is omitted, FeedbackJar identifies the user by sub alone. Providing an email is recommended — it’s what future email-based features (like notifications) will link against.
Example endpoint (Node.js / Hono)
import { Hono } from 'hono';
import { SignJWT } from 'jose';
const app = new Hono();
const PROJECT_ID = 'YOUR_PROJECT_ID';
const PROJECT_SECRET = 'YOUR_PROJECT_SECRET';
const FEEDBACKJAR_CALLBACK_URL = 'https://api.feedbackjar.com/auth/sso/callback';
app.get('/sso/feedbackjar', async (c) => {
const state = c.req.query('state');
if (!state) return c.text('Missing state', 400);
// Authenticate the user however your app normally does.
const user = await getCurrentUser(c);
const token = await new SignJWT({
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
})
.setProtectedHeader({ alg: 'HS256' })
.setSubject(user.id)
.setIssuer(PROJECT_ID)
.setAudience('feedbackjar')
.setIssuedAt()
.setExpirationTime('10m')
.sign(new TextEncoder().encode(PROJECT_SECRET));
const callback = new URL(FEEDBACKJAR_CALLBACK_URL);
callback.searchParams.set('jwt', token);
callback.searchParams.set('state', state);
return c.redirect(callback.toString());
}); Keep the project secret on your server. Never expose it in browser code.
Security notes
- SSO board login is disabled for admin/owner accounts — it’s for your end-users, not your FeedbackJar project team.
- The
stateparam is single-use and expires after 15 minutes; a captured redirect link can’t be replayed later. - Rotating your project secret immediately invalidates every JWT signed with the old one — update your SSO endpoint first, then rotate.
Troubleshooting
Users are sent back without being logged in. Check that:
- the JWT is signed with the current project secret
issmatches the exact Project ID from your project settingsaudis the exact stringfeedbackjarsubandexpare present- your endpoint sends back the exact
statevalue it received
If SSO fails after the callback, FeedbackJar redirects back to the board with an sso_error query parameter:
| Code | Meaning |
|---|---|
invalid_state | The state param was missing, already used, or expired (15 min) |
invalid_token | JWT verification failed — bad signature, wrong iss/aud, or missing sub |
auth_failed | SSO isn’t enabled/configured for this project |
admin_account | The account belongs to a project owner/admin — SSO board login is for end-users only |
The login button doesn’t redirect to my SSO endpoint. Check that SSO is toggled on in Settings → SSO and that a redirect URL is saved.
You rotated the project secret. Update your SSO endpoint immediately — tokens signed with the old secret stop working right away.
Single Sign-On vs. Auto-Login
| Single Sign-On | Auto-login | |
|---|---|---|
| Who starts it | The user, by clicking “Log in” on your public board | Your app, via the widget SDK |
| Best for | A visitor landing directly on your board | A logged-in user clicking through from inside your app |
| Format | JWT (HS256) via a server-to-server redirect | HMAC-SHA256 signature in a URL parameter |
| Network flow | Round-trip: portal → your SSO endpoint → FeedbackJar → portal | One-way: your frontend → portal |
| Requires a public redirect endpoint on your server | Yes | No |