diff --git a/apps/permission/scopes.py b/apps/permission/scopes.py
new file mode 100644
index 0000000000000000000000000000000000000000..4abca5a11eab57a5ca2f21982294833e82e64afe
--- /dev/null
+++ b/apps/permission/scopes.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from oauth2_provider.scopes import BaseScopes
+
+from member.models import Club
+
+from .backends import PermissionBackend
+from .models import Permission
+
+
+class PermissionScopes(BaseScopes):
+    """
+    An OAuth2 scope is defined by a permission object and a club.
+    A token will have a subset of permissions from the owner of the application,
+    and can be useful to make queries through the API with limited privileges.
+    """
+
+    def get_all_scopes(self):
+        return {f"{p.id}_{club.id}": f"{p.description} (club {club.name})"
+                for p in Permission.objects.all() for club in Club.objects.all()}
+
+    def get_available_scopes(self, application=None, request=None, *args, **kwargs):
+        if not application:
+            return []
+        user = application.user
+        return [f"{p.id}_{p.membership.club.id}"
+                for t in Permission.PERMISSION_TYPES
+                for p in PermissionBackend.get_raw_permissions(user, t[0])]
+
+    def get_default_scopes(self, application=None, request=None, *args, **kwargs):
+        if not application:
+            return []
+        user = application.user
+        return [f"{p.id}_{p.membership.club.id}"
+                for p in PermissionBackend.get_raw_permissions(user, 'view')]
diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py
index 6cb068a5c8398fdf94e997cba1b5ff0b94e6e74f..a0ece71504efe9f8dea0f2f0c0e421c15301d2a0 100644
--- a/note_kfet/settings/base.py
+++ b/note_kfet/settings/base.py
@@ -245,6 +245,11 @@ REST_FRAMEWORK = {
     'PAGE_SIZE': 20,
 }
 
+# OAuth2 Provider
+OAUTH2_PROVIDER = {
+    'SCOPES_BACKEND_CLASS': 'permission.scopes.PermissionScopes',
+}
+
 # Take control on how widget templates are sourced
 # See https://docs.djangoproject.com/en/2.2/ref/forms/renderers/#templatessetting
 FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'