@dravyn/auth-js
v0.4.1
Published
Official JS/React SDK for Dravyn Auth — register/login/OTP/MFA/orgs, matches the Dravyn Auth backend API exactly.
Readme
@dravyn/auth-js
Official JS/React SDK for Dravyn Auth — register, OTP verification, login, MFA, sessions, organisations, and Google/GitHub OAuth, matching the Dravyn Auth backend API exactly.
Installation
npm install @dravyn/auth-jsPeer dependency: react >=18 — only required if you use the @dravyn/auth-js/react entry point. The core client works in any JS environment (Node, React Native, vanilla browser).
Quick start (framework-agnostic)
import { DravynAuthClient } from '@dravyn/auth-js';
const auth = new DravynAuthClient({
baseUrl: 'https://your-dravyn-auth-instance.com',
publicKey: 'pk_your_project_key', // omit to use the deployment's default project
});
await auth.register('[email protected]', 'correct-horse-battery-staple');
await auth.verifyOtp('[email protected]', '123456'); // signs in on success
// login() returns the user, OR { mfaRequired: true, mfaToken } if MFA is enabled
const result = await auth.login('[email protected]', 'correct-horse-battery-staple');
if ('mfaRequired' in result) {
await auth.completeMfaChallenge(result.mfaToken, '482913');
}
// Roles/permissions are on the user object — no extra API call needed
const me = auth.getUser(); // { id, email, roles: ['admin'], permissions: [...], ... }
// Authenticated fetch helper for calling your own backend
const res = await auth.fetchAuthed('/api/my-endpoint'); // attaches + refreshes the bearer tokenReact
import { AuthProvider, useAuth } from '@dravyn/auth-js/react';
function Root() {
return (
<AuthProvider baseUrl="https://your-dravyn-auth-instance.com" publicKey="pk_...">
<App />
</AuthProvider>
);
}
function LoginForm() {
const { login, completeMfaChallenge, user, isAuthenticated, logout } = useAuth();
// login(email, password) → throws DravynAuthError on failure, with .code
}Wrap anything behind auth in <ProtectedRoute fallback={<LoginForm />}>.
Tokens persist to localStorage by default. For React Native / Expo, pass a storage adapter backed by @react-native-async-storage/async-storage:
new DravynAuthClient({
baseUrl: '...',
storage: {
getItem: AsyncStorage.getItem,
setItem: AsyncStorage.setItem,
removeItem: AsyncStorage.removeItem,
},
});MFA
const { qrCodeDataUrl, secret } = await auth.setupMfa();
// render qrCodeDataUrl as an <img>, user scans it with their authenticator app, then:
const { backupCodes } = await auth.confirmMfaSetup('482913'); // show these once
await auth.disableMfa();Organizations
const org = await auth.createOrg('Acme Workspace');
await auth.inviteOrgMember(org.id, '[email protected]');
const orgs = await auth.listOrgs();
const members = await auth.listOrgMembers(org.id);OAuth (Google / GitHub)
window.location.href = auth.getGoogleUrl(); // or auth.getGithubUrl()
// On the page the provider redirects back to:
const user = await auth.completeOAuthFromUrl(); // reads window.location, signs inSessions
const sessions = await auth.listSessions(); // device, IP, last active
await auth.revokeSession(sessionId);Errors
Every failed call throws DravynAuthError, with .message, .code, .status, and .details:
import { DravynAuthError } from '@dravyn/auth-js';
try {
await auth.login(email, password);
} catch (err) {
if (err instanceof DravynAuthError && err.code === 'INVALID_CREDENTIALS') {
// ...
}
}License
MIT
