# At most one auth library wired up

- **Pattern:** `ab-000218` (`ai-slop-code-drift.data-auth-drift.dual-auth`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-20
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000218
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000218)

## Why it matters

Two active auth libraries means two independent systems of record for who a user is. Password reset may work in NextAuth but silently fail for Clerk-authenticated users. Session revocation on logout may only fire in one library, leaving valid sessions alive in the other. OWASP A07 (Identification & Authentication Failures) and CWE-287 both flag fragmented identity systems as a direct path to authentication bypass — attackers can exploit the gap between which library enforces your authorization checks and which issued the session token they forged. Every route that trusts the wrong library is unprotected.

## Severity rationale

Critical because split auth systems produce routes that enforce access control against a session they didn't issue, creating authentication bypass vulnerabilities exploitable without credentials.

## Remediation

Pick one auth library and route every session lookup through it. Delete the runner-up's session-getting code, consolidate into a single `src/lib/auth.ts` helper, then `npm uninstall` the discarded package.

```ts
// src/lib/auth.ts — single canonical session helper
import { getServerSession } from 'next-auth'
import { authOptions } from './auth-options'

export function getSession() {
  return getServerSession(authOptions)
}
```

Search for any remaining imports of the removed library with `grep -r "@clerk/nextjs\|lucia" src/` and eliminate them before deploying.

## Detection

- **ID:** `dual-auth`
- **Severity:** `critical`
- **What to look for:** Apply the three-condition rule against this exact auth allowlist: `next-auth`, `@auth/core`, `@auth/nextjs`, `@clerk/nextjs`, `@clerk/clerk-react`, `@clerk/clerk-sdk-node`, `lucia`, `@lucia-auth/adapter-prisma`, `@supabase/auth-helpers-nextjs`, `@supabase/ssr`, `firebase` (with auth import), `firebase-admin`, `@auth0/nextjs-auth0`, `auth0`, `better-auth`, `@kinde-oss/kinde-auth-nextjs`, `@workos-inc/authkit-nextjs`, `iron-session`, `cookie-session`, `passport`. Before evaluating, extract and quote the exact package names found in `package.json` `dependencies` matching the allowlist. Count all that meet all three conditions (at least 1 non-escape-hatch importing file). Report the package names and file counts for each library.
- **Detector snippet (shell-capable tools only):** If the tool has shell access, list every source file that imports one of the allowlisted auth libraries. Group by library and count distinct files per library. If `rg` is not installed or exits >=2, fall back to prose reasoning above.

  ```detect-rg
  rg -l -e "from ['\"]next-auth" -e "from ['\"]@auth/" -e "from ['\"]@clerk/" -e "from ['\"]lucia" -e "from ['\"]@supabase/auth" -e "from ['\"]@auth0/" -e "from ['\"]better-auth" -e "from ['\"]passport" src/
  ```

- **Pass criteria:** 0 or 1 auth libraries from the allowlist are actively used. When 1 is found, quote its name and report: "Canonical auth: [name] ([N] importing files)."
- **Fail criteria:** 2 or more auth libraries actively used — sessions split across systems, password reset works for one but not the other, security model fragmented.
- **Do NOT pass when:** A custom JWT helper file exists alongside an auth library AND both have non-trivial import counts — count the custom helper as a second auth approach.
- **Skip (N/A) when:** 0 auth libraries from the allowlist appear in `RUNTIME_DEPS`.
- **Cross-reference:** For deeper authentication flow analysis, the SaaS Authentication audit (`saas-authentication`) covers session management and auth security in depth.
- **Detail on fail:** `"2 active auth libraries detected: 'next-auth' (5 importing files) AND '@clerk/nextjs' (7 importing files). Sessions are split between systems — users may be logged in to one but not the other."`
- **Remediation:** Multiple auth libraries means two systems of record for "who is the user." Pick one and migrate:

  ```ts
  // Bad: src/lib/auth.ts uses NextAuth, src/lib/clerk.ts uses Clerk
  // Pick one approach and consolidate ALL session logic there.

  // Good: a single src/lib/auth.ts that wraps your chosen provider
  import { auth } from '@/lib/auth'  // single import everywhere
  ```

  Pull the loser's session-getting code into a single migration file, route all session lookups through one helper, then `npm uninstall` the loser.

## External references

- cwe CWE-287
- cwe CWE-384
- owasp A07

Taxons: dependency-coherence, access-control

HTML version: https://auditbuffet.com/patterns/ab-000218
