@disruptica/ladybug-identity
v0.1.1
Published
Server-side helpers for signing Ladybug widget identities
Downloads
140
Maintainers
Readme
@disruptica/ladybug-identity
Server-side helper for signing Ladybug widget identity tokens. Use this in your backend to identify logged-in users in the embedded widget.
Works in any Node.js or Bun server — no dependencies beyond the built-in crypto module.
Installation
npm install @disruptica/ladybug-identityHow it works
Your backend signs a short-lived HMAC token containing the user's identity. The widget sends this token to Ladybug, which verifies it and associates the chat session with the real user.
Your server → signLadybugIdentity() → token → widget → LadybugUsage
Basic
import { signLadybugIdentity } from '@disruptica/ladybug-identity';
const token = signLadybugIdentity({
secret: process.env.WIDGET_SESSION_SECRET,
user: {
id: 'user_123',
email: '[email protected]',
name: 'Alice',
},
});
// Returns a signed token string, valid for 15 minutes by defaultPass this token to the widget:
<script
src="https://cdn.jsdelivr.net/npm/@disruptica/ladybug-widget/dist/widget.js"
data-embed-key="emb_xxx"
data-user-token="<token from your backend>"
></script>Or via the programmatic API:
new LadybugWidget({
embedKey: 'emb_xxx',
userToken: tokenFromYourBackend,
});Expose an endpoint
The recommended pattern is a short-lived token endpoint your frontend calls on load.
Next.js (App Router)
// app/api/ladybug-token/route.ts
import { signLadybugIdentity } from '@disruptica/ladybug-identity';
import { auth } from '@/lib/auth';
export async function GET() {
const session = await auth();
if (!session?.user) return new Response('Unauthorized', { status: 401 });
const token = signLadybugIdentity({
secret: process.env.WIDGET_SESSION_SECRET!,
user: {
id: session.user.id,
email: session.user.email,
name: session.user.name,
},
expiresInSeconds: 900, // 15 minutes
});
return Response.json({ token });
}Express / Hono / any framework
import { signLadybugIdentity } from '@disruptica/ladybug-identity';
app.get('/api/ladybug-token', requireAuth, (req, res) => {
const token = signLadybugIdentity({
secret: process.env.WIDGET_SESSION_SECRET,
user: {
id: req.user.id,
email: req.user.email,
name: req.user.name,
role: req.user.role, // optional
metadata: { plan: 'pro' }, // optional arbitrary data
},
});
res.json({ token });
});Rails
# config/routes.rb
get '/api/ladybug-token', to: 'ladybug#token'
# app/controllers/ladybug_controller.rb
class LadybugController < ApplicationController
before_action :authenticate_user!
def token
require 'openssl'
require 'base64'
require 'json'
secret = ENV['WIDGET_SESSION_SECRET']
now = Time.now.to_i
payload = {
sub: current_user.id.to_s,
email: current_user.email,
name: current_user.name,
iat: now,
exp: now + 900
}.to_json
body = Base64.urlsafe_encode64(payload, padding: false)
sig = Base64.urlsafe_encode64(
OpenSSL::HMAC.digest('sha256', secret, body),
padding: false
)
render json: { token: "#{body}.#{sig}" }
end
endWith getUserToken (dynamic refresh)
The widget calls this function each time it needs to authenticate, so tokens are always fresh:
new LadybugWidget({
embedKey: 'emb_xxx',
getUserToken: async () => {
const res = await fetch('/api/ladybug-token');
if (!res.ok) return null;
const { token } = await res.json();
return token;
},
});API reference
signLadybugIdentity(options)
| Option | Type | Default | Description |
|---|---|---|---|
| secret | string | required | WIDGET_SESSION_SECRET from your Ladybug instance |
| user.id | string | required | Unique user identifier |
| user.email | string | — | User email |
| user.name | string | — | Display name |
| user.role | string | — | User role |
| user.metadata | Record<string, unknown> | — | Any extra data |
| embedKey | string | — | Scope token to a specific embed installation |
| expiresInSeconds | number | 900 (15 min) | Token TTL |
Returns a string — a base64url-encoded signed token.
signLadybugIdentityPayload(payload, secret)
Low-level function if you need to construct the payload yourself.
import { signLadybugIdentityPayload } from '@disruptica/ladybug-identity';
const token = signLadybugIdentityPayload(
{ sub: 'user_123', exp: Math.floor(Date.now() / 1000) + 900 },
process.env.WIDGET_SESSION_SECRET,
);License
MIT
