The Auth0 Node.js SDK v7 is a TypeScript-based Management-API-only SDK. Authentication has moved to @auth0/auth0-auth-js. The codebase uses Fern-generated code for the Management API with custom wrappers.
Key Capabilities:
- Management API client for tenant administration and user management
- Dual module system supporting both CommonJS and ESM
- TypeScript-first with comprehensive type definitions
- Legacy v4 compatibility layer for migration
# Install dependencies
yarn install
# Build both CommonJS and ESM distributions
yarn build
# Build only CommonJS
yarn build:cjs
# Build only ESM (includes .mjs renaming)
yarn build:esm
# Run all tests
yarn test
# Run specific test suites
yarn test:unit # Unit tests (src/management/tests)
yarn test:browser # Browser environment tests
yarn test:wire # Integration tests with mock server
# Run linter
yarn lint
# Fix linting issues
yarn lint:fix
# Generate documentation
yarn docs
# Validate entire project (lint, format, build, test)
yarn validateCommon operations for working with the SDK:
# Build and test after changes
yarn build && yarn test
# Run tests with coverage
yarn test:coverage
# Watch mode for development (use specific TypeScript configs)
tsc --project ./tsconfig.cjs.json --watch
# Test specific functionality
yarn test:unit -- --testNamePattern="ManagementClient"
# Run linter with auto-fix
yarn lint:fix
# Format code
yarn format- Source TypeScript files live in
src/ - Compiled output goes to
dist/cjs/(CommonJS) anddist/esm/(ESM) - ESM build automatically renames
.js→.mjsand.d.ts→.d.mts - Always run
yarn buildbefore testing SDK changes - Use TypeScript project references for different build targets
src/ # TypeScript source
├── index.ts # Main SDK exports
├── utils.ts # Shared utilities
├── management/ # Management API client
│ ├── Client.ts # Fern-generated client (READ-ONLY)
│ ├── api/ # Fern-generated API definitions (READ-ONLY)
│ ├── wrapper/ # Custom wrapper classes (SAFE TO EDIT)
│ │ └── ManagementClient.ts # Main Management API wrapper
│ ├── request-options.ts # Helper functions for API calls
│ └── tests/ # Management API tests
├── lib/ # Shared libraries and utilities
└── auth0/ # Legacy compatibility exports
- Use strict TypeScript configuration (see
tsconfig.base.json) - Define shared types in
src/lib/models.ts - Follow existing patterns for API client implementations
- Use proper async/await patterns, avoid callbacks
- Import with
.jsextensions (TypeScript will resolve to.ts)
Every API client follows this structure:
class ApiClient {
constructor(options: ClientOptions) {
// Initialize with domain, credentials, etc.
}
async methodName(params: MethodParams): Promise<Response> {
// Implementation with proper error handling
}
}CRITICAL: Never edit Fern-generated files directly.
// ❌ Don't edit: src/management/Client.ts (Fern-generated)
// ✅ Use: src/management/wrapper/ManagementClient.ts
export class ManagementClient {
private _client: FernClient;
constructor(options: ManagementClientOptions) {
this._client = new FernClient(options);
// Custom logic, token handling, telemetry
}
}Use helper functions from src/management/request-options.ts:
import { withTimeout, withRetries, withHeaders, CustomDomainHeader } from "auth0";
const options = {
...withTimeout(30),
...withRetries(3),
...CustomDomainHeader("auth.example.com"),
};- ManagementError - For Management API errors (the only error class in v7)
- Use
.withRawResponse()for accessing raw HTTP response data - Provide clear, actionable error messages
# All tests
yarn test
# Specific test projects
yarn test:unit # Fast unit tests
yarn test:browser # Browser compatibility tests
yarn test:wire # Integration tests with mock server
# With coverage
yarn test:coverage
yarn test:coverage:unit
# Specific test files
yarn test -- src/management/tests/ManagementClient.test.ts
# Pattern matching
yarn test -- --testNamePattern="should authenticate user"- Tests mirror
src/directory structure in correspondingtests/folders - Use
.test.tsextensions - Unit tests use mocks/stubs for external dependencies
- Integration tests use MSW (Mock Service Worker) for HTTP mocking
- Browser tests validate cross-platform compatibility
Pattern for testing Management API wrappers:
import { ManagementClient } from "../wrapper/ManagementClient.js";
describe("ManagementClient", () => {
let client: ManagementClient;
beforeEach(() => {
client = new ManagementClient({
domain: "test.auth0.com",
clientId: "test-client-id",
clientSecret: "test-client-secret",
});
});
it("should handle API calls correctly", async () => {
// Test implementation
});
});Pattern for testing Management API clients with HTTP mocking:
import { ManagementClient } from "../src/index.js";
describe("ManagementClient", () => {
let management: ManagementClient;
beforeEach(() => {
management = new ManagementClient({
domain: "test.auth0.com",
clientId: "test-client-id",
clientSecret: "test-secret",
});
});
it("should call Management API correctly", async () => {
// Test implementation
});
});- Maintain minimum coverage thresholds (see
jest.config.mjs) - Add tests for any new API methods or features
- Test both success and error paths
- Test edge cases and validation logic
- Add method to appropriate class in
src/management/wrapper/ - Follow existing patterns for parameter validation
- Add proper TypeScript types
- Write comprehensive tests
- Update API reference documentation
- Never edit
src/management/Client.tsorsrc/management/api/(Fern-generated) - Extend
src/management/wrapper/ManagementClient.ts - Add custom methods with proper error handling
- Use helper functions from
request-options.ts - Add tests to
src/management/tests/
- Legacy exports in
legacy/exports/maintain v4 API compatibility - Use
import { ... } from 'auth0/legacy'for v4 imports - See
v5_MIGRATION_GUIDE.mdfor breaking changes - Test both new and legacy APIs when making changes
The SDK supports dual module systems:
// CommonJS (default)
const { ManagementClient } = require("auth0");
// ESM
import { ManagementClient } from "auth0";
// Legacy v4 compatibility
import { ManagementClient } from "auth0/legacy";# Always run validation before commit
yarn validateThis runs: lint → format → build → test → package validation
- All tests pass locally (
yarn test) - Code builds successfully (
yarn build) - Linting passes (
yarn lint) - Code is formatted (
yarn format) - New code has corresponding tests
- TypeScript compiles without errors
- Updated API reference if adding public methods
- Added entry to
CHANGELOG.mdif user-facing change - Tested with both CommonJS and ESM if applicable
- Verified backward compatibility
Follow conventional commits style:
feat: add support for new Management API endpointfix: resolve token refresh issue in Authentication clientdocs: update Management API examplestest: add coverage for passwordless authenticationrefactor: simplify error handling in base client
- Never commit Auth0 credentials, client secrets, or tokens
- Use environment variables for sensitive configuration
- Example configs use placeholder values
- Test configurations should use dedicated development tenants
- All inputs validated before API calls
- Proper sanitization of user-provided data
- JWT validation follows security best practices
- Rate limiting and retry logic implemented
- Use dedicated development/testing tenants only
- Never run tests against production tenants
- Store credentials in environment variables
- Clean up test resources after test runs
# Set environment variable for verbose logging
export DEBUG=auth0:*
yarn test- Build errors: Check TypeScript configuration and import paths
- Fern generation conflicts: Never edit auto-generated files
- Module resolution: Ensure
.jsextensions in imports - Test failures: Check mock server setup in wire tests
- Type errors: Verify all imports resolve correctly
# Check compiled output structure
ls -la dist/cjs/ dist/esm/
# Validate package exports
yarn lint:package
# Run specific test suite with verbose output
yarn test:unit --verbose
# Check TypeScript compilation
tsc --noEmit --project ./tsconfig.base.json
# Analyze bundle size
du -sh dist/- SDK Entry (
src/index.ts) → Export all public APIs - Client Initialization → Authentication or Management client
- Method Call → Route to appropriate API handler
- Request Processing → Add authentication, headers, retries
- HTTP Client → Make actual API call to Auth0
- Response Processing → Parse response, handle errors
- Return Result → Typed response to consumer
- Management API uses Fern-generated code for type safety
- Generated files are read-only - never edit directly
- Custom logic goes in wrapper classes
- Fern handles OpenAPI spec changes automatically
auth0 (main export)
├── ManagementClient (tenant administration)
└── Legacy exports (v4 compatibility)
- Migration Guide:
v5_MIGRATION_GUIDE.md - API Reference:
reference.md - Full Documentation: auth0.com/docs
- TypeScript Docs: Generated in
docs/directory - Examples: See README.md for usage examples
// Management Client
const management = new ManagementClient({
domain: "your-tenant.auth0.com",
clientId: "your-client-id",
clientSecret: "your-client-secret",
scope: "read:users create:users", // Optional
});src/index.ts- Main SDK exportssrc/management/wrapper/ManagementClient.ts- Management API wrappersrc/management/request-options.ts- Request configuration helperssrc/lib/models.ts- Shared TypeScript typesjest.config.mjs- Test configuration with multiple projects- Files marked "auto-generated by Fern" - READ-ONLY
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=your-test-client-id
AUTH0_CLIENT_SECRET=your-test-client-secret
AUTH0_M2M_TOKEN=your-machine-to-machine-tokenApplies only when working on the
betabranch.
This SDK ships two tracks from one npm package (auth0):
- Stable (
master): EA/GA endpoints only. Released by a maintainer via arelease/*branch. - Beta (
beta): a superset of stable plus beta-only endpoints. Released automatically when a PR is merged intobeta.
The beta branch is regenerated from the stable spec plus the beta-only spec files; it is never produced by merging master into beta. It receives one combined regeneration PR (stable + beta) as a single squash commit. The beta-only versus stable-mirrored split cannot be detected from code or file paths, so it must be recorded in the squash commit message.
Beta = the next stable minor + -beta.N, derived from git tags. Latest stable v6.3.0 → beta v6.4.0-beta.N; -beta.N auto-increments; once stable v6.4.0 ships, beta rolls to v6.5.0-beta.1. No state file.
Squash and merge with a commit message that marks each group:
Regenerate SDK (stable + beta) (#<pr-number>)
<!-- BETA -->
- feat: add `Management.Sandbox` preview API (Beta)
<!-- /BETA -->
<!-- STABLE -->
- feat: add tenant security headers configuration
<!-- /STABLE -->
- Beta-only changes go inside the
BETAmarkers; stable-mirrored changes go inside theSTABLEmarkers. - The
<!-- ... -->markers are HTML comments and stay invisible in GitHub's rendered view. - Omitting a section renders a "No ... changes in this release." note; omitting both falls back to the raw commit subject. Always prefer the structured form.
- Everything reaches
betathrough a PR. Never push directly tobeta(a direct push will not trigger a release).
The Beta Auto-Release workflow (.github/workflows/npm-release-beta.yml) owns versioning. When a PR is merged into beta it computes the next vX.Y.0-beta.N, aborts if that tag already exists, stamps .version, package.json, src/management/version.ts, and CHANGELOG.md, creates the release commit through the GitHub API (so it is signed/Verified, no GPG key), publishes to npm with --tag beta, tags it, and publishes a GitHub prerelease. Never manually bump these files on beta.
Code outside of the Fern-generated directories is hand-written and is not regenerated on beta. A fix on master does not reach beta automatically, so hand-written changes must be PR'd to both master and beta.
- Never hand-edit
.version,package.json(version field),src/management/version.ts, orCHANGELOG.md; mark beta vs. stable changes in the squash commit message instead (see above). - Do not merge
masterintobeta; the branch is always regenerated from scratch.