# Understanding the Authentication Mechanism in Karakeep: NextAuth v4 and API Key Security

> Explore Karakeep's authentication mechanism with NextAuth v4 for users and API keys for programmatic access. Learn about secure password hashing and scope-based authorization.

- Repository: [Karakeep App/karakeep](https://github.com/karakeep-app/karakeep)
- Tags: deep-dive
- Published: 2026-07-07

---

**Karakeep implements a dual-layer authentication system using NextAuth v4 with JWT-based sessions for web users and Bearer token API keys for programmatic access, featuring bcrypt password hashing, SHA-256 key storage, and scope-based authorization.**

Karakeep (formerly Hoarder), an open-source bookmarking application, employs a robust authentication mechanism designed to secure both interactive web sessions and automated API interactions. The `karakeep-app/karakeep` repository implements a layered strategy that combines modern web authentication standards with flexible API key management. This architecture ensures secure credential storage, rate-limited login attempts, and granular access control for third-party integrations.

## Web Authentication Architecture

The web interface relies on NextAuth v4 configured with a custom Drizzle adapter, as implemented in [`apps/web/server/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/server/auth.ts). This configuration supports multiple authentication strategies while maintaining stateless session management through JSON Web Tokens.

### Credentials and OAuth Providers

The authentication system supports **email and password authentication** through a custom `CredentialsProvider`, alongside optional OAuth providers configured via `serverConfig.auth.oauth`. When a user successfully authenticates, the system creates a user record through the `User.createRaw` model, which guarantees a safe display name before persisting to the database.

### JWT Session Management

Sessions utilize the JWT strategy (`strategy: "jwt"`) rather than database sessions. The `jwt` callback in [`apps/web/server/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/server/auth.ts) populates the token with essential user claims including user ID, name, email, role, and profile image. The `getServerAuthSession` function exposes these claims to server components, enabling role-based UI rendering without repeated database queries.

### Rate Limiting and Audit Logging

Security hardening includes aggressive rate limiting on authentication endpoints. The system restricts login attempts to **10 requests per 15 minutes per IP address** using the shared rate-limiting client. Additionally, all authentication events are logged via `logEvent`, creating an audit trail for security monitoring and compliance.

## API Key Authentication

For programmatic access to the Karakeep API, the system implements Bearer token authentication using API keys. The implementation in [`packages/trpc/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/trpc/auth.ts) provides a complete lifecycle for key generation, validation, and revocation.

### Key Generation and Storage

API keys follow a two-version format (`ak1` and `ak2`) and consist of a random `keyId` and secret. When generating keys via `generateApiKey`, the system stores only a **SHA-256 hash** (`keyHash`) of the secret in the database, while returning the full plaintext key to the user once. This pattern ensures that compromised database dumps do not expose usable API credentials.

### Validation Mechanisms

The `authenticateApiKey` function handles validation differently depending on the key version. Version 1 (ak1) keys use **bcrypt** for validation, while version 2 (ak2) employ direct SHA-256 hash comparison. After successful validation, the middleware attaches the user object and authorized scopes to the request context, making them available to downstream tRPC procedures.

### Scope-Based Access Control

API keys implement granular permissions through scopes. Keys default to `API_KEY_FULL_ACCESS_SCOPE` when created without specific restrictions. Router procedures access this authorization information through the `Context["auth"]` interface, allowing fine-grained control over which endpoints a specific key can access. The public router in [`packages/trpc/routers/apiKeys.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/trpc/routers/apiKeys.ts) exposes methods for creating, revoking, and inspecting these scoped keys.

## Password Hashing and Security

The credential provider employs **bcrypt** with per-user salts for password storage. The `generatePasswordSalt` function creates unique salts, while `validatePassword` performs hash comparisons that respect the global `disablePasswordAuth` configuration flag. This validation routine includes timing attack protection by ensuring constant-time comparison operations.

## Implementation Examples

### Authenticating with Email and Password

```typescript
import { signIn } from "@karakeep/web/lib/auth/client";

async function login(email: string, password: string) {
  const result = await signIn("credentials", {
    email,
    password,
    redirect: false,
  });
  if (result?.error) throw new Error(result.error);
  // Session is now stored in the JWT cookie
}

```

### Calling Protected API Endpoints

```typescript
import { createTRPCClient } from "@karakeep/trpc/client";

const client = createTRPCClient({
  url: "https://api.karakeep.com/trpc",
  // Inject the generated API key as a Bearer token
  async fetch({ input, type, path }) {
    const response = await fetch(`${this.url}/${path}`, {
      method: type,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${MY_API_KEY}`,
      },
      body: JSON.stringify(input),
    });
    return response.json();
  },
});

await client.bookmarks.list.query(); // succeeds only if the key is valid

```

### Generating API Keys Server-Side

```typescript
import { generateApiKey } from "@karakeep/trpc/auth";
import { db } from "@karakeep/db";

const { key } = await generateApiKey(
  "My script key",
  userId,
  db,
  ["bookmarks.read", "bookmarks.write"]
);
console.log("Store this secret safely:", key);

```

## Summary

- **Karakeep uses NextAuth v4** with JWT sessions for web authentication, supporting both credentials and OAuth providers through the custom Drizzle adapter in [`apps/web/server/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/server/auth.ts).
- **API keys implement Bearer token authentication** with SHA-256 hashed secrets and versioned validation logic (ak1/ak2) found in [`packages/trpc/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/trpc/auth.ts).
- **Rate limiting protects login endpoints** at 10 requests per 15 minutes per IP, while bcrypt with per-user salts secures password storage against brute-force attacks.
- **Scope-based authorization** allows granular API access control, defaulting to `API_KEY_FULL_ACCESS_SCOPE` for new keys unless explicitly restricted.

## Frequently Asked Questions

### What authentication methods does Karakeep support for web users?

Karakeep supports email and password authentication through a custom CredentialsProvider, alongside configurable OAuth providers. The implementation in [`apps/web/server/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/server/auth.ts) uses NextAuth v4 with a custom Drizzle adapter, storing session data in JWT cookies rather than database sessions.

### How are API keys validated in Karakeep?

API keys use Bearer token authentication with two validation methods depending on version. Version 1 (ak1) keys utilize bcrypt comparison, while version 2 (ak2) use direct SHA-256 hash comparison against the stored `keyHash`. The `authenticateApiKey` function in [`packages/trpc/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/packages/trpc/auth.ts) handles this validation and attaches user context to requests.

### Does Karakeep implement rate limiting on authentication?

Yes, login attempts are rate-limited to 10 requests per 15 minutes per IP address using the shared rate-limiting client. This protection applies to the NextAuth endpoints configured in [`apps/web/server/auth.ts`](https://github.com/karakeep-app/karakeep/blob/main/apps/web/server/auth.ts), preventing brute-force attacks against user credentials while maintaining usability for legitimate users.

### How does Karakeep store API key secrets securely?

API keys are stored as SHA-256 hashes (`keyHash`) rather than plaintext. When generating a key via `generateApiKey`, the system creates a random `keyId` and secret, stores only the hash, and returns the full key once to the user. This ensures that database compromises do not expose usable API credentials, as the original secret cannot be derived from the hash.