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

@tjoc/auth

v8.0.1

Published

Cognito-first JWT verification and auth primitives for the tjoc.dev portfolio

Downloads

1,231

Readme

@tjoc/auth

Cognito-first JWT verification and authentication primitives for the tjoc.dev portfolio.

v3.x is deprecated. v3 shipped real security defects and was incompatible with the portfolio's Cognito + Lambda reality. See ADR 0003 for the full rationale.

What this is

  • RS256 JWT verification via JWKS — no secrets in code, ever
  • AWS Cognito helpers — pre-wired verifier handling the access/id token distinction correctly
  • API Gateway authorizer adapters (HTTP API v2 + REST API v1)
  • Test helpers — in-memory key sets, signed JWTs, fake verifier

What this is not

  • Does not own passwords, sessions, 2FA, OAuth, account lockout, or rate limiting — that is Cognito's job
  • Does not open network connections or read env vars at import time — zero top-level side effects

Installation

pnpm add @tjoc/auth

Node ≥20. Published to npm (@tjoc/[email protected] on dist-tag pre; latest still points to v3 until the 2-week pilot in jobs.tjoc.dev completes on 2026-05-15).

# Install the pre-release pilot version explicitly:
pnpm add @tjoc/auth@pre

Lambda authorizer (the common case)

// authorizer/index.ts
import { createCognitoVerifier } from '@tjoc/auth/cognito';
import { apiGatewayAuthorizer } from '@tjoc/auth/lambda';

const verifier = createCognitoVerifier({
  region: 'eu-west-1',
  userPoolId: process.env.COGNITO_USER_POOL_ID!,
  clientId: process.env.COGNITO_CLIENT_ID!,
  tokenUse: 'access',
});

export const handler = apiGatewayAuthorizer({ verifier });

SAM template.yaml:

Auth:
  DefaultAuthorizer: CognitoAuthorizer
  Authorizers:
    CognitoAuthorizer:
      FunctionArn: !GetAtt AuthorizerFunction.Arn
      AuthorizerPayloadFormatVersion: "2.0"
      EnableSimpleResponses: true

The Principal lands in downstream Lambdas at event.requestContext.authorizer.lambda:

const { sub, groups } = event.requestContext.authorizer.lambda;
const parsedGroups: string[] = JSON.parse(groups);

REST API (v1) authorizer

import { restApiAuthorizer } from '@tjoc/auth/lambda';
export const handler = restApiAuthorizer({ verifier });

Core verifier (framework-agnostic)

import { verifyJwt, createJwksClient } from '@tjoc/auth';

const jwks = createJwksClient({ jwksUri: 'https://.../.well-known/jwks.json' });

const principal = await verifyJwt(token, {
  jwks,
  issuer: 'https://cognito-idp.eu-west-1.amazonaws.com/eu-west-1_xxxxx',
  audience: 'my-client-id',  // omit for Cognito access tokens
  algorithms: ['RS256'],
});

Error handling

Every error extends AuthError and carries a typed code:

import { AuthError, TokenExpiredError } from '@tjoc/auth';

try {
  await verifyJwt(token, opts);
} catch (err) {
  if (err instanceof TokenExpiredError) return res.status(401).json({ error: 'token_expired' });
  if (err instanceof AuthError) return res.status(401).json({ error: err.code });
  throw err;
}

| Class | Code | When | |---|---|---| | TokenExpiredError | TOKEN_EXPIRED | exp is in the past | | TokenInvalidError | TOKEN_INVALID | Tampered, malformed, or bad signature | | IssuerMismatchError | ISSUER_MISMATCH | iss doesn't match | | AudienceMismatchError | AUDIENCE_MISMATCH | aud / client_id doesn't match | | KidNotFoundError | KID_NOT_FOUND | JWKS has no key for this kid | | AlgorithmNotAllowedError | ALGORITHM_NOT_ALLOWED | alg:none or non-allow-listed algorithm | | ClaimsInvalidError | CLAIMS_INVALID | Missing required claim (sub, iss, exp) |

Testing in product code

import { generateTestKeyPair, signTestJwt, createFakeVerifier } from '@tjoc/auth/testing';

const kp = await generateTestKeyPair();
const verifier = createFakeVerifier({
  keyPair: kp,
  issuer: 'https://cognito-idp.eu-west-1.amazonaws.com/eu-west-1_test',
  tokenUse: 'access',
});

const token = await signTestJwt(kp, { groups: ['admin'] });
const principal = await verifier(token);

Subpath exports

| Import | Contents | |---|---| | @tjoc/auth | verifyJwt, createJwksClient, extractPrincipal, all error classes, all types | | @tjoc/auth/cognito | createCognitoVerifier, CognitoVerifierConfig | | @tjoc/auth/lambda | apiGatewayAuthorizer, restApiAuthorizer, AuthContext | | @tjoc/auth/testing | generateTestKeyPair, signTestJwt, createInMemoryJwksClient, createFakeVerifier |

Security baseline

  • No fallback secrets — missing config throws at construction, never defaults to an insecure value
  • Algorithm allow-list defaults to ['RS256']alg:none and HMAC algorithms rejected before key lookup
  • iss, aud, exp, nbf, kid all enforced — clock skew defaults to 5 seconds
  • No top-level side effects — importing this package opens no sockets and reads no env vars
  • JWKS cache TTL defaults to 10 minutes with 30-second cooldown on unknown kid

Adoption status

| Product | Status | |---|---| | jobs.tjoc.dev | Pilot live since 2026-05-01 (middleware/auth.ts, routes/jobs.ts) | | star.club | After GA (2026-05-15) — createCognitoVerifier swap in post-confirmation Lambda | | wisecv | Deferred to ADR 0007 Phase 4 |

Phase 2 (Express/Hono/Fastify adapters) ships after the pilot window closes.