Skip to content

ssojet/ssokit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SSOJet SSOKit

License: MIT npm version

Production-grade team management UI + webhook-driven SCIM provisioning for SSOJet

SSOJet SSOKit is an open-source, batteries-included solution for building team management experiences powered by SSOJet APIs. It features drop-in React widgets, headless hooks, and automatic SCIM 2.0 provisioning triggered by webhooks.


🎯 Features

πŸ§‘β€πŸ€β€πŸ§‘ Team Management UI

  • Drop-in TeamManager widget with members, invites, roles, and audit logs
  • Fully themed with 4 presets (light, dark, minimal, enterprise) + custom tokens
  • Headless hooks for building custom UIs
  • Type-safe with full TypeScript support

πŸ”— Webhook β†’ SCIM Provisioning

  • Signature verification for secure webhook handling
  • Automatic SCIM sync from team events (member added/removed/role changed)
  • Full SCIM 2.0 client for Users and Groups
  • Customizable mapping strategies

βš™οΈ Environment-Driven Configuration

  • Zero hardcoded secrets - everything from env vars
  • Client-safe config injection
  • Helpful error messages for missing configuration

πŸ“¦ Packages

Package Description Version
@ssojet/ssokit-core Types, schemas, errors, config npm
@ssojet/ssokit-react React hooks and providers npm
@ssojet/ssokit-team TeamManager drop-in widget npm
@ssojet/ssokit-next Next.js route handlers npm
@ssojet/ssokit-webhooks Webhook + SCIM provisioning npm
@ssojet/ssokit-css Theming + Tailwind preset npm

πŸš€ Quick Start

1. Install Packages

pnpm add @ssojet/ssokit-react @ssojet/ssokit-next @ssojet/ssokit-webhooks @ssojet/ssokit-css

2. Set Environment Variables

# .env.local

# SSOJet API (server-side)
DEFAULT_SSOJET_API_URL=https://api.ssojet.com
DEFAULT_SSOJET_CLIENT_ID=your-client-id
DEFAULT_SSOJET_CLIENT_SECRET=your-client-secret
DEFAULT_SSOJET_AUTHORITY=https://api.ssojet.com

# Webhook verification
SSOJET_WEBHOOK_SECRET=whsec_xxx

# SCIM downstream
SCIM_BASE_URL=https://scim.target.com/scim/v2
SCIM_TOKEN=scim_bearer_xxx

# Optional: Client-safe config
NEXT_PUBLIC_DEFAULT_SSOJET_CLIENT_ID=your-client-id
NEXT_PUBLIC_DEFAULT_SSOJET_AUTHORITY=https://api.ssojet.com

3. Setup Next.js Route Handlers

// app/api/ssokit/orgs/[orgId]/route.ts
import { createRouteHandlers } from '@ssojet/ssokit-next/routes';

const handlers = createRouteHandlers();

export const GET = handlers.getOrganization;
export const PATCH = handlers.updateOrganization;
// app/api/ssokit/orgs/[orgId]/members/route.ts
const handlers = createRouteHandlers();

export const GET = handlers.listMembers;
export const POST = handlers.addMember;

(See route setup guide for all routes)

4. Setup Webhook Endpoint

// app/api/ssokit/webhooks/route.ts
import { NextRequest, NextResponse } from 'next/server';
import {
  verifySignature,
  parseEvent,
  createScimClient,
  handleEventToSCIM,
} from '@ssojet/ssokit-webhooks';
import { readWebhookServerConfig, readScimServerConfig } from '@ssojet/ssokit-core/config';

export const runtime = 'nodejs';

export async function POST(req: NextRequest) {
  const rawBody = Buffer.from(await req.arrayBuffer());
  const signature = req.headers.get('ssojet-signature') || '';

  try {
    // 1. Verify signature
    const webhookConfig = readWebhookServerConfig();
    verifySignature({ rawBody, header: signature, secret: webhookConfig.secret });

    // 2. Parse event
    const event = parseEvent(rawBody.toString('utf8'));

    // 3. Handle SCIM provisioning
    const scimConfig = readScimServerConfig();
    const scim = createScimClient(scimConfig);
    
    await handleEventToSCIM({
      event,
      scimClient: scim,
      orgIdScopeStrategy: (orgId, role) => `${orgId}:${role}s`,
    });

    return NextResponse.json({ received: true });
  } catch (err: any) {
    console.error('Webhook error:', err);
    return NextResponse.json({ error: err.message }, { status: 400 });
  }
}

5. Use TeamManager Widget

import { SSOJetClient } from '@ssojet/ssokit-next';
import { TeamManager } from '@ssojet/ssokit-team';
import '@ssojet/ssokit-css';

function TeamPage() {
  const client = new SSOJetClient(accessToken);
  
  return (
    <TeamManager
      organizationId="org_123"
      client={client}
      currentUserId="user_456"
      currentUserEmail="user@example.com"
      showAuditLog
    />
  );
}

πŸ“š Documentation


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Your Next.js App                      β”‚
β”‚                                                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  TeamManager UI  │────────▢│ SSOJetClient            β”‚   β”‚
β”‚  β”‚  (@ssokit-team)  β”‚         β”‚ (@ssokit-next)          β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                          β”‚                    β”‚
β”‚                                          β–Ό                    β”‚
β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚                              β”‚    SSOJet API Client    β”‚   β”‚
β”‚                              β”‚   (CLIENT_ID/SECRET)    β”‚   β”‚
β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                          β”‚                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                           β”‚
                                           β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚   SSOJet API (Cloud)    β”‚
                              β”‚  api.ssojet.com/v1/...  β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                           β”‚
                                           β”‚ Webhook Events
                                           β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚ /api/v1/webhooks        β”‚
                              β”‚ (@ssokit-webhooks)      β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                           β”‚
                                           β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚   SCIM 2.0 Endpoint     β”‚
                              β”‚  (Your IdP/Directory)   β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Flow:

  1. UI β†’ SSOJet Client β†’ SSOJet API: TeamManager uses SSOJetClient directly to communicate with SSOJet APIs
  2. SSOJet β†’ Webhook β†’ SCIM: Team events trigger webhooks, verified and converted to SCIM operations

🎨 Theming

SSOKit supports multiple theming approaches:

1. Presets

import '@ssojet/ssokit-css/presets/dark.css';

2. Custom Tokens

import '@ssojet/ssokit-css/tokens.css';

3. CSS Variables

.sk-root {
  --sk-primary: #2563eb;
  --sk-radius: 12px;
}

4. Tailwind Integration

// tailwind.config.js
module.exports = {
  presets: [require('@ssojet/ssokit-css/tailwind/preset.cjs')],
};

πŸ”’ Security

  • Server-side API key never exposed to client
  • HMAC signature verification for webhooks
  • Timing-safe comparisons prevent timing attacks
  • Type-safe validation with Zod schemas

⚠️ Important: Implement authentication middleware to verify users can access requested organizations.


πŸ§ͺ Development

# Install dependencies
pnpm install

# Build all packages
pnpm -r build

# Run tests
pnpm test

# Run example app
cd examples/next-app
pnpm dev

πŸ“‹ Roadmap

  • Core types and schemas
  • Webhook verification + SCIM client
  • SSOJet API client
  • Theming system with CSS presets
  • TeamManager widget with full functionality
  • Example Next.js application
  • E2E tests
  • Storybook components
  • SDK documentation site

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.


πŸ“„ License

MIT Β© SSOJet Team


πŸ’¬ Support


Built with ❀️ by the SSOJet team

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published