Help Center
SSO Integration
Embed Issuely into your own app so users sign in seamlessly with a single click.
How it works
Issuely uses JWT-based SSO. Your server generates a short-lived signed token containing the user's details and redirects them to https://issuely.in/api/auth/sso?token=…. Issuely verifies the token, creates the user account if needed, and issues a session — all in one redirect.
- User clicks "Open Support" (or similar) in your app.
- Your server signs a JWT with your company's SSO secret and redirects the user.
- Issuely verifies the signature, provisions the account (first visit only), and logs them in.
- The user lands on their Issuely dashboard with no password required.
Setting up SSO
- In Issuely go to Settings → SSO and generate your SSO Secret. Keep this secret — anyone who has it can generate valid login tokens.
- Note your Company ID (shown on the same page).
- In your application, sign a JWT using the secret (HS256) with the payload described below.
- Redirect the user to
https://issuely.in/api/auth/sso?token=YOUR_TOKEN.
JWT payload
{
"companyId": "your-company-id", // required
"email": "user@example.com", // required
"name": "Jane Smith", // optional — used on first sign-in
"role": "CUSTOMER", // optional — CUSTOMER (default) or AGENT
"projectId": "proj_abc123", // optional — auto-add to this project
"iat": 1700000000, // issued-at (Unix seconds)
"exp": 1700000600 // must expire within 10 minutes of iat
}Code examples
Node.js
const jwt = require('jsonwebtoken');
const token = jwt.sign(
{
companyId: 'your-company-id',
email: req.user.email,
name: req.user.name,
role: 'CUSTOMER',
},
process.env.ISSUELY_SSO_SECRET,
{ algorithm: 'HS256', expiresIn: '5m' }
);
res.redirect(`https://issuely.in/api/auth/sso?token=${token}`);PHP
<?php
use Firebase\JWT\JWT;
$payload = [
'companyId' => 'your-company-id',
'email' => $user->email,
'name' => $user->name,
'role' => 'CUSTOMER',
'iat' => time(),
'exp' => time() + 300,
];
$token = JWT::encode($payload, $_ENV['ISSUELY_SSO_SECRET'], 'HS256');
header('Location: https://issuely.in/api/auth/sso?token=' . $token);Python
import jwt, time, os
from flask import redirect
payload = {
'companyId': 'your-company-id',
'email': current_user.email,
'name': current_user.name,
'role': 'CUSTOMER',
'iat': int(time.time()),
'exp': int(time.time()) + 300,
}
token = jwt.encode(payload, os.environ['ISSUELY_SSO_SECRET'], algorithm='HS256')
return redirect(f'https://issuely.in/api/auth/sso?token={token}').NET (C#)
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("ISSUELY_SSO_SECRET")));
var token = new JwtSecurityToken(
claims: new[] {
new Claim("companyId", "your-company-id"),
new Claim("email", user.Email),
new Claim("name", user.Name),
new Claim("role", "CUSTOMER"),
},
expires: DateTime.UtcNow.AddMinutes(5),
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
return Redirect($"https://issuely.in/api/auth/sso?token={tokenString}");Security notes
- Tokens must expire within 10 minutes of their
iat. Longer-lived tokens are rejected. - Never expose your SSO secret in client-side code. Always sign on the server.
- If your secret is compromised, regenerate it immediately in Settings → SSO.
- Each user's email must be unique across Issuely. An email already registered under a different company will be denied.
