Skip to content
/ auth Public

Type-safe, plugin-first authentication core for TypeScript applications.

License

Notifications You must be signed in to change notification settings

oglofus/auth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@oglofus/auth NPM Version Publish Package to NPM

Type-safe, plugin-first authentication core for TypeScript applications.

Features

  • Plugin architecture for auth methods and domain capabilities.
  • Strongly typed register/authenticate payloads inferred from enabled plugins.
  • Path-based issue model ({ message, path }) for field-level error mapping.
  • Built-in methods: password, email OTP, magic link, OAuth2, passkey.
  • Built-in domain plugins: two-factor auth (TOTP/recovery), organizations/RBAC.
  • Framework-agnostic core (works with Next.js, SvelteKit, Workers, Node servers).

Install

npm install @oglofus/auth
pnpm add @oglofus/auth
bun add @oglofus/auth

Optional for app-level integrations:

  • arctic for OAuth providers in your app code.
  • @oslojs/otp if you need direct OTP utilities in your app (the library already uses it internally for TOTP).

Quick Start (Password)

import {
  OglofusAuth,
  passwordPlugin,
  type PasswordCredentialAdapter,
  type SessionAdapter,
  type UserAdapter,
  type UserBase,
} from "@oglofus/auth";

interface AppUser extends UserBase {
  given_name: string;
  family_name: string;
}

const users: UserAdapter<AppUser> = /* your adapter */;
const sessions: SessionAdapter = /* your adapter */;
const credentials: PasswordCredentialAdapter = /* your adapter */;

const auth = new OglofusAuth({
  adapters: { users, sessions },
  plugins: [
    passwordPlugin<AppUser, "given_name" | "family_name">({
      requiredProfileFields: ["given_name", "family_name"] as const,
      credentials,
    }),
  ] as const,
  validateConfigOnStart: true,
});

const registered = await auth.register({
  method: "password",
  email: "nikos@example.com",
  password: "super-secret",
  given_name: "Nikos",
  family_name: "Gram",
});

const loggedIn = await auth.authenticate({
  method: "password",
  email: "nikos@example.com",
  password: "super-secret",
});

Core API

OglofusAuth exposes:

  • discover(input, request?)
  • register(input, request?)
  • authenticate(input, request?)
  • method(pluginMethod) for plugin-specific APIs
  • verifySecondFactor(input, request?)
  • completeProfile(input, request?)
  • setActiveOrganization(sessionId, organizationId, request?)
  • validateSession(sessionId, request?)
  • signOut(sessionId, request?)

Result and Error Shape

All operations return structured results.

if (!result.ok) {
  console.log(result.error.code); // e.g. "INVALID_INPUT"
  console.log(result.error.status); // HTTP-friendly status code
  console.log(result.issues); // path-based issues
}

Issue format:

type Issue = {
  message: string;
  path?: ReadonlyArray<PropertyKey | { key: PropertyKey } | { index: number }>;
};

You can build issues with helpers:

import { createIssue, createIssueFactory } from "@oglofus/auth";

const issue = createIssueFactory<{ email: string; profile: unknown }>([
  "email",
  "profile",
] as const);
issue.email("Email is required");
issue.$path(
  ["profile", { key: "addresses" }, { index: 0 }, "city"],
  "City is required",
);
createIssue("Generic failure");

Built-in Plugins

Password

  • Method: "password"
  • Register + authenticate supported.
  • Config: requiredProfileFields, credentials adapter.

Email OTP

  • Method: "email_otp"
  • Two-step flow with plugin API:
    1. auth.method("email_otp").request({ email })
    2. auth.authenticate(...) or auth.register(...) with challengeId + code

Magic Link

  • Method: "magic_link"
  • Two-step flow with plugin API:
    1. auth.method("magic_link").request({ email })
    2. auth.authenticate(...) or auth.register(...) with token

OAuth2 (Arctic)

  • Method: "oauth2"
  • Uses provider clients with validateAuthorizationCode(...) (Arctic-compatible).
  • Supports profile completion when required fields are missing.
import { Google } from "arctic";
import { oauth2Plugin } from "@oglofus/auth";

const google = new Google(process.env.GOOGLE_CLIENT_ID!, process.env.GOOGLE_CLIENT_SECRET!, process.env.GOOGLE_REDIRECT_URI!);

oauth2Plugin<AppUser, "google", "given_name" | "family_name">({
  providers: {
    google: {
      client: google,
      resolveProfile: async ({ tokens }) => {
        const res = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
          headers: { Authorization: `Bearer ${tokens.accessToken()}` },
        });
        const p = await res.json() as {
          sub: string;
          email?: string;
          email_verified?: boolean;
          given_name?: string;
          family_name?: string;
        };
        return {
          providerUserId: p.sub,
          email: p.email,
          emailVerified: p.email_verified,
          profile: {
            given_name: p.given_name ?? "",
            family_name: p.family_name ?? "",
          },
        };
      },
      // pkceRequired defaults to true
    },
  },
  accounts: /* OAuth2AccountAdapter<"google"> */,
  requiredProfileFields: ["given_name", "family_name"] as const,
});

const result = await auth.authenticate({
  method: "oauth2",
  provider: "google",
  authorizationCode: "code-from-callback",
  redirectUri: process.env.GOOGLE_REDIRECT_URI!,
  codeVerifier: "pkce-code-verifier",
});

Passkey

  • Method: "passkey"
  • Register + authenticate supported.
  • Config: requiredProfileFields, passkeys adapter.

Two-Factor (Domain Plugin)

  • Method: "two_factor"
  • Adds post-primary verification (TWO_FACTOR_REQUIRED).
  • Uses @oslojs/otp internally for TOTP verification and enrollment URI generation.
  • Plugin API:
    • beginTotpEnrollment(userId)
    • confirmTotpEnrollment({ enrollmentId, code })
    • regenerateRecoveryCodes(userId)

Organizations (Domain Plugin)

  • Method: "organizations"
  • Multi-tenant orgs, memberships, role inheritance, feature/limit entitlements, invites.
  • Validates role topology on startup (default role, owner role presence, inheritance cycles).

Account Discovery

Use discover(...) to support login/register routing logic before full auth:

  • private mode: generic non-enumerating response.
  • explicit mode: returns account-aware actions (continue_login, redirect_register, redirect_login).

explicit mode requires an identity adapter.

Examples

See ready-to-copy integrations:

Scripts

pnpm run typecheck
pnpm run test
pnpm run build

Development

  • Build: pnpm run build (outputs to dist/)
  • TypeScript config: tsconfig.json

License

ISC License. See the LICENSE file for details.

Links

About

Type-safe, plugin-first authentication core for TypeScript applications.

Resources

License

Stars

Watchers

Forks

Packages