kenzosso
v1.0.1
Published
SSO authentication package for Kenzo Portal integration with Clerk
Downloads
9
Maintainers
Readme
kenzosso
SSO authentication package for Kenzo Portal integration with Clerk.
This package allows target applications to authenticate users seamlessly when they click on an app link from the Kenzo Portal profile menu. The user is automatically signed in without needing to enter credentials.
Prerequisites
Before using this package, you must:
- Register your app in Kenzo Portal Admin → App Store
- Get your App Secret from the SSO Configuration tab
- Store the secret securely (environment variable recommended)
Installation
npm install kenzosso
# or
yarn add kenzossoPeer Dependencies
This package requires the following peer dependencies:
{
"react": ">=17.0.0",
"@clerk/clerk-react": ">=4.0.0"
}Quick Start
Option 1: Using the Provider (Recommended)
Wrap your app with KenzoSSOProvider to automatically handle SSO authentication:
// App.jsx or layout.jsx
import { ClerkProvider } from '@clerk/clerk-react';
import { KenzoSSOProvider } from 'kenzosso';
function App() {
return (
<ClerkProvider publishableKey={process.env.REACT_APP_CLERK_PUBLISHABLE_KEY}>
<KenzoSSOProvider
appSecret={process.env.REACT_APP_KENZO_SSO_SECRET}
onSuccess={({ userData, session }) => {
console.log('SSO Success:', userData);
}}
onError={({ error }) => {
console.error('SSO Error:', error);
}}
>
<YourApp />
</KenzoSSOProvider>
</ClerkProvider>
);
}Option 2: Using the Handler Component
For simpler cases, use the KenzoSSOHandler component:
import { ClerkProvider } from '@clerk/clerk-react';
import { KenzoSSOHandler } from 'kenzosso';
function App() {
return (
<ClerkProvider publishableKey={process.env.REACT_APP_CLERK_PUBLISHABLE_KEY}>
<KenzoSSOHandler
appSecret={process.env.REACT_APP_KENZO_SSO_SECRET}
onSuccess={({ userData }) => console.log('Logged in:', userData)}
onError={(error) => console.error('SSO failed:', error)}
/>
<YourApp />
</ClerkProvider>
);
}Option 3: Using Hooks
For more control, use the hooks directly:
import { useClerk } from '@clerk/clerk-react';
import { useKenzoSSOWithClerk } from 'kenzosso';
function App() {
const clerk = useClerk();
const { isProcessing, isAuthenticated, userData, error } = useKenzoSSOWithClerk(clerk, {
appSecret: process.env.REACT_APP_KENZO_SSO_SECRET,
onSuccess: ({ userData, session }) => {
console.log('SSO Success:', userData);
},
onError: ({ error }) => {
console.error('SSO Error:', error);
},
});
if (isProcessing) {
return <div>Authenticating...</div>;
}
return <YourApp />;
}Option 4: Manual Implementation
For complete control over the SSO flow:
import { useEffect } from 'react';
import { useClerk } from '@clerk/clerk-react';
import { handleKenzoSSO, signInWithClerk } from 'kenzosso';
const APP_SECRET = process.env.REACT_APP_KENZO_SSO_SECRET;
function App() {
const clerk = useClerk();
useEffect(() => {
async function processSSO() {
// 1. Handle SSO token validation
const userData = await handleKenzoSSO(APP_SECRET);
if (!userData) return; // No SSO token in URL
// 2. Sign in with Clerk
const result = await signInWithClerk(clerk, userData, {
createUserIfNotExists: true,
onSuccess: (session) => console.log('Signed in:', session),
onError: (error) => console.error('Sign-in failed:', error),
});
}
processSSO();
}, [clerk]);
return <YourApp />;
}Next.js Integration
For Next.js apps, wrap your layout with the provider:
// app/layout.jsx (App Router)
import { ClerkProvider } from '@clerk/nextjs';
import { KenzoSSOProvider } from 'kenzosso';
export default function RootLayout({ children }) {
return (
<html>
<body>
<ClerkProvider>
<KenzoSSOProvider appSecret={process.env.NEXT_PUBLIC_KENZO_SSO_SECRET}>
{children}
</KenzoSSOProvider>
</ClerkProvider>
</body>
</html>
);
}// pages/_app.jsx (Pages Router)
import { ClerkProvider } from '@clerk/nextjs';
import { KenzoSSOProvider } from 'kenzosso';
export default function App({ Component, pageProps }) {
return (
<ClerkProvider {...pageProps}>
<KenzoSSOProvider appSecret={process.env.NEXT_PUBLIC_KENZO_SSO_SECRET}>
<Component {...pageProps} />
</KenzoSSOProvider>
</ClerkProvider>
);
}API Reference
Components
KenzoSSOProvider
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| appSecret | string | REQUIRED | App secret from Kenzo App Store |
| clerk | object | - | Clerk instance (optional) |
| onSuccess | function | - | Callback on successful SSO |
| onError | function | - | Callback on SSO error |
| autoProcess | boolean | true | Auto-process SSO token on mount |
| createUserIfNotExists | boolean | true | Create Clerk user if not exists |
KenzoSSOHandler
Same props as KenzoSSOProvider, but renders nothing and doesn't provide context.
Hooks
useKenzoSSO(options)
Basic hook for SSO token handling without Clerk integration.
Options:
appSecret: App secret from Kenzo App Store (REQUIRED)autoProcess: Whether to auto-process on mount
Returns:
userData: Validated user dataisLoading: Processing stateerror: Error message if anyhasToken: Whether SSO token is presentprocessSSO: Manual trigger function
useKenzoSSOWithClerk(clerk, options)
Complete hook for SSO with Clerk sign-in.
Options:
appSecret: App secret from Kenzo App Store (REQUIRED)autoProcess: Whether to auto-process on mountcreateUserIfNotExists: Create user if not in ClerkonSuccess: Success callbackonError: Error callback
Returns:
isProcessing: Processing stateisAuthenticated: Whether user is signed inuserData: Validated user dataerror: Error message if anyprocessSSO: Manual trigger function
useKenzoSSOToken()
Simple hook to check for SSO token presence.
Returns:
hasToken: Whether token is presenttoken: The token value
useKenzoTokenValidation(appSecret)
Manual token validation hook.
Returns:
validate: Function to validate a tokenisValidating: Validation stateresult: Validation resulterror: Error message if any
Utility Functions
handleKenzoSSO(appSecret)
Complete SSO flow - extracts token, validates, and cleans URL.
const userData = await handleKenzoSSO('your-app-secret');
// Returns: { email, name, employee_id, app_id } or nullvalidateSSOToken(token, appSecret)
Validates an SSO token with the Kenzo API.
const result = await validateSSOToken('abc123...', 'your-app-secret');
// Returns: { valid: boolean, data: {...}, message: string }signInWithClerk(clerk, userData, options)
Signs in a user with Clerk using SSO user data.
const result = await signInWithClerk(clerk, userData, {
createUserIfNotExists: true,
onSuccess: (session) => console.log('Success'),
onError: (error) => console.error('Error'),
});
// Returns: { success: boolean, session?, error? }getSSOTokenFromURL()
Extracts SSO token from URL query parameters.
removeSSOTokenFromURL()
Removes SSO token from URL without page reload.
How It Works
- User clicks app in Kenzo Portal → Kenzo generates a secure SSO token
- User is redirected to target app → URL contains
?sso_token=xxx - Package detects token → Validates with Kenzo API
- Kenzo validates and returns user data → Email, name, employee_id
- Package signs in with Clerk → Creates user if needed
- Token is removed from URL → Clean browser history
Security
- Tokens expire in 5 minutes
- Tokens are single-use (marked as used after validation)
- Tokens are app-specific
- All communication over HTTPS
- App secret required for validation
Troubleshooting
SSO token not detected
- Check if URL contains
?sso_token=parameter - Ensure
autoProcessistrueor callprocessSSO()manually
Token validation fails
- Token may have expired (5 minute limit)
- Token may have already been used
- Verify your app secret is correct
Clerk sign-in fails
- Verify Clerk publishable key is correct
- Check if email-based authentication is enabled in Clerk
- Check Clerk dashboard for sign-in errors
CORS errors
- Ensure target app domain is allowed in Kenzo CORS configuration
License
MIT
