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

@tango-ts/contrib-auth

v0.9.0

Published

Batteries-included auth app for Tango: User and AuthToken models, password hashing, token issuing routes, and a ready-made authentication class.

Downloads

1,308

Readme

@tango-ts/contrib-auth

Responsibility

The batteries-included auth app (Tango's django.contrib.auth + rest_framework.authtoken): a built-in User model with secure password hashing, a database-backed opaque AuthToken model, token-issuing routes (/login/, /logout/, /me/), and a ready-made Authentication class that plugs into viewsets. It is NOT responsible for the authentication/permission interfaces (those live in @tango-ts/auth), nor for OAuth/social login or JWT issuance — those are layers on top.

What it responds to

  • authRoutes() produces a Router of Web RequestResponse handlers.
  • authTokenAuthentication() fulfills the Authentication contract from @tango-ts/auth (consumed by ModelViewSet's authentication option).
  • app (via @tango-ts/contrib-auth/app) fulfills the TangoApp contract for the CLI: tango migrate --app node_modules/@tango-ts/contrib-auth/dist/app.js applies the shipped migrations.

Functionality

  • User model (auth_users): email login, pbkdf2_sha256 password hashes in Django's exact encoded format, isActive / isStaff / isSuperuser flags that power IsAdminUser, dateJoined, lastLogin.
  • AuthToken model (auth_tokens): opaque tango_-prefixed bearer tokens. Only the SHA-256 of a token is stored; plaintext is returned once at issue time. Optional expiry (expiresAt) and lastUsedAt tracking (throttled to one write per minute per token).
  • createUser / createSuperuser / authenticateUser (timing-safe against user enumeration). tango createsuperuser (in @tango-ts/cli) wraps createSuperuser for bootstrap.
  • issueToken / revokeToken / verifyAuthToken.
  • authRoutes(): POST /login/ ({ email, password }{ token, user }), POST /logout/ (revokes the presented token), GET /me/ (an apiView running the standard pipeline).
  • Plays with project-level auth: pass authentication: [authTokenAuthentication()] to defineServer/defineProject and ctx.user is set on every route and viewset without per-route wiring.
  • Shipped migration 0001_initial in migrations/ (packaged with the npm tarball). FKs are declared with dbConstraint: false so the schema deploys on PlanetScale/Vitess; token verification re-fetches the user row, so deleted/deactivated users lose access without a database cascade.

Design patterns that matter here

  • Serverless: no module-level mutable state; every request resolves tokens through the ORM's request-scoped connection.
  • Runtime-agnostic crypto: WebCrypto only (crypto.subtle, crypto.getRandomValues) — no node:crypto in the runtime entrypoint. The one Node-specific module (src/app.ts, which resolves the packaged migrations directory) is a separate export (./app) used by the CLI.
  • Django parity: password hashes use Django's storage format (pbkdf2_sha256$<iterations>$<salt>$<b64>), so hashes migrate between Django and Tango projects unchanged.
  • Secrets are hashed at rest: never store a plaintext token or password; never put the password hash on ctx.user or in a response.
  • Indistinguishable login failures: unknown email, wrong password, and inactive account all return the same 400 with comparable timing.

Public contract

index.ts exports: User, AuthToken, models, publicUser, hashPassword, verifyPassword, generateToken, hashToken, createUser, createSuperuser, authenticateUser, issueToken, revokeToken, verifyAuthToken, authTokenAuthentication, authRoutes, and their option/row types. ./app exports the TangoApp. Nothing else may be imported from outside.

Testing

  • Unit: test/hashers.test.ts (round-trips, malformed hashes, the published PBKDF2-HMAC-SHA256 test vector, Django format), test/tokens.test.ts (entropy/format, SHA-256 cross-checked against node:crypto).
  • Integration (real MySQL): test/contrib-auth.integration.test.ts applies the shipped migration via migrateApp, then exercises login → protected viewset → /me/ → logout end to end, plus expiry, deactivation, and IsAdminUser enforcement.
  • Parity (vs Django/DRF oracle): password hash format is Django's; a hash generated by either side verifies on the other.