Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions apps/api/plane/authentication/middleware/proxy_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

from uuid import uuid4

import jwt
from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.hashers import make_password
from django.db import IntegrityError
from django.http import JsonResponse

from plane.authentication.middleware.proxy_auth_utils import (
_coerce_bypass_paths,
Expand Down Expand Up @@ -36,6 +38,29 @@
}


def _check_corporate_id(request) -> bool:
"""Verify the caller's access token contains a corporate_id matching this deployment.

When SMB_CORPORATE_ID is configured, only corporate mPass tokens whose
``custom:corporate_id`` claim matches are allowed through. Individual
(non-corporate) tokens are rejected. When SMB_CORPORATE_ID is not set,
the check is skipped entirely for backward compatibility.
"""
expected = getattr(settings, "SMB_CORPORATE_ID", None)
if not expected:
return True
access_token = request.META.get("HTTP_X_AUTH_REQUEST_ACCESS_TOKEN")
if not access_token:
return False
try:
claims = jwt.decode(access_token, options={"verify_signature": False})
except Exception:
return False
if claims.get("custom:is_corporate") != "true":
return False
return claims.get("custom:corporate_id") == expected


class ProxyAuthMiddleware:
"""
Django middleware for mPass proxy authentication.
Expand Down Expand Up @@ -82,6 +107,9 @@ def __call__(self, request):
if not email:
return self.get_response(request)

if not _check_corporate_id(request):
return JsonResponse({"error": "access_denied"}, status=403)

user = self._resolve_user(email)

# Respect deactivated accounts — mPass authentication does not
Expand Down
1 change: 1 addition & 0 deletions apps/api/plane/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
# SMB portal hostname segment (landing / logout redirects) vs default Plane workspace slug
SMB_NAME = os.environ.get("SMB_NAME")
SMB_DEFAULT_WORKSPACE_NAME = os.environ.get("SMB_DEFAULT_WORKSPACE_NAME") or SMB_NAME
SMB_CORPORATE_ID = os.environ.get("SMB_CORPORATE_ID")

# Middlewares
MIDDLEWARE = [
Expand Down