From 6911c81af3de15e4175a033e0dd17df6295fee1d Mon Sep 17 00:00:00 2001 From: Andrew Chen Wang <60190294+Andrew-Chen-Wang@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:24:12 -0500 Subject: [PATCH 1/6] Add migration due to noop FK from Django 4.0 (#1056) * Add migration due to noop --- CHANGELOG.md | 6 +++ .../migrations/0005_auto_20211222_2352.py | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 oauth2_provider/migrations/0005_auto_20211222_2352.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f10cdf145..2e650e052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.2] unrelease + +### Fixed + +* #1056 Add missing migration triggered by [Django 4.0 changes to the migrations autodetector](https://docs.djangoproject.com/en/4.0/releases/4.0/#migrations-autodetector-changes). + ## [1.6.1] 2021-12-23 ### Changed diff --git a/oauth2_provider/migrations/0005_auto_20211222_2352.py b/oauth2_provider/migrations/0005_auto_20211222_2352.py new file mode 100644 index 000000000..ebff59f80 --- /dev/null +++ b/oauth2_provider/migrations/0005_auto_20211222_2352.py @@ -0,0 +1,39 @@ +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('oauth2_provider', '0004_auto_20200902_2022'), + ] + + operations = [ + migrations.AlterField( + model_name='accesstoken', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='application', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='grant', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='idtoken', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='refreshtoken', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s', to=settings.AUTH_USER_MODEL), + ), + ] From 36dc8b27005249f0d74deeb26e5af42cae42602e Mon Sep 17 00:00:00 2001 From: Alan Crosswell Date: Tue, 4 Jan 2022 15:36:27 -0500 Subject: [PATCH 2/6] * #1066: Revert #967 which incorrectly breaks API. --- AUTHORS | 1 + CHANGELOG.md | 1 + docs/oidc.rst | 19 +++++++++---------- oauth2_provider/oauth2_validators.py | 25 ++++++++----------------- oauth2_provider/views/oidc.py | 8 -------- tests/test_oidc_views.py | 24 ++++-------------------- 6 files changed, 23 insertions(+), 55 deletions(-) diff --git a/AUTHORS b/AUTHORS index deb0c7ce4..b741b49a4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -63,5 +63,6 @@ pySilver Łukasz Skarżyński Shaheed Haque Andrea Greco +Peter Karman Vinay Karanam diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e650e052..5c5b2f5c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * #1056 Add missing migration triggered by [Django 4.0 changes to the migrations autodetector](https://docs.djangoproject.com/en/4.0/releases/4.0/#migrations-autodetector-changes). +* #1068 Revert #967 which incorrectly changed an API. See #1066. ## [1.6.1] 2021-12-23 diff --git a/docs/oidc.rst b/docs/oidc.rst index eae9a67d4..ba69e984f 100644 --- a/docs/oidc.rst +++ b/docs/oidc.rst @@ -245,17 +245,16 @@ required claims, eg ``iss``, ``aud``, ``exp``, ``iat``, ``auth_time`` etc), and the ``sub`` claim will use the primary key of the user as the value. You'll probably want to customize this and add additional claims or change what is sent for the ``sub`` claim. To do so, you will need to add a method to -our custom validator. -Standard claim ``sub`` is included by default, for remove it override ``get_claim_list``:: +our custom validator:: + class CustomOAuth2Validator(OAuth2Validator): - def get_additional_claims(self): - def get_user_email(request): - return request.user.get_full_name() - - # Element name, callback to obtain data - claims_list = [ ("email", get_sub_cod), - ("username", get_user_email) ] - return claims_list + + def get_additional_claims(self, request): + return { + "sub": request.user.email, + "first_name": request.user.first_name, + "last_name": request.user.last_name, + } .. note:: This ``request`` object is not a ``django.http.Request`` object, but an diff --git a/oauth2_provider/oauth2_validators.py b/oauth2_provider/oauth2_validators.py index 461c40d53..f3a24e258 100644 --- a/oauth2_provider/oauth2_validators.py +++ b/oauth2_provider/oauth2_validators.py @@ -728,24 +728,15 @@ def _save_id_token(self, jti, request, expires, *args, **kwargs): def get_jwt_bearer_token(self, token, token_handler, request): return self.get_id_token(token, token_handler, request) - def get_claim_list(self): - def get_sub_code(request): - return str(request.user.id) - - list = [("sub", get_sub_code)] + def get_oidc_claims(self, token, token_handler, request): + # Required OIDC claims + claims = { + "sub": str(request.user.id), + } # https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims - add = self.get_additional_claims() - list.extend(add) - - return list + claims.update(**self.get_additional_claims(request)) - def get_oidc_claims(self, token, token_handler, request): - data = self.get_claim_list() - claims = {} - - for k, call in data: - claims[k] = call(request) return claims def get_id_token_dictionary(self, token, token_handler, request): @@ -898,5 +889,5 @@ def get_userinfo_claims(self, request): """ return self.get_oidc_claims(None, None, request) - def get_additional_claims(self): - return [] + def get_additional_claims(self, request): + return {} diff --git a/oauth2_provider/views/oidc.py b/oauth2_provider/views/oidc.py index 0cd24fc85..b4bb8869b 100644 --- a/oauth2_provider/views/oidc.py +++ b/oauth2_provider/views/oidc.py @@ -45,13 +45,6 @@ def get(self, request, *args, **kwargs): signing_algorithms = [Application.HS256_ALGORITHM] if oauth2_settings.OIDC_RSA_PRIVATE_KEY: signing_algorithms = [Application.RS256_ALGORITHM, Application.HS256_ALGORITHM] - - validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS - validator = validator_class() - oidc_claims = [] - for el, _ in validator.get_claim_list(): - oidc_claims.append(el) - data = { "issuer": issuer_url, "authorization_endpoint": authorization_endpoint, @@ -64,7 +57,6 @@ def get(self, request, *args, **kwargs): "token_endpoint_auth_methods_supported": ( oauth2_settings.OIDC_TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED ), - "claims_supported": oidc_claims, } response = JsonResponse(data) response["Access-Control-Allow-Origin"] = "*" diff --git a/tests/test_oidc_views.py b/tests/test_oidc_views.py index 719d10e98..46040f86d 100644 --- a/tests/test_oidc_views.py +++ b/tests/test_oidc_views.py @@ -29,7 +29,6 @@ def test_get_connect_discovery_info(self): "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["RS256", "HS256"], "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], - "claims_supported": ["sub"], } response = self.client.get(reverse("oauth2_provider:oidc-connect-discovery-info")) self.assertEqual(response.status_code, 200) @@ -56,7 +55,6 @@ def test_get_connect_discovery_info_without_issuer_url(self): "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["RS256", "HS256"], "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], - "claims_supported": ["sub"], } response = self.client.get(reverse("oauth2_provider:oidc-connect-discovery-info")) self.assertEqual(response.status_code, 200) @@ -148,21 +146,11 @@ def test_userinfo_endpoint_bad_token(oidc_tokens, client): assert rsp.status_code == 401 -EXAMPLE_EMAIL = "example.email@example.com" - - -def claim_user_email(request): - return EXAMPLE_EMAIL - - @pytest.mark.django_db def test_userinfo_endpoint_custom_claims(oidc_tokens, client, oauth2_settings): class CustomValidator(OAuth2Validator): - def get_additional_claims(self): - return [ - ("username", claim_user_email), - ("email", claim_user_email), - ] + def get_additional_claims(self, request): + return {"state": "very nice"} oidc_tokens.oauth2_settings.OAUTH2_VALIDATOR_CLASS = CustomValidator auth_header = "Bearer %s" % oidc_tokens.access_token @@ -173,9 +161,5 @@ def get_additional_claims(self): data = rsp.json() assert "sub" in data assert data["sub"] == str(oidc_tokens.user.pk) - - assert "username" in data - assert data["username"] == EXAMPLE_EMAIL - - assert "email" in data - assert data["email"] == EXAMPLE_EMAIL + assert "state" in data + assert data["state"] == "very nice" From c3dc78db277e2f7bf44fae7f2e3680df76b47022 Mon Sep 17 00:00:00 2001 From: Alan Crosswell Date: Thu, 23 Dec 2021 22:17:59 -0500 Subject: [PATCH 3/6] Replace RST header underline with one that pre-commit check-merge wont break on. (#1057) --- AUTHORS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index b741b49a4..20c83e46b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,11 @@ Authors -======= +------- Massimiliano Pippi Federico Frenguelli Contributors -============ +------------ Abhishek Patel Alan Crosswell From 45134594dab0a2a9c43ba33560b24bffcfc7b37b Mon Sep 17 00:00:00 2001 From: Alan Crosswell Date: Thu, 6 Jan 2022 10:56:20 -0500 Subject: [PATCH 4/6] Release 1.6.2 hotfix --- CHANGELOG.md | 4 +++- oauth2_provider/__init__.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c5b2f5c6..040d82a23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [1.6.2] unrelease +## [1.6.2] 2022-01-06 + +**NOTE: This release reverts an inadvertently-added breaking change.** ### Fixed diff --git a/oauth2_provider/__init__.py b/oauth2_provider/__init__.py index 68a0914f2..4848693a0 100644 --- a/oauth2_provider/__init__.py +++ b/oauth2_provider/__init__.py @@ -1,7 +1,7 @@ import django -__version__ = "1.6.1" +__version__ = "1.6.2" if django.VERSION < (3, 2): default_app_config = "oauth2_provider.apps.DOTConfig" From 45d9efcd9fafc5907c31fd6b0cea948c7dc5091a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Tue, 11 Jan 2022 14:37:15 +0100 Subject: [PATCH 5/6] fix #1083 ('token' not valid search field), add search fields to all remaining admin classes (#1085) * fix #1083 ('token' not valid search field), add search fields to all remaining admin classes --- oauth2_provider/admin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/oauth2_provider/admin.py b/oauth2_provider/admin.py index bd26dddb1..cf41ec5b2 100644 --- a/oauth2_provider/admin.py +++ b/oauth2_provider/admin.py @@ -25,6 +25,7 @@ class ApplicationAdmin(admin.ModelAdmin): "client_type": admin.HORIZONTAL, "authorization_grant_type": admin.VERTICAL, } + search_fields = ("name",) + (("user__email",) if has_email else ()) raw_id_fields = ("user",) @@ -39,12 +40,13 @@ class AccessTokenAdmin(admin.ModelAdmin): class GrantAdmin(admin.ModelAdmin): list_display = ("code", "application", "user", "expires") raw_id_fields = ("user",) + search_fields = ("code",) + (("user__email",) if has_email else ()) class IDTokenAdmin(admin.ModelAdmin): list_display = ("jti", "user", "application", "expires") raw_id_fields = ("user",) - search_fields = ("token",) + (("user__email",) if has_email else ()) + search_fields = ("user__email",) if has_email else () list_filter = ("application",) From 1a55feb40301caabd0869c46517413612743eae0 Mon Sep 17 00:00:00 2001 From: Alan Crosswell Date: Tue, 11 Jan 2022 08:49:00 -0500 Subject: [PATCH 6/6] Release 1.6.3 --- CHANGELOG.md | 8 ++++++++ oauth2_provider/__init__.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 040d82a23..28c7bc4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.3] 2022-01-11 + +### Fixed +* #1085 Fix for #1083 admin UI search for idtoken results in `django.core.exceptions.FieldError: Cannot resolve keyword 'token' into field.` + +### Added +* #1085 Add admin UI search fields for additional models. + ## [1.6.2] 2022-01-06 **NOTE: This release reverts an inadvertently-added breaking change.** diff --git a/oauth2_provider/__init__.py b/oauth2_provider/__init__.py index 4848693a0..487f0a884 100644 --- a/oauth2_provider/__init__.py +++ b/oauth2_provider/__init__.py @@ -1,7 +1,7 @@ import django -__version__ = "1.6.2" +__version__ = "1.6.3" if django.VERSION < (3, 2): default_app_config = "oauth2_provider.apps.DOTConfig"