@yeboid/node SDK — Product Integration Guide
The @yeboid/node SDK enables any Yebo product backend to validate YeboID tokens locally and integrate with the identity system.
Overview
The SDK provides:
- Token validation middleware — Verify JWTs without API calls
- User profile fetching — Get full user data from YeboID API
- Express integration — Drop-in middleware for protected routes
Installation
bash
npm install @yeboid/nodeQuick Start
javascript
const { yeboidAuth, getYeboUser } = require('@yeboid/node');
const express = require('express');
const app = express();
// 1. Initialize with shared JWT secret
yeboidAuth.init({
jwtSecret: process.env.YEBOID_JWT_SECRET
});
// 2. Protect routes
app.get('/api/orders', yeboidAuth.required, async (req, res) => {
// req.yeboUserId is the authenticated user's UUID
const orders = await db.orders.find({ userId: req.yeboUserId });
res.json(orders);
});
// 3. Optional: Fetch full profile
app.get('/api/profile', yeboidAuth.required, async (req, res) => {
const user = await getYeboUser(req.yeboUserId);
res.json(user);
});SDK API Reference
yeboidAuth.init(config)
Initialize the SDK with configuration.
Parameters:
typescript
interface YeboIDConfig {
jwtSecret: string; // Required: shared JWT secret
apiUrl?: string; // Optional: YeboID API URL
}Example:
javascript
yeboidAuth.init({
jwtSecret: process.env.YEBOID_JWT_SECRET,
apiUrl: 'https://api.yeboid.com' // default
});validateToken Middleware
Alias: yeboidAuth.required
Validates the Bearer token and fails with 401 if invalid.
Request Augmentation:
req.yeboUserId— User's UUID
Example:
javascript
const { validateToken } = require('@yeboid/node');
// Single route
app.get('/api/protected', validateToken, (req, res) => {
console.log('User ID:', req.yeboUserId);
});
// Router-level
const apiRouter = express.Router();
apiRouter.use(validateToken);Error Response (401):
json
{
"error": "Invalid token"
}optionalToken Middleware
Alias: yeboidAuth.optional
Extracts user if token present, but doesn't fail if missing.
Example:
javascript
const { optionalToken } = require('@yeboid/node');
app.get('/api/products', optionalToken, (req, res) => {
if (req.yeboUserId) {
// Personalized response
} else {
// Anonymous response
}
});getYeboUser(userId)
Fetches full user profile from YeboID API.
Parameters:
| Param | Type | Description |
|---|---|---|
userId | string | YeboID user UUID |
Returns:
typescript
interface YeboUser {
id: string;
phone: string;
handle: string | null;
name: string | null;
avatar: string | null;
kycStatus: 'NONE' | 'PENDING' | 'VERIFIED' | 'REJECTED';
createdAt: string;
}Example:
javascript
const { getYeboUser } = require('@yeboid/node');
const user = await getYeboUser('uuid-123');
console.log(user.handle); // 'laslie'
console.log(user.kycStatus); // 'VERIFIED'Notes:
- Requires service-to-service auth (API key)
- Consider caching for frequently accessed profiles
Token Payload Structure
Access tokens contain:
typescript
interface YeboIDPayload {
userId: string; // UUID
type: 'access'; // Always 'access' for access tokens
iat: number; // Issued at (Unix timestamp)
exp: number; // Expires (15 min from iat)
}Environment Variables
env
# Required - shared across ALL Yebo products
YEBOID_JWT_SECRET=your-shared-secret
# Optional - for fetching user profiles via getYeboUser()
YEBOID_API_URL=https://api.yeboid.com
YEBOID_SERVICE_KEY=service-to-service-api-keyProduct Integration Pattern
1. Add SDK Dependency
bash
npm install @yeboid/node2. Update Database Schema
Add yeboidUserId column to link product users to YeboID:
prisma
// In your product's schema.prisma
model User {
id String @id @default(uuid())
yeboidUserId String @unique @map("yeboid_user_id")
// Product-specific fields
shopName String? // YeboShops
resume Json? // YeboJobs
// Relations
orders Order[]
}3. Initialize SDK
javascript
// In your app initialization
const { yeboidAuth } = require('@yeboid/node');
yeboidAuth.init({
jwtSecret: process.env.YEBOID_JWT_SECRET
});4. Protect Routes
javascript
const { validateToken } = require('@yeboid/node');
// All /api routes require auth
app.use('/api', validateToken);5. Link to Product Users
javascript
// After token validation, find/create local user
app.use('/api', async (req, res, next) => {
let user = await prisma.user.findUnique({
where: { yeboidUserId: req.yeboUserId }
});
if (!user) {
// First time user - create local profile
user = await prisma.user.create({
data: { yeboidUserId: req.yeboUserId }
});
}
req.user = user; // Attach local user
next();
});How Local Validation Works
The SDK validates tokens locally without calling YeboID API:
User request with token
│
▼
┌───────────────────────────────────┐
│ SDK extracts token from header │
│ Authorization: Bearer <token> │
└───────────────────────────────────┘
│
▼
┌───────────────────────────────────┐
│ SDK verifies JWT signature │
│ using YEBOID_JWT_SECRET │
│ │
│ jwt.verify(token, secret) │
└───────────────────────────────────┘
│
├── Valid ──► req.yeboUserId = payload.userId
│
└── Invalid ──► 401 UnauthorizedBenefits:
- ⚡ Fast — No network call per request
- 🔒 Secure — Short-lived tokens (15 min)
- 📦 Scalable — No single point of failure
- 🔄 Reliable — Works even if YeboID API is down
Shared Secret Distribution
All Yebo products use the same JWT secret stored in GCP Secret Manager:
┌─────────────────────────────────────┐
│ GCP Secret Manager (org level) │
│ │
│ Secret: YEBOID_JWT_SECRET │
│ │ │
│ ├─► YeboShops (Cloud Run) │
│ ├─► YeboJobs (Cloud Run) │
│ ├─► Eneza (Cloud Run) │
│ ├─► YeboLink (Cloud Run) │
│ └─► [All products] │
│ │
└─────────────────────────────────────┘Cloud Run Secret Mount:
yaml
# In Cloud Run service config
env:
- name: YEBOID_JWT_SECRET
valueFrom:
secretKeyRef:
name: yeboid-jwt-secret
key: latestComplete Integration Example
javascript
// app.js - Full YeboShops integration
const express = require('express');
const { yeboidAuth, getYeboUser } = require('@yeboid/node');
const prisma = require('./prisma');
const app = express();
app.use(express.json());
// Initialize YeboID SDK
yeboidAuth.init({
jwtSecret: process.env.YEBOID_JWT_SECRET
});
// Middleware to attach local user after auth
async function attachUser(req, res, next) {
let user = await prisma.user.findUnique({
where: { yeboidUserId: req.yeboUserId }
});
if (!user) {
// Fetch profile from YeboID
const yeboUser = await getYeboUser(req.yeboUserId);
user = await prisma.user.create({
data: {
yeboidUserId: req.yeboUserId,
name: yeboUser.name,
avatar: yeboUser.avatar
}
});
}
req.user = user;
next();
}
// Protected routes
app.use('/api', yeboidAuth.required, attachUser);
// Product endpoints
app.get('/api/my-shop', async (req, res) => {
const shop = await prisma.shop.findFirst({
where: { ownerId: req.user.id }
});
res.json(shop);
});
app.post('/api/products', async (req, res) => {
const product = await prisma.product.create({
data: {
...req.body,
sellerId: req.user.id
}
});
res.json(product);
});
// Public routes (optional auth)
app.get('/products', yeboidAuth.optional, async (req, res) => {
const products = await prisma.product.findMany();
// Personalize if logged in
if (req.yeboUserId) {
// Add favorites, recommendations, etc.
}
res.json(products);
});
app.listen(3000);SDK Development Roadmap
| SDK | Status | Features |
|---|---|---|
@yeboid/node | 📋 Planned | Token validation, user fetch |
@yeboid/react | 📋 Planned | Hooks, LoginButton, Provider |
@yeboid/react-native | 📋 Planned | Same as React + secure storage |