Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lack of dynamic scope handling in TokenHasScope #1535

Open
birddevelper opened this issue Dec 18, 2024 · 0 comments
Open

Lack of dynamic scope handling in TokenHasScope #1535

birddevelper opened this issue Dec 18, 2024 · 0 comments

Comments

@birddevelper
Copy link

birddevelper commented Dec 18, 2024

The Current Limitation

In the current implementation of TokenHasScope, the get_scopes method retrieves the required scopes using this method:

def get_scopes(self, request, view):
    try:
        return getattr(view, "required_scopes")
    except AttributeError:
        raise ImproperlyConfigured(
            "TokenHasScope requires the view to define the required_scopes attribute"
        )

This approach assumes a static required_scopes attribute on the view. However, this design doesn't support cases where the required scope changes dynamically such as different scopes for GET, PUT, PATCH, or DELETE methods in RetrieveUpdateDestroyAPIView like following example:

class StudentRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [TokenHasScope]

    def get_required_scopes(self):
        if self.request.method in ["PUT", "PATCH"]:
            return ["student_data_update"]
        elif self.request.method == "GET":
            return ["student_data_read"]
        elif self.request.method == "DELETE":
            return ["student_data_delete"]

Solutions

  1. Modifying TokenHasScope to support a get_required_scopes method in addition to the existing required_scopes attribute. The new behavior could be:

    1. Check if the view has a get_required_scopes method.
    2. If the method exists, call it and use its return value as the required scopes.
    3. If the method does not exist, fall back to the static required_scopes attribute.

Here’s how the updated get_scopes implementation might look:

def get_scopes(self, request, view):
    if hasattr(view, "get_required_scopes"):
        return view.get_required_scopes()
    try:
        return getattr(view, "required_scopes")
    except AttributeError:
        raise ImproperlyConfigured(
            "TokenHasScope requires the view to define either the required_scopes attribute or the get_required_scopes method"
        )
  1. Another solution is to adjust TokenHasScope to check for get_scopes() in the view, if the view uses ScopedResourceMixin, Instead of directly checking for the required_scopes attribute
@birddevelper birddevelper changed the title lack of get_required_scopes in TokenHasScope for Dynamic Scope Handling in Views lack of dynamic scope handling in views in TokenHasScope Dec 18, 2024
@birddevelper birddevelper changed the title lack of dynamic scope handling in views in TokenHasScope Lack of dynamic scope handling in TokenHasScope Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant