npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@krutai/auth

v0.6.1

Published

Authentication package for KrutAI — fetch-based client for your server's auth routes with API key validation

Readme

@krutai/auth

Authentication package for KrutAI — a fetch-based HTTP client that calls your server's /api/lib-auth routes (powered by Better Auth on the server side).

Architecture Note: This package has no local database or Better Auth dependency. Email/password operations call your server's auth routes. The optional server-side Google helper also creates the authorization request and exchanges Google's one-time code before sending the verified ID token to your server. User and session persistence remains on the server.

Features

  • 🔐 API Key Protection — Requires a valid KrutAI API key (validated via krutai)
  • ✉️ Verified Registration — Activates email/password accounts with a six-digit email OTP
  • 🔁 Password Recovery — Resets forgotten passwords with a short-lived email OTP
  • 🔵 Google OAuth — Server-side authorization-code flow with state validation and PKCE
  • 🚀 Better Auth Integration — Calls your server's Better Auth routes
  • 🐘 PostgreSQL Ready — Your server can use any Better Auth-supported database (PostgreSQL, MySQL, etc.)
  • Dual Format — Supports both ESM and CommonJS
  • 🔷 TypeScript First — Full type safety and IntelliSense
  • 🌐 Zero DB Dependencies — No local database driver needed

Installation

npm install @krutai/auth

How It Works

Your App
  └── @krutai/auth (HTTP client)
        └── POST /api/lib-auth/api/auth/sign-up/email  ──► Your Server
                                                          └── better-auth
                                                                └── PostgreSQL

All database operations (user storage, session management, etc.) happen on your server. Google OAuth additionally makes a server-side request to Google's token endpoint; it never stores user or session data locally.

Quick Start

import { KrutAuth } from "@krutai/auth";

const auth = new KrutAuth({
  apiKey: process.env.KRUTAI_API_KEY!,
  serverUrl: "https://your-server.com",
  databaseUrl: process.env.DATABASE_URL!, // sent as x-database-url
});

await auth.initialize(); // validates API key against server

// Sign up. The account remains pending until its email OTP is verified.
const pending = await auth.signUpEmail({
  email: "[email protected]",
  password: "secret123",
  name: "Alice",
});

// Ask the user for the six-digit code sent to their email.
const { token, user } = await auth.verifyEmailOtp({
  email: "[email protected]",
  otp: "123456",
});

// Sign in
const result = await auth.signInEmail({
  email: "[email protected]",
  password: "secret123",
});

// Get session
const session = await auth.getSession(result.token);

// Sign out
await auth.signOut(result.token);

Google OAuth (server-side)

Create and use the Google-enabled client only in backend code. If you omit clientId and clientSecret, Krut uses its own Google client and your app only provides the callback URL.

const auth = new KrutAuth({
  apiKey: process.env.KRUTAI_API_KEY!,
  serverUrl: "https://krut.ai",
  databaseUrl: process.env.DATABASE_URL!,
  google: {
    redirectUri: "https://your-app.com/auth/google/callback",
  },
});

await auth.initialize();

// In the route that starts login:
const oauth = await auth.authorizeGoogleOAuth();
// Redirect the browser to oauth.authorizationUrl.

If your app owns its Google client, pass clientId and clientSecret. Keep the client secret on your backend and register your app's redirectUri in Google Cloud.

const auth = new KrutAuth({
  apiKey: process.env.KRUTAI_API_KEY!,
  serverUrl: "https://krut.ai",
  databaseUrl: process.env.DATABASE_URL!,
  google: {
    clientId: process.env.GOOGLE_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    redirectUri: "https://your-app.com/auth/google/callback",
  },
});

const oauth = auth.startGoogleOAuth();
// Store oauth.state and oauth.codeVerifier in the user's server-side session,
// then redirect the browser to oauth.authorizationUrl.

// In your redirectUri callback route:
const result = await auth.completeGoogleOAuth({
  code: String(request.query.code),
  state: String(request.query.state),
  expectedState: request.session.googleOAuthState,
  codeVerifier: request.session.googleOAuthCodeVerifier,
});

// result.token is the Krut/Better Auth bearer token.

For app-owned credentials, register the exact redirectUri above as an Authorized redirect URI in Google Cloud. For Krut-managed credentials, no app Google client setup is required; Google redirects through the Krut backend callback and then back to your redirectUri.

Forgot password

// This always returns { success: true }, even when the account does not exist.
await auth.requestPasswordReset({ email: "[email protected]" });

await auth.resetPasswordWithOtp({
  email: "[email protected]",
  otp: "123456",
  password: "new-secure-password",
});

Registration-verification and password-reset OTP requests are each limited by the backend to three requests per client IP in a rolling five-minute window. A newly requested code replaces the previous code.

Configuration

import { KrutAuth } from "@krutai/auth";

const auth = new KrutAuth({
  apiKey: "krut_...",          // Required (or set KRUTAI_API_KEY env var)
  serverUrl: "https://...",    // Default: "http://localhost:8000"
  authPrefix: "/api/lib-auth", // Default: "/api/lib-auth"
  databaseUrl: "...",          // Optional: DB connection for better-auth
  google: {                     // Optional; server-side only
    clientId: "...",            // Optional; provide with clientSecret for app-owned Google
    clientSecret: "...",        // Optional; backend only
    redirectUri: "https://your-app.com/auth/google/callback",
    scopes: [],                 // Optional additional scopes
  },
  validateOnInit: true,        // Default: true — set false to skip in tests
});

| Option | Type | Default | Description | |---|---|---|---| | apiKey | string | process.env.KRUTAI_API_KEY | Your KrutAI API key | | serverUrl | string | http://localhost:8000 | Base URL of your server | | authPrefix | string | /api/lib-auth | Path prefix for auth routes | | databaseUrl | string | process.env.DATABASE_URL | Database URL sent to server | | google | GoogleOAuthConfig | — | Google callback URI with optional app-owned client credentials | | validateOnInit | boolean | true | Validate API key on initialize() |

API Reference

Creates a KrutAuth instance.

import { KrutAuth } from "@krutai/auth";
const auth = new KrutAuth({
  apiKey: "...",
  serverUrl: "https://...",
  databaseUrl: "...",
});
await auth.initialize();

KrutAuth class — Methods

| Method | HTTP Call | Description | |---|---|---| | initialize() | validates API key | Must be called before other methods | | signUpEmail(params) | POST /api/lib-auth/api/auth/sign-up/email | Register a new user | | verifyEmailOtp(params) | POST /api/lib-auth/api/auth/email-otp/verify-email | Verify registration and create a session | | resendVerificationOtp(params) | POST /api/lib-auth/api/auth/email-otp/send-verification-otp | Resend the registration OTP | | requestPasswordReset(params) | POST /api/lib-auth/api/auth/email-otp/request-password-reset | Send a password-reset OTP | | resetPasswordWithOtp(params) | POST /api/lib-auth/api/auth/email-otp/reset-password | Set a new password using the OTP | | signInEmail(params) | POST /api/lib-auth/api/auth/sign-in/email | Authenticate a user | | authorizeGoogleOAuth() | POST /api/lib-auth/google/authorize | Start Krut-managed or app-owned Google OAuth through the auth server | | startGoogleOAuth() | — | Generate Google authorization URL, state, and PKCE verifier | | completeGoogleOAuth(params) | Google + POST /api/lib-auth/google/sign-in | Exchange the Google code and create a Krut session | | getSession(token) | GET /api/lib-auth/api/auth/get-session | Retrieve session info | | signOut(token) | POST /api/lib-auth/api/auth/sign-out | Invalidate a session | | request(method, path, body?) | Any | Generic helper for custom endpoints | | isInitialized() | — | Returns boolean |

Types

interface SignUpEmailParams { email: string; password: string; name: string; }
interface SignInEmailParams { email: string; password: string; }
interface VerifyEmailOtpParams { email: string; otp: string; }
interface ResendVerificationOtpParams { email: string; }
interface RequestPasswordResetParams { email: string; }
interface ResetPasswordWithOtpParams { email: string; otp: string; password: string; }
interface GoogleOAuthConfig {
  clientId: string; clientSecret: string; redirectUri: string; scopes?: string[];
}
interface GoogleOAuthAuthorization { authorizationUrl: string; state: string; codeVerifier: string; }
interface CompleteGoogleOAuthParams {
  code: string; state: string; expectedState: string; codeVerifier: string;
}

interface AuthResponse  { token: string; user: AuthUser; }
interface PendingSignUpResponse { token: null; user: AuthUser; }
interface VerifyEmailOtpResponse extends AuthResponse { status: true; }
interface AuthSuccessResponse { success: boolean; }
interface AuthSession   { user: AuthUser; session: AuthSessionRecord; }

interface AuthUser {
  id: string; email: string; name?: string;
  emailVerified: boolean; createdAt: string; updatedAt: string;
}

Environment Variables

Client app (where @krutai/auth is used)

| Variable | Required | Description | |---|---|---| | KRUTAI_API_KEY | ✅ | Your KrutAI API key | | DATABASE_URL | optional | Sent as x-database-url header | | GOOGLE_CLIENT_ID | for app-owned Google OAuth | Read by your app and passed in google.clientId | | GOOGLE_CLIENT_SECRET | for app-owned Google OAuth | Backend-only secret passed in google.clientSecret |

Backend SMTP configuration

The backend sends OTP messages through a generic SMTP server. Credentials belong only on the backend and must never be exposed to client applications.

| Variable | Required | Default | Description | |---|---:|---|---| | SMTP_HOST | ✅ | — | SMTP server hostname | | SMTP_PORT | optional | 587 | SMTP server port | | SMTP_SECURE | optional | true for port 465 | Whether to use implicit TLS | | SMTP_USER | ✅ | — | SMTP username | | SMTP_PASSWORD | ✅ | — | SMTP password or provider app password | | EMAIL_FROM | ✅ | — | Sender email address | | EMAIL_FROM_NAME | optional | — | Sender display name |

Error Handling

import { KrutAuth, KrutAuthKeyValidationError } from "@krutai/auth";

try {
  const auth = new KrutAuth({ apiKey: "invalid-key" });
  await auth.initialize();
} catch (e) {
  if (e instanceof KrutAuthKeyValidationError) {
    console.error("Invalid API key:", e.message);
  } else {
    console.error("Auth error:", e);
  }
}

Custom Endpoints

Use the request() method to call any Better Auth endpoint not covered by the convenience methods:

const data = await auth.request("POST", "/api/auth/some-custom-endpoint", {
  someParam: "value",
});

Skipping Validation in Tests

import { KrutAuth } from "@krutai/auth";

const auth = new KrutAuth({
  apiKey: "test-api-key",
  serverUrl: "http://localhost:8000",
  validateOnInit: false, // Skip server round-trip in tests
});
// No need to call initialize()

Architecture

@krutai/[email protected]
└── dependency: krutai   ← API key format validation (also peerDep)

Your Server
├── better-auth          ← Auth engine
└── pg / postgres        ← PostgreSQL adapter

For Better Auth PostgreSQL setup, see: https://www.better-auth.com/docs/adapters/postgresql

For Better Auth documentation, visit: https://www.better-auth.com/docs

License

MIT