# Security Configurations and Authentication Mechanisms in Plane: A Complete Technical Guide

> Explore Plane's robust security: API keys, Django sessions, CSRF tokens, secret keys, and JWT invitations. Secure your project management resources with our technical guide.

- Repository: [Plane/plane](https://github.com/makeplane/plane)
- Tags: deep-dive
- Published: 2026-06-18

---

**Plane employs a multi-layered security architecture combining API key authentication, Django session management with CSRF tokens, secret-key middleware for internal services, and JWT-signed invitations to protect project management resources.**

Plane is an open-source project management platform that implements defense-in-depth through distinct authentication layers for different access patterns. Understanding these security configurations and authentication mechanisms is essential for developers integrating with the REST API, securing self-hosted deployments, or extending the frontend. The codebase separates concerns between programmatic API access, browser-based user sessions, and inter-service communication.

## API Key Authentication

For programmatic access to the REST API, Plane uses a custom `APIKeyAuthentication` class located in [`apps/api/plane/app/middleware/api_authentication.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/app/middleware/api_authentication.py). This middleware reads the `X-Api-Key` header and verifies the token against the `APIToken` model in the database.

Upon successful validation, the system updates the token's `last_used` timestamp to track activity. The authentication scheme is automatically documented in the OpenAPI specification through `APIKeyAuthenticationExtension` in [`apps/api/plane/utils/openapi/auth.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/utils/openapi/auth.py).

```typescript
import { APIService } from "@plane/services/api.service";

const api = new APIService(); // base URL is API_BASE_URL
await api.get("/issues/", {
  headers: { "X-Api-Key": "YOUR_API_KEY_HERE" },
});

```

## Session Authentication and CSRF Protection

The web UI relies on Django's session-based authentication extended through `BaseSessionAuthentication` in [`apps/api/plane/authentication/session.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/session.py). This class extends DRF's standard `SessionAuthentication` but **disables CSRF enforcement for API calls**, as the frontend handles CSRF protection separately.

For state-changing operations like password resets or sign-outs, the frontend obtains a fresh CSRF token from the `/auth/get-csrf-token/` endpoint through `AuthService.requestCSRFToken()` in [`packages/services/src/auth/auth.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/auth/auth.service.ts). Subsequent POST requests include this token in the `X-CSRFTOKEN` header to prevent cross-site request forgery.

```typescript
import { AuthService } from "@plane/services/auth.service";

const auth = new AuthService();
const { csrf_token } = await auth.requestCSRFToken();

await auth.post("/auth/set-password/", { password: "newPass" }, {
  headers: { "X-CSRFTOKEN": csrf_token },
});

```

## Live Server Secret Key Middleware

Internal "live-server" endpoints—such as webhook receivers—utilize shared secret authentication implemented in [`apps/live/src/lib/auth-middleware.ts`](https://github.com/makeplane/plane/blob/main/apps/live/src/lib/auth-middleware.ts). The `requireSecretKey` Express middleware validates the `live-server-secret-key` header against the `env.LIVE_SERVER_SECRET_KEY` environment variable, returning a 401 response on mismatch.

```typescript
import express from "express";
import { requireSecretKey } from "@/lib/auth-middleware";

const router = express.Router();

router.post("/admin/trigger", requireSecretKey, (req, res) => {
  // secret key validated – proceed safely
  res.json({ status: "ok" });
});

```

## JWT-Based Invitation Tokens

Project and workspace invitations use cryptographically signed JWT tokens to verify email-based invites. When creating an invitation in [`apps/api/plane/app/views/project/invite.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/app/views/project/invite.py), Plane encodes a payload containing the invitee's email and timestamp using `jwt.encode()` with the Django `SECRET_KEY` and HS256 algorithm.

The resulting token is stored on the `ProjectMemberInvite` model and validated when the invitee accepts, ensuring only intended recipients can join workspaces.

```python
token = jwt.encode(
    {"email": email, "timestamp": datetime.now().timestamp()},
    settings.SECRET_KEY,
    algorithm="HS256",
)

invite = ProjectMemberInvite.objects.create(
    email=email,
    workspace_id=workspace.id,
    token=token,
    # …

)

```

## Frontend Authentication Layer

The React frontend centralizes routing logic through `AuthenticationWrapper` in [`apps/web/core/lib/wrappers/authentication-wrapper.tsx`](https://github.com/makeplane/plane/blob/main/apps/web/core/lib/wrappers/authentication-wrapper.tsx). This component checks the user store, profile data, and workspace selection status, then redirects to onboarding, workspace selection, or login pages based on authentication state.

For third-party OAuth providers like Google and GitHub, the `OAuthOptions` component in [`packages/ui/src/oauth/oauth-options.tsx`](https://github.com/makeplane/plane/blob/main/packages/ui/src/oauth/oauth-options.tsx) renders available authentication buttons and forwards click events to backend handlers that manage the actual token exchange.

```tsx
import { AuthenticationWrapper, EPageTypes } from "@/helpers/authentication.helper";

export default function Dashboard() {
  return (
    <AuthenticationWrapper pageType={EPageTypes.AUTHENTICATED}>
      {/* Dashboard UI – only rendered for logged‑in users */}
      <h1>Welcome to Plane</h1>
    </AuthenticationWrapper>
  );
}

```

## Summary

Plane's security model implements distinct authentication strategies tailored to different interaction patterns:

- **API Key Authentication**: Custom middleware validates `X-Api-Key` headers against database tokens with automatic OpenAPI documentation in [`apps/api/plane/utils/openapi/auth.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/utils/openapi/auth.py)
- **Session Management**: Extended Django sessions disable CSRF for APIs while the frontend manages CSRF tokens separately via `AuthService`
- **Internal Service Protection**: Express middleware enforces shared secret validation for live-server endpoints using `requireSecretKey`
- **Invitation Security**: JWT tokens signed with Django's `SECRET_KEY` prevent unauthorized workspace access through the `ProjectMemberInvite` model
- **Frontend Routing**: React wrappers enforce authentication state at the UI layer before rendering protected components

## Frequently Asked Questions

### How does Plane authenticate API requests?

Plane authenticates API requests through the `APIKeyAuthentication` class in [`apps/api/plane/app/middleware/api_authentication.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/app/middleware/api_authentication.py). This middleware extracts the `X-Api-Key` header, validates it against the `APIToken` model, and updates the `last_used` timestamp. For browser-based access, it falls back to Django session authentication via `BaseSessionAuthentication` in [`apps/api/plane/authentication/session.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/session.py).

### What CSRF protection does Plane use for web forms?

Plane implements CSRF protection through a token service defined in [`packages/services/src/auth/auth.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/auth/auth.service.ts). The frontend requests a fresh token from `/auth/get-csrf-token/` and attaches it to POST requests via the `X-CSRFTOKEN` header. The API layer disables CSRF enforcement for direct API calls while maintaining protection for browser-based form submissions.

### How are project invitations secured in Plane?

Project invitations use JWT tokens generated in [`apps/api/plane/app/views/project/invite.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/app/views/project/invite.py). These tokens encode the invitee's email and a timestamp, signed with Django's `SECRET_KEY` using the HS256 algorithm. The token is stored on the `ProjectMemberInvite` model and validated upon acceptance to ensure only the intended recipient can join the workspace.

### What authentication methods are available for self-hosted Plane instances?

Self-hosted instances support API key authentication for programmatic access, Django session authentication for web users, and optional OAuth providers (Google, GitHub) through the `OAuthOptions` component. Internal services require the `live-server-secret-key` header configured via the `LIVE_SERVER_SECRET_KEY` environment variable.