Token Endpoint Setup
The token endpoint is an API route on your backend that exchanges a user's existing session (cookie, OAuth token, etc.) for a short-lived JWT. The Agent77 widget calls this endpoint when a conversation starts.
Required JWT Claims
| Claim | Description | Example |
|---|---|---|
sub | User identifier | "user_92x7f" |
aud | Audience — must be "chatbot" | "chatbot" |
iss | Issuer — your domain | "https://app.example.com" |
iat | Issued-at timestamp (epoch seconds) | 1700000000 |
exp | Expiration timestamp | 1700001800 |
Django Example
Uses djangorestframework-simplejwt for signing. Install
with pip install djangorestframework-simplejwt.
# views.py
from datetime import timedelta
from django.conf import settings
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
import jwt, time
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def chatbot_token(request):
now = int(time.time())
payload = {
"sub": str(request.user.id),
"aud": "chatbot",
"iss": settings.SITE_URL, # e.g. "https://app.example.com"
"iat": now,
"exp": now + 1800, # 30 minutes
}
private_key = settings.CHATBOT_PRIVATE_KEY # RSA PEM string
token = jwt.encode(payload, private_key, algorithm="RS256",
headers={"kid": settings.CHATBOT_KEY_ID})
return Response({"token": token}) Express / Node.js Example
Uses jsonwebtoken. Install with
npm install jsonwebtoken.
// routes/chatbot-token.js
const jwt = require("jsonwebtoken");
const fs = require("fs");
const PRIVATE_KEY = fs.readFileSync("./keys/private.pem");
const KEY_ID = process.env.CHATBOT_KEY_ID;
module.exports = (req, res) => {
if (!req.user) return res.status(401).json({ error: "Not authenticated" });
const token = jwt.sign(
{
sub: req.user.id,
aud: "chatbot",
iss: process.env.SITE_URL,
},
PRIVATE_KEY,
{
algorithm: "RS256",
expiresIn: "30m",
keyid: KEY_ID,
}
);
res.json({ token });
}; Rails Example
Uses ruby-jwt. Add gem "jwt" to your
Gemfile.
# app/controllers/api/chatbot_tokens_controller.rb
class Api::ChatbotTokensController < ApplicationController
before_action :authenticate_user!
def create
now = Time.now.to_i
payload = {
sub: current_user.id.to_s,
aud: "chatbot",
iss: ENV["SITE_URL"],
iat: now,
exp: now + 1800
}
private_key = OpenSSL::PKey::RSA.new(ENV["CHATBOT_PRIVATE_KEY"])
token = JWT.encode(payload, private_key, "RS256",
{ kid: ENV["CHATBOT_KEY_ID"] })
render json: { token: token }
end
end Security Notes
- Short-lived tokens. Set
expto 15–30 minutes. The widget will re-fetch a token when it expires. - Use RS256. Asymmetric signing lets Agent77 verify tokens using your public key without ever seeing your private key.
- Authenticate first. The token endpoint must only issue JWTs for already-authenticated users. Never issue tokens to unauthenticated requests.
- Include
kidin the header. This lets Agent77 look up the correct public key from your JWKS endpoint, enabling key rotation.