From 47ebe8cbd81b7b8d97ee110c28e3243d0eb563cd Mon Sep 17 00:00:00 2001 From: Josue Kouka Date: Wed, 8 Aug 2018 17:17:26 +0200 Subject: [PATCH] idp oidc: set user identifier as preferred username claim (#23900) --- .../migrations/0011_auto_20180808_1546.py | 38 ++++++++++++++++ tests/test_idp_oidc.py | 43 +++++++++++++++++-- 2 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/authentic2_idp_oidc/migrations/0011_auto_20180808_1546.py diff --git a/src/authentic2_idp_oidc/migrations/0011_auto_20180808_1546.py b/src/authentic2_idp_oidc/migrations/0011_auto_20180808_1546.py new file mode 100644 index 00000000..89863bcb --- /dev/null +++ b/src/authentic2_idp_oidc/migrations/0011_auto_20180808_1546.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +DEFAULT_CLAIM_VALUES = { + 'django_user_email', 'django_user_email_verified', 'django_user_first_name', + 'django_user_last_name', 'django_user_username'} + + +def set_oidcclient_default_preferred_username_as_identifier(apps, schema_editor): + OIDCClient = apps.get_model('authentic2_idp_oidc', 'OIDCClient') + OIDCClaim = apps.get_model('authentic2_idp_oidc', 'OIDCClaim') + for oidcclient in OIDCClient.objects.all(): + claim_values = set(oidcclient.oidcclaim_set.values_list('value', flat=True)) + # check if default config + if DEFAULT_CLAIM_VALUES.symmetric_difference(claim_values): + continue + pref_username_claim = OIDCClaim.objects.get(name='preferred_username', client=oidcclient) + if pref_username_claim.value != 'django_user_identifier': + pref_username_claim.value = 'django_user_identifier' + pref_username_claim.save() + + +def unset_oidcclient_default_preferred_username_as_identifier(apps, schema_editor): + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentic2_idp_oidc', '0010_oidcclaim'), + ] + + operations = [ + migrations.RunPython(set_oidcclient_default_preferred_username_as_identifier, unset_oidcclient_default_preferred_username_as_identifier) + ] diff --git a/tests/test_idp_oidc.py b/tests/test_idp_oidc.py index 2f77cde9..12aef82a 100644 --- a/tests/test_idp_oidc.py +++ b/tests/test_idp_oidc.py @@ -11,9 +11,12 @@ from jwcrypto.jwk import JWKSet, JWK import utils from django.core.urlresolvers import reverse +from django.db import connection +from django.db.migrations.executor import MigrationExecutor from django.utils.timezone import now from django.contrib.auth import get_user_model + User = get_user_model() from authentic2_idp_oidc.models import OIDCClient, OIDCAuthorization, OIDCCode, OIDCAccessToken, OIDCClaim @@ -856,9 +859,6 @@ def test_registration_service_slug(oidc_settings, app, simple_oidc_client, simpl def test_oidclient_claims_data_migration(): - from django.db import connection - from django.db.migrations.executor import MigrationExecutor - executor = MigrationExecutor(connection) app = 'authentic2_idp_oidc' migrate_from = [(app, '0009_auto_20180313_1156')] @@ -877,6 +877,43 @@ def test_oidclient_claims_data_migration(): assert OIDCClaim.objects.filter(client=client.id).count() == 5 +def test_oidclient_preferred_username_as_identifier_data_migration(): + executor = MigrationExecutor(connection) + app = 'authentic2_idp_oidc' + migrate_from = [(app, '0010_oidcclaim')] + migrate_to = [(app, '0011_auto_20180808_1546')] + executor.migrate(migrate_from) + executor.loader.build_graph() + old_apps = executor.loader.project_state(migrate_from).apps + OIDCClient = old_apps.get_model('authentic2_idp_oidc', 'OIDCClient') + OIDCClaim = old_apps.get_model('authentic2_idp_oidc', 'OIDCClaim') + client1 = OIDCClient.objects.create(name='test', slug='test', redirect_uris='https://example.net/') + client2 = OIDCClient.objects.create(name='test1', slug='test1', redirect_uris='https://example.net/') + client3 = OIDCClient.objects.create(name='test2', slug='test2', redirect_uris='https://example.net/') + for client in (client1, client2, client3): + if client.name == 'test1': + continue + OIDCClaim.objects.create(client=client, name='preferred_username', value='django_user_username', scopes='profile') + OIDCClaim.objects.create(client=client, name='given_name', value='django_user_first_name', scopes='profile') + OIDCClaim.objects.create(client=client, name='family_name', value='django_user_last_name', scopes='profile') + if client.name == 'test2': + continue + OIDCClaim.objects.create(client=client, name='email', value='django_user_email', scopes='email') + OIDCClaim.objects.create(client=client, name='email_verified', value='django_user_email_verified', scopes='email') + executor.migrate(migrate_to) + executor.loader.build_graph() + client = OIDCClient.objects.first() + for client in OIDCClient.objects.all(): + if client.name == 'test': + assert client.oidcclaim_set.count() == 5 + assert client.oidcclaim_set.get(name='preferred_username').value == 'django_user_identifier' + elif client.name == 'test2': + assert client.oidcclaim_set.count() == 3 + assert client.oidcclaim_set.get(name='preferred_username').value == 'django_user_username' + else: + assert client.oidcclaim_set.count() == 0 + + def test_api_synchronization(app, oidc_client): oidc_client.has_api_access = True oidc_client.save() -- 2.18.0