# How Plane Handles Authentication and Authorization: Django Sessions, CSRF Protection, and RBAC

> Discover how Plane handles authentication and authorization with Django sessions, CSRF protection, and RBAC for secure access. Learn about its robust security features.

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

---

**Plane implements a session-based authentication system using Django's cookie-based sessions and CSRF tokens, paired with centralized service classes in the frontend, while enforcing fine-grained role-based access control through workspace membership validation.**

Plane's open-source project management platform employs a **dual-layer security architecture** that combines Django's proven backend session management with a TypeScript-based service layer in React. This article analyzes the makeplane/plane repository to explain how the system authenticates users via cookies and magic links, integrates OAuth providers, and authorizes actions through workspace-specific permission checks.

## Backend Authentication: Django Sessions and CSRF Protection

The backend authentication layer relies on Django's native session framework supplemented with custom middleware for API-specific handling.

### API Authentication Middleware

At the core of Plane's request authentication is the `APIAuthenticationMiddleware` 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 extracts the Django session from incoming requests and validates CSRF tokens when required, populating `request.user` for downstream consumers. The middleware ensures that every protected API endpoint receives an authenticated user object or rejects the request with appropriate error handling.

```python

# apps/api/plane/app/middleware/api_authentication.py

class APIAuthenticationMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Django session is automatically attached to request.user

        # CSRF validation happens in the view when needed

        response = self.get_response(request)
        return response

```

### CSRF Token Handling

Plane requires CSRF tokens for state-changing operations (POST, PUT, DELETE). The frontend retrieves these tokens via a dedicated endpoint, and subsequent requests include the token in the `X-CSRFTOKEN` header. The middleware validates these tokens against the user's session to prevent cross-site request forgery attacks.

## Frontend Authentication Service

The frontend abstracts all authentication operations into a centralized service class, promoting consistency across the React application.

### The AuthService Class

