Get your keys from the Application dashboard
Go to Admin → Application in your Kynetra dashboard. Copy your pk_live_… publishable key, rotate a secret key, add your origin and callback URL to the allowlists.
Publishable key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Secret key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ← rotate once, store server-side
Allowed origin: https://yoursite.com
Allowed redirect: https://yoursite.com/callbackOption A — Hosted sign-in page (no SDK)
The simplest path. Redirect users to Kynetra's hosted sign-in page. It shows your branding, your enabled providers, and returns tokens to redirect_url as a URL fragment.
<!-- Redirect the user: -->
<a href="https://auth.kynetra.dev/sign-in?pk=pk_live_YOUR_KEY&redirect_url=https://yoursite.com/callback">
Sign in
</a>After sign-in the user lands on https://yoursite.com/callback#access_token=…&refresh_token=…&tenant_id=…. Parse the fragment on your callback page.
// callback page
const params = new URLSearchParams(location.hash.slice(1));
const accessToken = params.get('access_token');
const tenantId = params.get('tenant_id');
if (accessToken) {
localStorage.setItem('kynetra_token', accessToken);
window.location.href = '/dashboard';
}Option B — Vanilla JS SDK (script tag)
Drop one <script> tag into any HTML page. No npm, no build step. The global Kynetra() factory handles fetching config, rendering buttons, and storing tokens.
<script src="https://auth.kynetra.dev/sdk/kynetra.js"></script>
<div id="kynetra-signin"></div>
<script>
const auth = Kynetra({ publishableKey: 'pk_live_YOUR_KEY' });
// Auto-fetch enabled providers and render branded buttons
auth.mount('#kynetra-signin', {
redirectUrl: 'https://yoursite.com/callback',
});
</script>Option C — React / Next.js (@kynetra/react)
The React package wraps the same logic with a context provider, hooks, and UI components. npm publish is deferred — see the SDK reference for CDN usage.
import { KynetraProvider } from '@kynetra/react';
export default function RootLayout({ children }) {
return (
<KynetraProvider publishableKey="pk_live_YOUR_KEY">
{children}
</KynetraProvider>
);
}Verify tokens on your server
Use the introspection endpoint — pass your secret key as a Bearer token and the user's access token in the body. The endpoint validates the signature, checks the tenant binding, and returns the active claims. Never verify tokens in the browser.
const res = await fetch('https://api.auth.kynetra.dev/api/auth/introspect', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.KYNETRA_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ token: accessToken }),
});
const { active, sub, email, tid, roles, scope, exp } = await res.json();
if (!active) return res.status(401).json({ error: 'Unauthorized' });
// sub = user ID, tid = tenant IDNote: JWKS / RS256 local verification is a documented fast-follow. For now, introspection is the only server-side verification path.
Add more auth methods
Once social login is working, layer on additional factors.
Migrating from Clerk / Auth0 / NextAuth?
Kynetra is designed as a drop-in replacement. The hosted sign-in flow mirrors Clerk's Account Portal. The @kynetra/react component API mirrors Clerk's React SDK shape (<SignedIn>, <SignedOut>, useUser(), <UserButton>). Full migration guide in the architecture overview.