Skip to content

Show Diff for Changed Scope #809

@jdevries3133

Description

@jdevries3133

Describe the feature

When scopes change, show the differences between the new and old scopes.

Additional context

I experienced the output of this code path:

# If the issued access token scope is different from the one requested by
# the client, the authorization server MUST include the "scope" response
# parameter to inform the client of the actual scope granted.
# https://tools.ietf.org/html/rfc6749#section-3.3
if params.scope_changed:
message = 'Scope has changed from "{old}" to "{new}".'.format(
old=params.old_scope, new=params.scope,
)
scope_changed.send(message=message, old=params.old_scopes, new=params.scopes)
if not os.environ.get('OAUTHLIB_RELAX_TOKEN_SCOPE', None):
w = Warning(message)
w.token = params
w.old_scope = params.old_scopes
w.new_scope = params.scopes
raise w

I found that the output was hard to read. I was able to better debug what was happening by adding some code to this effect into oauthlib:

diff --git a/oauthlib/oauth2/rfc6749/parameters.py b/oauthlib/oauth2/rfc6749/parameters.py
index 44738bb..32e6bf6 100644
--- a/oauthlib/oauth2/rfc6749/parameters.py
+++ b/oauthlib/oauth2/rfc6749/parameters.py
@@ -6,6 +6,7 @@ This module contains methods related to `Section 4`_ of the OAuth 2 RFC.
 
 .. _`Section 4`: https://tools.ietf.org/html/rfc6749#section-4
 """
+import difflib
 import json
 import os
 import time
@@ -459,8 +460,15 @@ def validate_token_parameters(params):
     # parameter to inform the client of the actual scope granted.
     # https://tools.ietf.org/html/rfc6749#section-3.3
     if params.scope_changed:
-        message = 'Scope has changed from "{old}" to "{new}".'.format(
-            old=params.old_scope, new=params.scope,
+        message = 'Scope has changed from "{old}" to "{new}".\nDifference:\n{diff}'.format(
+            old=params.old_scope,
+            new=params.scope,
+            diff="\n".join(
+                difflib.ndiff(
+                    sorted(params.old_scope.split(' ')),
+                    sorted(params.scope.split(' '))
+                )
+            )
         )
         scope_changed.send(message=message, old=params.old_scopes, new=params.scopes)
         if not os.environ.get('OAUTHLIB_RELAX_TOKEN_SCOPE', None):

Python's difflib makes the addition of this feature trivial. I'm sure that this implementation isn't perfect, but I'm wondering if this looks like a nice feature. I'm interested in hearing what the community thinks, and I'd be happy to write a PR based on feedback.

  • Does the feature apply to OAuth1, OAuth2 and/or OIDC? Oauth2
  • Does the feature apply to client or server side code? Client

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions