From fba879e7398bee5d9a5798b1de9714c32860c109 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 24 Nov 2025 19:10:00 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(backend)=20allow=20prefixing=20resour?= =?UTF-8?q?ce=20server=20scopes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When declaring scopes with our OIDC provider, they require us to prefix each scope with our application name. This is to prevent reserving generic scopes like rooms:list for only our app, as they manage a large federation. I’m proposing a workaround where, if a resource server prefix is detected in the scope, it’s stripped out. This solution is simple and sufficient in my opinion. Since the scopes are defined in the database, I don’t want to update them directly. Additionally, each self-hosted instance may have a different application name, so the prefix should be configurable via a Django setting. --- src/backend/core/external_api/permissions.py | 8 ++++++++ src/backend/core/tests/test_external_api_rooms.py | 6 ++++-- src/backend/meet/settings.py | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/backend/core/external_api/permissions.py b/src/backend/core/external_api/permissions.py index ec3d570a..813d1900 100644 --- a/src/backend/core/external_api/permissions.py +++ b/src/backend/core/external_api/permissions.py @@ -3,6 +3,8 @@ import logging from typing import Dict +from django.conf import settings + from rest_framework import exceptions, permissions from .. import models @@ -55,6 +57,12 @@ class BaseScopePermission(permissions.BasePermission): if isinstance(token_scopes, str): token_scopes = token_scopes.split() + if settings.OIDC_RS_SCOPES_PREFIX: + token_scopes = [ + scope.replace(f"{settings.OIDC_RS_SCOPES_PREFIX}:", "") + for scope in token_scopes + ] + if required_scope not in token_scopes: raise exceptions.PermissionDenied( f"Insufficient permissions. Required scope: {required_scope}" diff --git a/src/backend/core/tests/test_external_api_rooms.py b/src/backend/core/tests/test_external_api_rooms.py index bffc7e9f..5697d6d1 100644 --- a/src/backend/core/tests/test_external_api_rooms.py +++ b/src/backend/core/tests/test_external_api_rooms.py @@ -373,6 +373,7 @@ def test_resource_server_creates_user_on_first_authentication(settings): settings.OIDC_RS_CLIENT_ID = "some_client_id" settings.OIDC_RS_CLIENT_SECRET = "some_client_secret" + settings.OIDC_RS_SCOPES_PREFIX = "lasuite_meet" settings.OIDC_OP_URL = "https://oidc.example.com" settings.OIDC_VERIFY_SSL = False @@ -389,7 +390,7 @@ def test_resource_server_creates_user_on_first_authentication(settings): "aud": "some_client_id", # settings.OIDC_RS_CLIENT_ID "sub": "very-specific-sub", "client_id": "some_service_provider", - "scope": "openid lasuite_meet rooms:list", + "scope": "openid lasuite_meet lasuite_meet:rooms:list", "active": True, }, ) @@ -489,6 +490,7 @@ def test_resource_server_authentication_successful(settings): settings.OIDC_RS_CLIENT_ID = "some_client_id" settings.OIDC_RS_CLIENT_SECRET = "some_client_secret" + settings.OIDC_RS_SCOPES_PREFIX = "lasuite_meet" settings.OIDC_OP_URL = "https://oidc.example.com" settings.OIDC_VERIFY_SSL = False @@ -505,7 +507,7 @@ def test_resource_server_authentication_successful(settings): "aud": "some_client_id", # settings.OIDC_RS_CLIENT_ID "sub": "very-specific-sub", "client_id": "some_service_provider", - "scope": "openid lasuite_meet rooms:list", + "scope": "openid lasuite_meet lasuite_meet:rooms:list", "active": True, }, ) diff --git a/src/backend/meet/settings.py b/src/backend/meet/settings.py index 5d331d13..2a2e7f49 100755 --- a/src/backend/meet/settings.py +++ b/src/backend/meet/settings.py @@ -538,6 +538,9 @@ class Base(Configuration): OIDC_RS_ENCRYPTION_KEY_TYPE = values.Value( default="RSA", environ_name="OIDC_RS_ENCRYPTION_KEY_TYPE", environ_prefix=None ) + OIDC_RS_SCOPES_PREFIX = values.Value( + default=None, environ_name="OIDC_RS_SCOPES_PREFIX", environ_prefix=None + ) # Video conference configuration LIVEKIT_CONFIGURATION = {