{"id":29417867,"url":"https://github.com/grenish/authrix","last_synced_at":"2026-04-05T22:37:20.657Z","repository":{"id":304006268,"uuid":"1012051404","full_name":"Grenish/authrix","owner":"Grenish","description":"Authrix is a lightweight, TypeScript-first authentication library for Node.js with pluggable database adapters, secure cookie-based sessions, and zero UI bloat.","archived":false,"fork":false,"pushed_at":"2025-07-10T19:43:23.000Z","size":107,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-10T22:05:09.741Z","etag":null,"topics":["bcryptjs","firebase","mongodb","nodejs","npm","postgresql","supabase"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Grenish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"grenish","buy_me_a_coffee":"grenish"}},"created_at":"2025-07-01T18:25:38.000Z","updated_at":"2025-07-10T19:43:27.000Z","dependencies_parsed_at":"2025-07-10T22:05:18.080Z","dependency_job_id":"e1cce8fa-3a32-4b68-a402-8035f9021ae0","html_url":"https://github.com/Grenish/authrix","commit_stats":null,"previous_names":["grenish/authrix"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Grenish/authrix","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grenish%2Fauthrix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grenish%2Fauthrix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grenish%2Fauthrix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grenish%2Fauthrix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Grenish","download_url":"https://codeload.github.com/Grenish/authrix/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Grenish%2Fauthrix/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264905459,"owners_count":23681417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bcryptjs","firebase","mongodb","nodejs","npm","postgresql","supabase"],"created_at":"2025-07-11T22:12:57.307Z","updated_at":"2026-04-05T22:37:20.269Z","avatar_url":"https://github.com/Grenish.png","language":"TypeScript","funding_links":["https://github.com/sponsors/grenish","https://buymeacoffee.com/grenish"],"categories":[],"sub_categories":[],"readme":"# Authrix\r\n\r\n\u003cdiv align=\"center\"\u003e\r\n  \u003cimg src=\"./logo/logo.svg\" alt=\"Authrix Logo\" width=\"220\" height=\"180\" /\u003e\r\n  \u003ch3\u003eUnified, framework‑agnostic authentication for Node.js, TypeScript \u0026 modern runtimes\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\r\n[![npm version](https://img.shields.io/npm/v/authrix.svg)](https://www.npmjs.com/package/authrix)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\r\n[![Tests](https://img.shields.io/badge/Tests-Jest-green.svg)](https://jestjs.io/)\r\n[![Security Focus](https://img.shields.io/badge/Security-Hardened-success.svg)](#security)\r\n\r\nAuthrix provides production‑grade authentication primitives with minimal ceremony: JWT sessions, secure cookie handling, rolling session refresh, password flows, SSO/OAuth, email flows, and extensible adapters. Version 2.1 introduces the **unified `auth` namespace** simplifying the API surface while remaining backward compatible (legacy exports emit one‑time deprecation warnings).\r\n\r\n---\r\n\r\n## TL;DR\r\n\r\n```ts\r\nimport { initAuth, auth } from 'authrix';\r\nimport { mongoAdapter } from 'authrix/adapters/mongo';\r\n\r\ninitAuth({\r\n  jwtSecret: process.env.JWT_SECRET!,\r\n  db: mongoAdapter,\r\n  cookieName: 'auth_token',\r\n  sessionMaxAgeMs: 7 * 24 * 60 * 60 * 1000,\r\n  rollingSessionEnabled: true,\r\n  rollingSessionThresholdSeconds: 15 * 60, // refresh when ≤ 15m left\r\n});\r\n\r\n// Express example\r\napp.post('/api/auth/signup', async (req, res) =\u003e {\r\n  const { email, password } = req.body;\r\n  const { user } = await auth.actions.signup(email, password, { res }); // sets cookie\r\n  res.status(201).json({ success: true, user });\r\n});\r\n\r\napp.post('/api/auth/signin', async (req, res) =\u003e {\r\n  const { email, password } = req.body;\r\n  const { user } = await auth.actions.signin(email, password, { res });\r\n  res.json({ success: true, user });\r\n});\r\n\r\napp.get('/api/auth/me', async (req, res) =\u003e {\r\n  const user = await auth.session.getCurrentUserFromRequest(req); // auto token extract\r\n  if (!user) return res.status(401).json({ success: false, error: 'Not authenticated' });\r\n  res.json({ success: true, user });\r\n});\r\n\r\napp.get('/api/private', auth.middleware.requireAuth, (req, res) =\u003e {\r\n  res.json({ success: true, user: (req as any).user });\r\n});\r\n```\r\n\r\n---\r\n\r\n## Table of Contents\r\n1. [Architecture](#architecture)\r\n2. [Feature Overview](#features)\r\n3. [Installation](#installation)\r\n4. [Initialization \u0026 Configuration](#configuration)\r\n5. [Unified API Surface](#unified-api)\r\n6. [Framework Usage](#framework-usage)\r\n7. [Sessions \u0026 Rolling Refresh](#sessions-and-rolling-refresh)\r\n8. [Cookies \u0026 Security Defaults](#cookies)\r\n9. [OAuth / SSO](#oauth--sso)\r\n10. [Database Adapters](#database-adapters)\r\n11. [Email \u0026 2FA / Forgot Password](#email--2fa--recovery)\r\n12. [Structured Logging](#logging)\r\n13. [Extensibility (Adapters \u0026 Providers)](#extensibility)\r\n14. [Migration (≤2.0 → 2.1)](#migration)\r\n15. [Roadmap](#roadmap)\r\n16. [Contributing](#contributing)\r\n17. [License](#license)\r\n\r\n---\r\n\r\n## Architecture\r\n\r\n```\r\n┌──────────────────────────────────────────────┐\r\n│                    auth                      │  \u003c- unified facade\r\n├──────────────┬───────────────┬───────────────┤\r\n│ actions      │ session       │ middleware    │\r\n│ signup/signin│ token→user    │ require/opt   │\r\n├──────────────┴───────┬───────┴──────┬────────┤\r\n│ handlers (Next.js)   │ cookies util │ env     │\r\n├───────────────────────────────────────────────┤\r\n│ Core Logic (pure functions)                   │\r\n├───────────────────────────────────────────────┤\r\n│ Adapters: Mongo | PostgreSQL | (Prisma WIP)   │\r\n│ Providers: Google | GitHub | ...              │\r\n│ Email: Gmail | SendGrid | Resend | SMTP       │\r\n└───────────────────────────────────────────────┘\r\n```\r\n\r\nDesign principles:\r\n* Pure core (no framework imports) → thin framework façades.\r\n* Minimal public surface; strong defaults; explicit opt‑ins.\r\n* Extensible via small interfaces (db adapter, email provider, oauth provider).\r\n* Predictable error model (`Error` with message; route layer decides JSON shape).\r\n\r\n---\r\n\r\n## Features\r\n\r\n| Area | Highlights |\r\n|------|------------|\r\n| Auth Core | Signup, Signin, Logout, Session inspection |\r\n| Security | Explicit JWT signature validation; cookie normalization; optional rolling refresh |\r\n| Cookies | Central name + normalization (HttpOnly, SameSite=lax, Secure in prod) |\r\n| OAuth/SSO | pluggable providers (Google, GitHub) with state verification |\r\n| Email | Multiple transports (gmail, sendgrid, resend, smtp, console) |\r\n| Recovery | Forgot password + (email) 2FA foundations |\r\n| Adapters | MongoDB, PostgreSQL, Prisma (scaffold) |\r\n| Logging | Structured logger with contextual warnings |\r\n| Extensibility | Simple contracts for adapters/providers/email |\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install authrix\r\n# or yarn add authrix / pnpm add authrix / bun add authrix\r\n```\r\n\r\nPeer deps (install only what you use): `mongodb`, `pg`, `next`, `react`, etc.\r\n\r\n---\r\n\r\n## Configuration\r\n\r\nCall `initAuth` once at application bootstrap (server entry, Next.js edge route, etc.).\r\n\r\n```ts\r\nimport { initAuth } from 'authrix';\r\nimport { mongoAdapter } from 'authrix/adapters/mongo';\r\n\r\ninitAuth({\r\n  jwtSecret: process.env.JWT_SECRET!,      // required, min 32 chars recommended\r\n  db: mongoAdapter,                        // optional if only stateless operations\r\n  cookieName: 'auth_token',                // optional override\r\n  forceSecureCookies: false,               // force Secure attr regardless of NODE_ENV\r\n  sessionMaxAgeMs: 7 * 24 * 60 * 60 * 1000,// absolute lifetime of issued tokens\r\n  rollingSessionEnabled: true,             // enable rolling refresh\r\n  rollingSessionThresholdSeconds: 15 * 60, // refresh when remaining life ≤ threshold\r\n});\r\n```\r\n\r\nConfig fields (selected):\r\n* `jwtSecret` (string, required)\r\n* `db` (adapter) – provides persistence for user lookup \u0026 future session state needs\r\n* `cookieName` (string) – default: `auth_token`\r\n* `sessionMaxAgeMs` (number) – default: 7 days\r\n* `rollingSessionEnabled` (boolean) – off by default if unspecified\r\n* `rollingSessionThresholdSeconds` (number) – default internal heuristic (e.g. 900)\r\n* `forceSecureCookies` (boolean) – override environment heuristic\r\n\r\nAccess at runtime via `auth.config` (read-only snapshot / accessor pattern) if needed.\r\n\r\n---\r\n\r\n## Environment Requirements\r\n\r\n- JWT_SECRET (required)\r\n  - A strong secret used to sign JWTs. Recommended length: 32+ characters.\r\n  - Required in all environments. Authrix will throw if missing when creating tokens.\r\n\r\n- AUTHRIX_PASSWORD_PEPPER (required in production)\r\n  - Additional secret applied during password hashing to harden stored hashes.\r\n  - Production: must be set explicitly. The library throws on startup if missing.\r\n  - Development: if not set, Authrix derives a stable pepper from `jwtSecret` when available; if `jwtSecret` is not yet initialized, a temporary pepper is generated and later upgraded once `jwtSecret` is set. Always configure a real pepper before deploying.\r\n\r\nNotes\r\n- Keep both secrets in a secure secret store (not in source control).\r\n- Rotating `jwtSecret` invalidates existing sessions. Plan for a rotation strategy if needed.\r\n\r\n---\r\n\r\n## Unified API\r\n\r\n```ts\r\nimport { auth } from 'authrix';\r\n\r\nauth.actions.signup(email, password, { res?, autoSignin? });\r\nauth.actions.signin(email, password, { res? });\r\nauth.actions.logout({ res? });\r\n\r\nconst user = await auth.session.getCurrentUserFromToken(token);\r\nconst user2 = await auth.session.getCurrentUserFromRequest(req);\r\nconst { user: refreshed, refreshedToken } = await auth.session.getCurrentUserFromTokenWithRefresh(token);\r\n\r\n// Express / API middleware\r\nauth.middleware.requireAuth(req, res, next); // attaches user → req.user\r\nauth.middleware.optionalAuth(req, res, next);\r\n\r\n// Next.js route handlers (App Router) dynamic helpers\r\nauth.handlers.signup(request);\r\nauth.handlers.signin(request);\r\nauth.handlers.logout(request);\r\nauth.handlers.currentUser(request);\r\n\r\n// Cookie helpers\r\nauth.cookies.name;              // string\r\nauth.cookies.create(token, opts?); // returns Set-Cookie string\r\nauth.cookies.clear();              // logout cookie string\r\n\r\n// Environment insight\r\nauth.env.isNext; auth.env.isNode; auth.env.details; \r\n```\r\n\r\nAll legacy direct exports (e.g. `signupCore`) still work but emit a single deprecation warning (development only).\r\n\r\n---\r\n\r\n## Framework Usage\r\n\r\n### Express\r\n```ts\r\napp.post('/api/auth/signup', async (req, res) =\u003e {\r\n  const { email, password } = req.body;\r\n  const { user } = await auth.actions.signup(email, password, { res });\r\n  res.status(201).json({ success: true, user });\r\n});\r\n\r\napp.get('/api/secure', auth.middleware.requireAuth, (req, res) =\u003e {\r\n  res.json({ success: true, user: (req as any).user });\r\n});\r\n```\r\n\r\n### Next.js (App Router)\r\n```ts\r\n// app/api/auth/signin/route.ts\r\nimport { auth } from 'authrix';\r\nexport const POST = auth.handlers.signin; // returns Response with cookie\r\n\r\n// app/api/auth/me/route.ts\r\nimport { auth } from 'authrix';\r\nexport const GET = auth.handlers.currentUser;\r\n```\r\n\r\n### Universal (Raw Fetch / Edge)\r\nUse `auth.session.getCurrentUserFromToken(token)` after extracting cookie manually if necessary.\r\n\r\n---\r\n\r\n## Sessions and Rolling Refresh\r\n\r\nRolling refresh keeps users active without silent expiration while preserving an absolute max lifetime:\r\n1. Each request (middleware or explicit call) checks remaining lifetime.\r\n2. If `remainingSeconds ≤ rollingSessionThresholdSeconds` and `rollingSessionEnabled`, a new token is issued + cookie updated.\r\n3. Token is still fully signed \u0026 time‑boxed by `sessionMaxAgeMs` at issue time.\r\n\r\nDisable by setting `rollingSessionEnabled: false`.\r\n\r\nEdge cases handled: tampered token → rejection; expired token → null user; refresh only when threshold reached (no churn).\r\n\r\n---\r\n\r\n## Cookies\r\n\r\nDefaults (unless overridden):\r\n* `HttpOnly: true`\r\n* `SameSite: lax`\r\n* `Secure: true` in production OR when `forceSecureCookies` true\r\n* `Path: /`\r\n* `Max-Age` normalized to seconds (internal uses ms; outward always correct)\r\n\r\nHelpers:\r\n```ts\r\nconst headerValue = auth.cookies.create(token, { sameSite: 'strict' });\r\nres.setHeader('Set-Cookie', headerValue);\r\n```\r\n\r\nLogout cookie:\r\n```ts\r\nres.setHeader('Set-Cookie', auth.cookies.clear());\r\n```\r\n\r\n---\r\n\r\n## OAuth / SSO\r\n\r\nProviders (Google, GitHub) reside under `providers/*`. High‑level orchestration lives in core and is exposed via handler helpers (see `docs/OAUTH_USAGE.md`). Unified namespace does not yet encapsulate bespoke OAuth flows; migration planned (see roadmap). For now, continue using documented provider helpers; future minor will add `auth.oauth.*` façade.\r\n\r\n---\r\n\r\n## Database Adapters\r\n\r\nCurrently shipped: MongoDB, PostgreSQL. Prisma scaffold exists (contributions welcome).\r\n\r\nAdapter contract snapshot (simplified):\r\n```ts\r\ninterface AuthDbAdapter {\r\n  createUser(data): Promise\u003cUser\u003e;\r\n  getUserByEmail(email): Promise\u003cUser|null\u003e;\r\n  getUserById(id): Promise\u003cUser|null\u003e;\r\n  updateUser(id, partial): Promise\u003cUser\u003e;\r\n  // plus SSO + password reset helpers\r\n}\r\n```\r\n\r\nNormalization: emails / usernames are lowercased \u0026 trimmed in adapters (maintain this in custom adapters). Duplicate conflicts must throw informative `Error` messages.\r\n\r\n---\r\n\r\n## Email \u0026 2FA / Recovery\r\n\r\nEmail providers selected at config time. See `docs/2FA_EMAIL_SETUP_GUIDE.md` \u0026 `docs/SSO_FORGOT_PASSWORD_GUIDE.md` for end‑to‑end flows. These modules will adopt structured logging fully in upcoming releases (currently partially migrated).\r\n\r\n---\r\n\r\n## Logging\r\n\r\nUse the central logger:\r\n```ts\r\nimport { logger } from 'authrix';\r\nlogger.debug('Auth flow start', { email });\r\nlogger.structuredWarn({\r\n  category: 'deprecation',\r\n  action: 'legacy-signup',\r\n  outcome: 'fallback',\r\n  message: 'signupCore is deprecated; use auth.actions.signup'\r\n});\r\n```\r\n\r\nCategories used so far: `deprecation`, `security`, `adapter`, `session`.\r\n\r\nYou can wrap or replace output by providing a custom transport (see source of `utils/logger.ts`).\r\n\r\n---\r\n\r\n## Extensibility\r\n\r\n| Extension | How |\r\n|-----------|-----|\r\n| DB Adapter | Implement `AuthDbAdapter` and pass to `initAuth` |\r\n| Email Provider | Implement send interface (see existing providers) |\r\n| OAuth Provider | Follow provider module pattern (token exchange + profile map) |\r\n| Middleware | Compose `auth.middleware.requireAuth` inside your framework adapters |\r\n\r\nDesign goals: small, testable, dependency‑light surfaces.\r\n\r\n---\r\n\r\n## Migration\r\n\r\nIf upgrading from ≤2.0.x:\r\n\r\n| Old | New |\r\n|-----|-----|\r\n| `signupCore(email,pw,res?)` | `auth.actions.signup(email,pw,{res})` |\r\n| `signinCore` | `auth.actions.signin` |\r\n| `logoutCore` | `auth.actions.logout` |\r\n| `getCurrentUser(req)` | `auth.session.getCurrentUserFromRequest(req)` |\r\n| scattered cookie helpers | `auth.cookies.*` |\r\n\r\nDeprecations emit once per symbol (non‑prod). Planned removal: 3.0.0 (see roadmap). Begin migrating now; wrappers will persist through at least 2.3.x.\r\n\r\n---\r\n\r\n## Roadmap\r\n\r\nSee also `RELEASE_NOTES_2.1.0.md` for detailed schedule.\r\n\r\n### Near‑Term (2.1.x → 2.2.x)\r\n* Complete structured logging coverage (providers, email).\r\n* Rolling session test matrix \u0026 docs.\r\n* Expanded cookie matrix across runtimes.\r\n* Publish detailed migration guide (FAQ, code mods suggestions).\r\n\r\n### Mid‑Term (2.2.x → 2.3.x)\r\n* Provider observability events (oauth.start/success/failure).\r\n* Finalize Prisma adapter.\r\n* JWT secret rotation helper.\r\n* Enhanced recovery \u0026 2FA audit logging.\r\n\r\n### 3.0.0 Themes\r\n* Remove deprecated exports.\r\n* Optional strict security mode (always secure cookies, enforced config validation).\r\n* Stable machine‑readable error codes + typed error classes.\r\n* Audit event publishing hook.\r\n\r\n---\r\n\r\n## Contributing\r\n\r\n1. Fork \u0026 clone.\r\n2. `npm install`\r\n3. Run tests: `npm test`\r\n4. For significant changes open a draft PR early.\r\n\r\nQuality gates: build (`npm run build`), type checks, Jest. Avoid committing `dist/`.\r\n\r\nIssue labels you can use: `adapter`, `provider`, `security`, `docs`, `enhancement`.\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT © 2025 Authrix Contributors\r\n\r\n---\r\n\r\nNeed help or migration guidance? Open an issue with the `unified-api` label.\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrenish%2Fauthrix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrenish%2Fauthrix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrenish%2Fauthrix/lists"}