Located in [`packages/services/src/auth/auth.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/auth/auth.service.ts), the **AuthService** class encapsulates HTTP interactions with the backend. Key methods include:

- **`requestCSRFToken()`** – Retrieves a fresh CSRF token from `/auth/get-csrf-token/`
- **`generateUniqueCode()`** – Initiates magic-link authentication via `/auth/magic-generate/`
- **`signOut(baseUrl)`** – Submits a hidden form containing the CSRF token to `/auth/sign-out/`

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

const auth = new AuthService();

// Retrieve CSRF token (required for POST/PUT/DELETE)
async function getCsrf() {
  const { csrf_token } = await auth.requestCSRFToken();
  return csrf_token;
}

// Sign-out creates a hidden form with the token and submits it
async function signOut() {
  const baseUrl = window.location.origin;
  await auth.signOut(baseUrl);
}

```

### Magic-Link Authentication Flow

For passwordless login, Plane generates short-lived unique codes through the `generateUniqueCode` method. The backend sends an email containing a link (e.g., `https://app.plane.so/auth/magic-login/?code=XYZ123`), which establishes the session when clicked.

```typescript
// Request a magic link for a user's email
await auth.generateUniqueCode({ email: "user@example.com" });

```

## OAuth and Single Sign-On (SSO) Integration

Plane supports third-party authentication providers through a modular adapter pattern.

### OAuth Adapter Implementation

The [`apps/api/plane/authentication/adapter/oauth.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/adapter/oauth.py) file contains the **OAuth adapter** that exchanges authorization codes from providers (Google, GitHub, etc.) for Plane session tokens. This adapter normalizes provider-specific responses into Plane's user model, creating or updating user records while maintaining the same session-based authentication flow as native logins.

## Authorization and Role-Based Access Control (RBAC)

After authentication, Plane enforces **fine-grained permissions** through workspace and project membership validation.

### Workspace Membership Validation

The [`apps/api/plane/authentication/utils/user_auth_workflow.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/utils/user_auth_workflow.py) module contains utility functions like `require_active_member` that validate a user's role within specific workspaces. These functions query the `WorkspaceMember` model and raise `PermissionDenied` exceptions if the user lacks the required membership status or role level.

```python

# apps/api/plane/authentication/utils/user_auth_workflow.py

def require_active_member(user, workspace_id):
    membership = WorkspaceMember.objects.filter(user=user, workspace_id=workspace_id).first()
    if not membership or not membership.is_active:
        raise PermissionDenied("User is not an active workspace member")

```

### Permission Classes and View Protection

Django REST Framework viewsets utilize custom permission classes that invoke the workflow utilities. These classes verify whether the authenticated user possesses the necessary permissions (admin, member, or viewer) before allowing resource creation, modification, or deletion operations.

### Enterprise Edition Enhancements

The [`packages/types/src/instance/auth-ee.ts`](https://github.com/makeplane/plane/blob/main/packages/types/src/instance/auth-ee.ts) file defines extended authentication types for the **Enterprise Edition**, including fields like `is_email_verified` and `is_super_admin`. These additional attributes enable premium features such as mandatory email verification and instance-wide administrative privileges.

## End-to-End Authentication Flow

The complete authentication lifecycle involves coordination between the frontend service layer and backend middleware:

1. **Initial Request** – The user initiates login via magic link (`generateUniqueCode`) or OAuth callback
2. **Session Establishment** – The backend creates a Django session, sets the session cookie, and returns a CSRF token
3. **Authenticated Requests** – The frontend includes the CSRF token in the `X-CSRFTOKEN` header for state-changing operations, while the browser automatically sends the session cookie
4. **Authorization Check** – Protected views invoke `user_auth_workflow` utilities to validate workspace membership before processing requests

## Summary

- Plane utilizes **Django session cookies** with **CSRF token validation** to maintain secure, stateful authentication connections between clients and the API
- The **AuthService** class in [`packages/services/src/auth/auth.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/auth/auth.service.ts) centralizes all frontend authentication logic, including token retrieval and magic-link generation
- **OAuth integration** adapts third-party identity providers to Plane's native session system through the adapter pattern in [`apps/api/plane/authentication/adapter/oauth.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/adapter/oauth.py)
- **Role-based access control** is enforced through workspace membership checks in [`apps/api/plane/authentication/utils/user_auth_workflow.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/utils/user_auth_workflow.py), which validates user roles before resource access
- **Enterprise Edition** extends the authentication model with additional verification fields and administrative capabilities via [`packages/types/src/instance/auth-ee.ts`](https://github.com/makeplane/plane/blob/main/packages/types/src/instance/auth-ee.ts)

## Frequently Asked Questions

### What authentication methods does Plane support?

Plane supports **email-based magic links**, traditional email/password combinations, and **OAuth 2.0 providers** including Google and GitHub. The OAuth implementation adapts external provider responses to Plane's internal session system, ensuring consistent authentication semantics regardless of the login method used.

### How does Plane protect against CSRF attacks?

Plane implements **double-submit cookie pattern** validation through the `APIAuthenticationMiddleware`. The frontend retrieves a CSRF token via `AuthService.requestCSRFToken()` and submits it in the `X-CSRFTOKEN` header for all state-changing requests. The backend validates this token against the user's session before processing the request, preventing unauthorized cross-site commands.

### How is workspace access authorization enforced?

Authorization relies on the **user_auth_workflow.py** utilities, which query the `WorkspaceMember` model to verify active membership and role levels (admin, member, viewer). Django REST Framework permission classes invoke these utilities, returning **403 Forbidden** responses when users attempt actions outside their permission scope within specific workspaces or projects.

### Can Plane integrate with corporate identity providers?

Yes, through the **OAuth adapter** ([`apps/api/plane/authentication/adapter/oauth.py`](https://github.com/makeplane/plane/blob/main/apps/api/plane/authentication/adapter/oauth.py)), Plane can integrate with any OAuth 2.0-compliant identity provider. The adapter exchanges the provider's authorization code for a Plane session, creating or updating user records while maintaining the same workspace-based authorization checks used for native authentication.