diff --git a/oauth2_provider/forms.py b/oauth2_provider/forms.py index a8b398554..8fe85aefa 100644 --- a/oauth2_provider/forms.py +++ b/oauth2_provider/forms.py @@ -25,4 +25,4 @@ class RegistrationForm(forms.ModelForm): """ class Meta: model = Application - fields = ('name', 'client_id', 'client_secret', 'client_type', 'authorization_grant_type', 'redirect_uris') + fields = ('name', 'client_id', 'client_secret', 'client_type', 'authorization_grant_type', 'redirect_uris') \ No newline at end of file diff --git a/oauth2_provider/models.py b/oauth2_provider/models.py index d3091fd2a..e8315eace 100644 --- a/oauth2_provider/models.py +++ b/oauth2_provider/models.py @@ -66,6 +66,8 @@ class AbstractApplication(models.Model): default=generate_client_secret, db_index=True) name = models.CharField(max_length=255, blank=True) skip_authorization = models.BooleanField(default=False) + # only used if oauth2_settings.APP_SPECIFIC_SCOPES is True + allowed_scopes = models.TextField(help_text="List of allowed scopes for this application, space separated", blank=True) class Meta: abstract = True diff --git a/oauth2_provider/oauth2_validators.py b/oauth2_provider/oauth2_validators.py index d40dbdfdf..4ab5ffe62 100644 --- a/oauth2_provider/oauth2_validators.py +++ b/oauth2_provider/oauth2_validators.py @@ -265,7 +265,10 @@ def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs): return set(scopes).issubset(set(oauth2_settings._SCOPES)) def get_default_scopes(self, client_id, request, *args, **kwargs): - return oauth2_settings._SCOPES + if oauth2_settings.APP_SPECIFIC_SCOPES: + return request.client.allowed_scopes + else: + return oauth2_settings._SCOPES def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs): return request.client.redirect_uri_allowed(redirect_uri) diff --git a/oauth2_provider/settings.py b/oauth2_provider/settings.py index db5768686..420dcdd36 100644 --- a/oauth2_provider/settings.py +++ b/oauth2_provider/settings.py @@ -43,6 +43,7 @@ 'APPLICATION_MODEL': getattr(settings, 'OAUTH2_PROVIDER_APPLICATION_MODEL', 'oauth2_provider.Application'), 'REQUEST_APPROVAL_PROMPT': 'force', 'ALLOWED_REDIRECT_URI_SCHEMES': ['http', 'https'], + 'APP_SPECIFIC_SCOPES': False, # Special settings that will be evaluated at runtime '_SCOPES': [], diff --git a/oauth2_provider/views/base.py b/oauth2_provider/views/base.py index 5d80f1d9a..3ebb53da4 100644 --- a/oauth2_provider/views/base.py +++ b/oauth2_provider/views/base.py @@ -78,8 +78,16 @@ class AuthorizationView(BaseAuthorizationView, FormView): skip_authorization_completely = False def get_initial(self): - # TODO: move this scopes conversion from and to string into a utils function - scopes = self.oauth2_data.get('scope', self.oauth2_data.get('scopes', [])) + if oauth2_settings.APP_SPECIFIC_SCOPES: + ApplicationModel = get_application_model() + application = ApplicationModel.objects.get(client_id=self.request.GET['client_id']) + allowed_scopes = application.allowed_scopes.split(' ') + requested_scopes = self.oauth2_data.get('scope', self.oauth2_data.get('scopes', [])) + # now reduce down to allowed scopes + scopes = list(set(allowed_scopes) & set(requested_scopes)) + else: + # TODO: move this scopes conversion from and to string into a utils function + scopes = self.oauth2_data.get('scope', self.oauth2_data.get('scopes', [])) initial_data = { 'redirect_uri': self.oauth2_data.get('redirect_uri', None), 'scope': ' '.join(scopes), diff --git a/oauth2_provider/views/mixins.py b/oauth2_provider/views/mixins.py index 168d5f42d..919878a9f 100644 --- a/oauth2_provider/views/mixins.py +++ b/oauth2_provider/views/mixins.py @@ -155,9 +155,17 @@ def error_response(self, error, **kwargs): :param error: :attr:`OAuthToolkitError` """ oauthlib_error = error.oauthlib_error + + separator = '?' + try: + if '?' in oauthlib_error.redirect_uri: + separator = '&' + except: + pass + error_response = { 'error': oauthlib_error, - 'url': "{0}?{1}".format(oauthlib_error.redirect_uri, oauthlib_error.urlencoded) + 'url': "{0}{1}{2}".format(oauthlib_error.redirect_uri, separator, oauthlib_error.urlencoded) } error_response.update(kwargs)