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

Scopes (finer-grained permissions) #29

Closed
florimondmanca opened this issue May 10, 2019 · 1 comment
Closed

Scopes (finer-grained permissions) #29

florimondmanca opened this issue May 10, 2019 · 1 comment
Labels
feedback welcome Give us your thoughts on this!

Comments

@florimondmanca
Copy link
Owner

florimondmanca commented May 10, 2019

Is your feature request related to a problem? Please describe.
API keys are useful to identify a client, but the permission system could be more fine-grained by introducing a notion of "scope", i.e. what is the API key allowed to do?

Describe the solution you'd like

Scopes can be assigned via the admin (using a "Scopes" section in the APIKeyModelAdmin), or programmatically:

read_projects = Scope.objects.get_from_label("myapp.project.read")
api_key.scopes.add(read_projects)

create_projects = Scope.objects.get_from_label("myapp.project.create")
api_key.scopes.remove(create_projects)

Assigning a scope to an API key has the effect of granting it access to the views which require this scope, e.g.

from rest_framework.views import APIView
from rest_framework_api_key.permissions import HasAPIKeyWithScopes

class ProjectListView(APIView):
    permission_classes = [HasAPIKeyWithScopes]
    required_scopes = ["myapp.project.read"]

Like Django's permissions system, the x.y.read, x.y.create, x.y.update and x.y.delete scopes should be created automatically for each model y in each app x.

Custom scopes can be registered via settings:

API_KEY_CUSTOM_SCOPES = {
    "myapp": {
        "project": [
            ("publish", "Can publish a project")
        ]
    }
}

Implementation ideas

Models:

  • Scope: code*, verbose_name, description
  • ScopesMixin: scopes (M2M to Scope) + various helpers (.has_scope(), .has_scopes())
  • APIKey: add ScopesMixin to the class hierarchy.

Permissions:

  • Create APIKeyHasScopes permission class which inspects the required_scopes attribute on the view. Scopes in required_scopes are formatted as code:action.

Describe alternatives you've considered

  • Do not include builtin scopes: it would be cumbersome to have to create them manually, and the cost of creating/storing them is very low.
  • Custom scope discovery via a model's Meta.api_key_scopes: while it possible to allow extra attributes on Meta (by extending models.options.DEFAULT_NAMES), those extra attributes are not available during migrations (as models are faked at that time), which means custom scopes are not detected as they should be. On the other hand, settings are always available.

Additional context
@LeOntalEs implemented a flavor of this in his fork: tarasira#1

Useful inspiration:

@florimondmanca florimondmanca added feedback welcome Give us your thoughts on this! and removed discuss labels Jun 28, 2019
@florimondmanca florimondmanca modified the milestone: 1.4 Jun 30, 2019
This was referenced Jun 30, 2019
@florimondmanca florimondmanca changed the title Scopes Scopes (finer-grained permissions) Jul 20, 2019
@florimondmanca
Copy link
Owner Author

Closing to reduce project scope for now, happy to reconsider in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feedback welcome Give us your thoughts on this!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant