New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@ratio1/cstore-auth-ts

Package Overview
Dependencies
Maintainers
2
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ratio1/cstore-auth-ts

Plug-and-play authentication layer for Ratio1 CStore hashes. This TypeScript library wraps the official [@ratio1/ratio1-sdk-ts](https://github.com/Ratio1/ratio1-sdk-ts) SDK, providing a minimal API to bootstrap an admin account and manage simple username/

latest
Source
npmnpm
Version
0.6.1
Version published
Maintainers
2
Created
Source

@ratio1/cstore-auth-ts

Plug-and-play authentication layer for Ratio1 CStore hashes. This TypeScript library wraps the official @ratio1/ratio1-sdk-ts SDK, providing a minimal API to bootstrap an admin account and manage simple username/password credentials.

Features

  • Hash-backed user store with Argon2id hashing and automatic Node.js scrypt fallback
  • Strict username validation and canonicalisation (lowercase keys)
  • Admin bootstrap workflow driven by environment variables
  • Strong typing, unit tests (Vitest), linting, and dual ESM/CJS builds via tsup
  • Works in Node.js services and Next.js API routes

Installation

pnpm add @ratio1/cstore-auth-ts
# or
npm install @ratio1/cstore-auth-ts

Required environment variables

VariableDescription
R1EN_CSTORE_AUTH_HKEYHash key that stores all user records (e.g. auth:default).
R1EN_CSTORE_AUTH_SECRETLong-lived server-side pepper mixed into password hashes.
R1EN_CSTORE_AUTH_BOOTSTRAP_ADMIN_PWDOne-time bootstrap password for the initial admin user. Required until the admin account exists.

Note: Legacy environment variable names (EE_CSTORE_AUTH_HKEY, EE_CSTORE_AUTH_SECRET, EE_CSTORE_AUTH_BOOTSTRAP_ADMIN_PW) are still supported for backwards compatibility but are deprecated.

Quick start

import { CStoreAuth } from '@ratio1/cstore-auth-ts';

const auth = new CStoreAuth();
await auth.simple.init();

await auth.simple.createUser('alice', 'S3curePassw0rd', {
  metadata: { email: 'alice@example.com' }
});

const user = await auth.simple.authenticate('alice', 'S3curePassw0rd');
console.log(user);
// → { username: 'alice', role: 'user', metadata: { email: 'alice@example.com' }, createdAt: '...', updatedAt: '...', type: 'simple' }

// Retrieve all users
const allUsers = await auth.simple.getAllUsers();
console.log(`Total users: ${allUsers.length}`);
allUsers.forEach((u) => console.log(`- ${u.username} (${u.role})`));

// Update user metadata or role
// IMPORTANT: Implement authorization checks in your application layer!
// Example: Only allow users to edit themselves or admins to edit anyone
await auth.simple.updateUser('alice', {
  metadata: { email: 'newemail@example.com', verified: true }
});

// Change password (requires current password)
await auth.simple.changePassword('alice', 'S3curePassw0rd', 'NewP@ssw0rd!');

Public API

interface CStoreAuthOptions {
  hkey?: string;
  secret?: string;
  client?: CStoreLikeClient;
  hasher?: PasswordHasher;
  now?: () => Date;
  logger?: Pick<Console, 'debug' | 'info' | 'warn' | 'error'>;
}

class CStoreAuth {
  constructor(opts?: CStoreAuthOptions);

  simple: {
    init(): Promise<void>;
    createUser<TMeta = Record<string, unknown>>(
      username: string,
      password: string,
      opts?: CreateUserOptions<TMeta>
    ): Promise<PublicUser<TMeta>>;
    authenticate<TMeta = Record<string, unknown>>(
      username: string,
      password: string
    ): Promise<PublicUser<TMeta>>;
    getUser<TMeta = Record<string, unknown>>(username: string): Promise<PublicUser<TMeta> | null>;
    getAllUsers<TMeta = Record<string, unknown>>(): Promise<PublicUser<TMeta>[]>;
    updateUser<TMeta = Record<string, unknown>>(
      username: string,
      opts: UpdateUserOptions<TMeta>
    ): Promise<PublicUser<TMeta>>;
    changePassword(username: string, currentPassword: string, newPassword: string): Promise<void>;
  };
}

Errors are surfaced as descriptive subclasses (EnvVarMissingError, AuthInitError, InvalidUsernameError, InvalidCredentialsError, UserExistsError, UserNotFoundError, etc.).

Authorization Patterns

⚠️ IMPORTANT: updateUser does not enforce authorization. You must implement authorization checks in your application layer.

// Example: Users can edit themselves, admins can edit anyone
async function updateUserWithAuth(
  currentUser: PublicUser,
  targetUsername: string,
  updates: UpdateUserOptions
) {
  // Check if user is editing themselves OR is an admin
  const isEditingSelf = currentUser.username === targetUsername;
  const isAdmin = currentUser.role === 'admin';

  if (!isEditingSelf && !isAdmin) {
    throw new Error('Unauthorized: You can only edit your own profile');
  }

  // Only admins can change roles
  if (updates.role && !isAdmin) {
    throw new Error('Unauthorized: Only admins can change roles');
  }

  return await auth.simple.updateUser(targetUsername, updates);
}

// Example: Express.js middleware
app.put('/api/users/:username', async (req, res) => {
  const currentUser = req.session.user; // From authenticated session
  const { username } = req.params;
  const updates = req.body;

  try {
    // Authorization check
    if (currentUser.username !== username && currentUser.role !== 'admin') {
      return res.status(403).json({ error: 'Forbidden' });
    }

    // Only admins can change roles
    if (updates.role && currentUser.role !== 'admin') {
      return res.status(403).json({ error: 'Only admins can change roles' });
    }

    const updated = await auth.simple.updateUser(username, updates);
    res.json(updated);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Security notes

Password Security

  • Argon2id (via @node-rs/argon2) is used when available. The module automatically downgrades to Node's built-in crypto.scrypt with strong defaults when Argon2 cannot load.
  • Each user receives a random 16-byte salt and a global pepper (R1EN_CSTORE_AUTH_SECRET).
  • Password hashes are stored versioned to enable future migrations.
  • changePassword always requires current password verification.
  • Secrets and hash material never leave the module through logs.

Authorization

  • ⚠️ updateUser does NOT enforce authorization - implement checks in your application layer
  • Recommended pattern: Users can edit themselves, admins can edit anyone
  • Role changes should be restricted to admins only
  • Consider field-level permissions (e.g., users can't set verified: true on themselves)

Data Validation

  • Usernames are canonicalised to lowercase and must match [a-z0-9._-]{3,64}.
  • Validation happens on every entry point.
  • Only metadata is returned publicly (passwords never exposed).

Development

pnpm install
pnpm run lint
pnpm test                  # Run unit tests
pnpm run test:integration  # Run integration tests
pnpm run test:all          # Run all tests
pnpm run build
pnpm run docs

Testing

The project includes two test suites:

  • Unit tests (test/**/*.spec.ts): Fast, isolated tests with mocked dependencies
  • Integration tests (test/integration/**/*.integration.spec.ts): Complete workflow tests with realistic cleanup patterns

Integration tests follow best practices including:

  • Cleanup before and after each test (setting values to null before deletion)
  • Isolated test environments with unique hash keys
  • Serial execution to avoid race conditions
  • Extended timeouts for password hashing operations

See test/integration/README.md for detailed integration testing documentation.

Typedoc emits HTML documentation to docs/. GitHub Actions (see .github/workflows/ci.yml) runs linting, type-checking, tests, build, and docs generation on Node.js 18 and 20.

Roadmap

  • Additional providers (Google, OAuth 2.0) alongside the current simple method
  • Session issuance (JWT/cookies) and rate limiting/lockouts
  • Password rotation and secret (pepper) rotation workflows
  • Multi-tenant or namespaced user separation

FAQs

Package last updated on 13 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts