@hopak/auth
v1.0.1
Published
Authentication for Hopak.js — JWT, credential signup/login, OAuth (GitHub + Google), and role-based access control.
Downloads
28
Maintainers
Readme
@hopak/auth
Authentication for Hopak.js — JWT, credential signup/login, role-based access control, and OAuth (GitHub + Google).
hopak use auth # scaffolds the model, routes and middleware
# or
bun add @hopak/auth jose📖 Docs: hopak.dev/docs/packages/auth
The pieces
// app/middleware/auth.ts — call once, export the pair
import { jwtAuth } from '@hopak/auth';
export const { requireAuth, signToken } = jwtAuth({
secret: process.env.JWT_SECRET!,
claims: ['id', 'role'],
});// app/routes/api/auth/login.ts
import { credentialsLogin } from '@hopak/auth';
import { defineRoute } from '@hopak/core';
import user from '../../../models/user';
import { signToken } from '../../../middleware/auth';
export const POST = defineRoute({
handler: credentialsLogin({ model: user, sign: signToken }),
});// app/routes/api/admin.ts — gate a route
import { requireRole } from '@hopak/auth';
import { defineRoute } from '@hopak/core';
import { requireAuth } from '../../middleware/auth';
export const GET = defineRoute({
before: [requireAuth(), requireRole('admin')],
handler: () => ({ ok: true }),
});requireAuth() populates ctx.user; the type is added to RequestContext by module augmentation, so ctx.user?.role is typed wherever this package is imported.
Security posture
- Algorithms are pinned on verify — a token signed with a different algorithm is rejected, closing algorithm-confusion attacks.
- Login is uniform — unknown user and wrong password return the same message and cost the same hash verification, so response timing doesn't leak whether an account exists.
- OAuth
stateis an HMAC over{nonce, exp}with a 5-minute TTL, compared in constant time. No session store needed. - PKCE — the code verifier is bound to the browser through an HttpOnly cookie. On by default for Google, opt-in for GitHub (
pkce: true). - GitHub private emails resolve through
/user/emailswhen the profile hides the address. hashPasswordis idempotent — safe to call in a modelbeforeCreatehook even thoughcredentialsSignupalso hashes, so the two never produce a double hash.
Requirements
Bun ≥ 1.3, @hopak/core, and jose (peer dependencies).
Author
Volodymyr Press · [email protected]
License
MIT.
