-
Notifications
You must be signed in to change notification settings - Fork 6
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
Replace digid_eherkenning_oidc_generics with library code #1297
Conversation
a3f7e32
to
748d8b8
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #1297 +/- ##
===========================================
- Coverage 94.88% 94.86% -0.03%
===========================================
Files 1045 1045
Lines 38692 38691 -1
===========================================
- Hits 36714 36704 -10
- Misses 1978 1987 +9
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this will need some face-to-face discussion :)
ADMIN_OIDC_USERNAME_CLAIM = config("ADMIN_OIDC_USERNAME_CLAIM", None) | ||
ADMIN_OIDC_GROUPS_CLAIM = config("ADMIN_OIDC_GROUPS_CLAIM", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these need to be lists of strings rather than strings
f078ed1
to
924977d
Compare
@@ -87,8 +87,7 @@ | |||
"django.contrib.auth.backends.ModelBackend", | |||
"digid_eherkenning.mock.backends.DigiDBackend", | |||
"eherkenning.mock.backends.eHerkenningBackend", | |||
"digid_eherkenning_oidc_generics.backends.OIDCAuthenticationDigiDBackend", | |||
"digid_eherkenning_oidc_generics.backends.OIDCAuthenticationEHerkenningBackend", | |||
"open_inwoner.accounts.backends.DigiDEHerkenningOIDCBackend", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the setting duplication here bit my ass in development, spent about 20 minutes trying to figure out why my breakpoint wasn't hitting :(
686d522
to
c728bd4
Compare
71e22ad
to
fd35173
Compare
@@ -16,6 +16,8 @@ | |||
from .forms import GroupAdminForm | |||
from .models import Action, Document, Invite, Message, User | |||
|
|||
# XXX: register proxy models and unregister digid_eherkenning.oidc models |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self-reminder!
Upgrade digid-eherkenning to a version with OIDC support. This requires a newer version of mozilla-django-oidc-db too.
The app_label is changed to avoid conflicts with the app_label defined in the 'digid_eherkenning.oidc' package. Migrations are added to rename any existing database tables and keep a consistent migration history/state. Special care is needed with regards to the django_migrations table - fixes here cannot be done through migrations, so the AppConfig.ready hook is used to bring these in a consistent state. Finally, the code that is replaced by the library is deleted to de-clutter, which includes uninstalling the models. The migrations are defined such that the new tables are created first and configuration can be copied over, which prevents data loss.
Some database fields have been renamed, which requires settings for the setup_configuration to be updated too. Future commits provide different authentication backends/views implementations, which require listing in their respective django settings too.
Using proxy models is the preferred approach to modify python behaviour as no database schema changes are usually required. This does require all code to call the proxy model rather than the concrete base model, or different outcomes for the same checks would cause problems. This includes the copy of the legacy data into the new models, which should be a smooth automatic migration.
The OIDC libraries support different OIDC-configurations/flow through the same views and backends, which is what this changeset achieves. The init views are exposed via separate URLs/endpoints, and bind the specific OIDC config flavour to be used to the endpoint. This information is recorded in the (session) state, and consulted again in the callback flow. All return flows (when returning from the OIDC Provider) go through the same callback view, which can route to specific handlers based on the configuration used. DigiD/eHerkenning is sent to a single authentication backend, which implements behaviours depending on the specific flavour used. The admin OIDC configuration is bound to the admin user backend, isolated from the DigiD/eHerkenning backend. Currently the callback URLs are still different urls for admin, digid and eherkenning, but there is no need for this - you can already use /oidc/callback/ instead (see the setting OIDC_CALLBACK_CLASS).
The configuration settings are tightly coupled to the django model fields (names and data types). The field names for the configuration have been changed compared to the vendored library, and the structure has been changed to be able to use claims with dots in their name. Unfortunately, this means that breaking changes in the infrastructure/ configuration setup are required because of the way this config is specified and used.
fd35173
to
fb2e811
Compare
fb2e811
to
7d70386
Compare
Possible values string | ||
Default value roles | ||
|
||
Possible values list of strings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can specify the values by adding the ClaimField
to custom fields in the settings:
DJANGO_SETUP_CONFIG_CUSTOM_FIELDS = [
{
"field": "mozilla_django_oidc_db.fields.ClaimField",
"description": "list of strings representing a claim",
},
]
Default value roles | ||
|
||
Possible values list of strings | ||
Default value [roles] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code responsible for returning roles
instead of [roles]
as default value is this:
if isinstance(field, (JSONField, ArrayField)) and isinstance(default, Sequence):
try:
return ", ".join(str(item) for item in default)
except TypeError:
return str(default)
The values for env variables used to configure an ArrayField
are comma-delimited strings, not lists (the comma-delimited string is transformed into a list via a call to config
in the settings).
|
||
def rename_app_label(): | ||
with connection.cursor() as cursor: | ||
# uses explicit query names so that we don't accidentally rwrite the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# uses explicit query names so that we don't accidentally rwrite the | |
# uses explicit query names so that we don't accidentally rewrite the |
( | ||
"digid_eherkenning_oidc_generics_legacy", | ||
"0003_alter_openidconnectdigidconfig_oidc_exempt_urls_and_more", | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something's going wrong. After renaming of the tables Django attempts to run:
digid_eherkenning_oidc_generics_legacy.0004_alter_openidconnectdigidconfig_table_and_more
and complains:
psycopg2.errors.UndefinedTable: relation "digid_eherkenning_oidc_generics_legacy_openidconnectdigidconfig" does not exist
Default value {'email': 'email', 'first_name': 'given_name', 'last_name': 'family_name'} | ||
|
||
Description Mapping from user-model fields to OIDC claim paths | ||
Possible values Mapping: {'some_key': ['Some value']} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The possible values are hard-coded for the different field types. Needs change in the library (or overwrite in the configuration step, but this would need to be done for every setting separately)
- Various models for digid-eherkenning-generics have the wrong database tables associated due to renaming of the app label before the migrations.
Replaced with #1448 , thanks Sergei for the hard work and patience! |
Excellent, I can start working on the next breaking changes now 😉 |
Trying this is as backwards compatible as possible, but there are some breaking changes. I can't find where to mention this in the documenation :/
Breaking changes
ADMIN_OIDC_CLAIM_MAPPING
must now be a mapping of key -> list of strings. This makes it possible to use dots in claim names while still supporting nesting. Every element in the array is a level of nesting. Change is because ofClaimField
support in mozilla-django-oidc-db 0.16+ADMIN_OIDC_USERNAME_CLAIM
must now be a list of strings. Same reason as above. I don't know how to fix this for the configuration via envvars, since the whole point of this feature is that no characters gain magical meaning. A comma could be used in a claim, so CSV splitting suffers from the same problem. Maybe it should just be ajson.loads(...)
call on the envvar string?ADMIN_OIDC_GROUPS_CLAIM
same as forADMIN_OIDC_USERNAME_CLAIM
OIDC_EXEMPT_URLS
configuration variables, after checking in the office these don't appear to be used at all. The config option was removed in mozilla-django-oidc-db*_OIDC_ERROR_MESSAGE_MAPPING
configuration variables, in favour of hardcoded messages.Questions
is theerror_message_mapping
really necessary? Error code + prescribed error messages are specified by OIDC standard and Logius, no?OIDC_EXEMPT_URLS
setting for the non-standard URLs? Otherwise there is a session refresh redirect loop issue for DigiD/eHerkenning/admin via OIDC I suspect.