Skip to content
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

Feature/OIDC #279

Merged
merged 20 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ django-timeline-logger
django-rich
django-csp
django-csp-reports
mozilla-django-oidc-db

# API libraries
djangorestframework
Expand Down
27 changes: 24 additions & 3 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ commonmark==0.9.1
confusable-homoglyphs==3.2.0
# via django-registration
cryptography==35.0.0
# via pyopenssl
# via
# josepy
# mozilla-django-oidc
# pyopenssl
cssselect2==0.4.1
# via weasyprint
defusedxml==0.7.1
Expand Down Expand Up @@ -81,6 +84,8 @@ django==3.2.13
# easy-thumbnails
# mail-editor
# maykin-django-two-factor-auth
# mozilla-django-oidc
# mozilla-django-oidc-db
# zgw-consumers
django-admin-index==1.5.0
# via -r requirements/base.in
Expand All @@ -91,7 +96,9 @@ django-autoslug==1.9.8
django-axes==5.25.0
# via -r requirements/base.in
django-better-admin-arrayfield==1.4.2
# via -r requirements/base.in
# via
# -r requirements/base.in
# mozilla-django-oidc-db
django-choices==1.7.2
# via
# -r requirements/base.in
Expand Down Expand Up @@ -165,6 +172,7 @@ django-sniplates==0.7.0
django-solo==1.2.0
# via
# -r requirements/base.in
# mozilla-django-oidc-db
# zgw-consumers
django-timeline-logger==2.0.0
# via -r requirements/base.in
Expand Down Expand Up @@ -210,7 +218,9 @@ geographiclib==1.52
geopy==2.2.0
# via -r requirements/base.in
glom==20.11.0
# via -r requirements/base.in
# via
# -r requirements/base.in
# mozilla-django-oidc-db
html5lib==1.1
# via weasyprint
humanfriendly==10.0
Expand All @@ -223,6 +233,8 @@ inflection==0.5.1
# via drf-spectacular
isodate==0.6.1
# via python3-saml
josepy==1.13.0
# via mozilla-django-oidc
jsonschema==4.1.0
# via drf-spectacular
lxml==4.6.3
Expand All @@ -238,6 +250,10 @@ markuppy==1.14
# via tablib
maykin-django-two-factor-auth==2.0.4
# via -r requirements/base.in
mozilla-django-oidc==2.0.0
# via mozilla-django-oidc-db
mozilla-django-oidc-db==0.10.0
# via -r requirements/base.in
odfpy==1.4.1
# via tablib
openpyxl==3.0.9
Expand Down Expand Up @@ -266,6 +282,7 @@ pyjwt==2.3.0
pyopenssl==21.0.0
# via
# -r requirements/base.in
# josepy
# python3-saml
# zgw-consumers
pyphen==0.12.0
Expand Down Expand Up @@ -304,6 +321,7 @@ requests==2.26.0
# via
# django-rosetta
# gemma-zds-client
# mozilla-django-oidc
# python3-saml
# requests-mock
# zgw-consumers
Expand Down Expand Up @@ -369,3 +387,6 @@ zipp==3.6.0
# via importlib-metadata
zopfli==0.1.9
# via fonttools

# The following packages are considered to be unsafe in a requirements file:
# setuptools
23 changes: 23 additions & 0 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ cryptography==35.0.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
# josepy
# mozilla-django-oidc
# pyopenssl
cssselect==1.1.0
# via pyquery
Expand Down Expand Up @@ -125,6 +127,8 @@ django==3.2.13
# easy-thumbnails
# mail-editor
# maykin-django-two-factor-auth
# mozilla-django-oidc
# mozilla-django-oidc-db
# zgw-consumers
django-admin-index==1.5.0
# via
Expand All @@ -147,6 +151,7 @@ django-better-admin-arrayfield==1.4.2
# via
# -c requirements/base.txt
# -r requirements/base.txt
# mozilla-django-oidc-db
django-choices==1.7.2
# via
# -c requirements/base.txt
Expand Down Expand Up @@ -287,6 +292,7 @@ django-solo==1.2.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
# mozilla-django-oidc-db
# zgw-consumers
django-timeline-logger==2.0.0
# via
Expand Down Expand Up @@ -387,6 +393,7 @@ glom==20.11.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
# mozilla-django-oidc-db
html5lib==1.1
# via
# -c requirements/base.txt
Expand Down Expand Up @@ -418,6 +425,11 @@ isodate==0.6.1
# python3-saml
isort==5.9.3
# via pylint
josepy==1.13.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
# mozilla-django-oidc
jsonschema==4.1.0
# via
# -c requirements/base.txt
Expand Down Expand Up @@ -452,6 +464,15 @@ maykin-django-two-factor-auth==2.0.4
# -r requirements/base.txt
mccabe==0.6.1
# via pylint
mozilla-django-oidc==2.0.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
# mozilla-django-oidc-db
mozilla-django-oidc-db==0.10.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
odfpy==1.4.1
# via
# -c requirements/base.txt
Expand Down Expand Up @@ -517,6 +538,7 @@ pyopenssl==21.0.0
# -c requirements/base.txt
# -r requirements/base.txt
# -r requirements/test-tools.in
# josepy
# python3-saml
# zgw-consumers
pyphen==0.12.0
Expand Down Expand Up @@ -589,6 +611,7 @@ requests==2.26.0
# -r requirements/base.txt
# django-rosetta
# gemma-zds-client
# mozilla-django-oidc
# python3-saml
# requests-mock
# zgw-consumers
Expand Down
23 changes: 23 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ cryptography==35.0.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# josepy
# mozilla-django-oidc
# pyopenssl
cssselect==1.1.0
# via
Expand Down Expand Up @@ -150,6 +152,8 @@ django==3.2.13
# easy-thumbnails
# mail-editor
# maykin-django-two-factor-auth
# mozilla-django-oidc
# mozilla-django-oidc-db
# zgw-consumers
django-admin-index==1.5.0
# via
Expand All @@ -172,6 +176,7 @@ django-better-admin-arrayfield==1.4.2
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# mozilla-django-oidc-db
django-choices==1.7.2
# via
# -c requirements/ci.txt
Expand Down Expand Up @@ -316,6 +321,7 @@ django-solo==1.2.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# mozilla-django-oidc-db
# zgw-consumers
django-timeline-logger==2.0.0
# via
Expand Down Expand Up @@ -432,6 +438,7 @@ glom==20.11.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# mozilla-django-oidc-db
html5lib==1.1
# via
# -c requirements/ci.txt
Expand Down Expand Up @@ -471,6 +478,11 @@ isort==5.9.3
# pylint
jinja2==3.0.1
# via sphinx
josepy==1.13.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# mozilla-django-oidc
jsonschema==4.1.0
# via
# -c requirements/ci.txt
Expand Down Expand Up @@ -514,6 +526,15 @@ mccabe==0.6.1
# -r requirements/ci.txt
# flake8
# pylint
mozilla-django-oidc==2.0.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# mozilla-django-oidc-db
mozilla-django-oidc-db==0.10.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
mypy-extensions==0.4.3
# via black
odfpy==1.4.1
Expand Down Expand Up @@ -603,6 +624,7 @@ pyopenssl==21.0.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
# josepy
# python3-saml
# zgw-consumers
pyparsing==2.4.7
Expand Down Expand Up @@ -683,6 +705,7 @@ requests==2.26.0
# ddt-api-calls
# django-rosetta
# gemma-zds-client
# mozilla-django-oidc
# python3-saml
# requests-mock
# sphinx
Expand Down
8 changes: 7 additions & 1 deletion src/open_inwoner/accounts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class ActionInlineAdmin(UUIDAdminFirstInOrder, admin.StackedInline):
@admin.register(User)
class _UserAdmin(UserAdmin):
hijack_success_url = reverse_lazy("root")
list_display_links = (
"email",
"first_name",
)
fieldsets = (
(None, {"fields": ("email", "password", "login_type")}),
(
Expand All @@ -31,6 +35,7 @@ class _UserAdmin(UserAdmin):
"contact_type",
"bsn",
"rsin",
"oidc_id",
"birthday",
"street",
"housenumber",
Expand Down Expand Up @@ -66,11 +71,12 @@ class _UserAdmin(UserAdmin):
},
),
)
readonly_fields = ("bsn", "rsin", "is_prepopulated")
readonly_fields = ("bsn", "rsin", "is_prepopulated", "oidc_id")
list_display = (
"email",
"first_name",
"last_name",
"login_type",
"is_staff",
"is_active",
"contact_type",
Expand Down
38 changes: 38 additions & 0 deletions src/open_inwoner/accounts/backends.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import logging

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import check_password

from axes.backends import AxesBackend
from mozilla_django_oidc_db.backends import OIDCAuthenticationBackend

from .choices import LoginTypeChoices

logger = logging.getLogger(__name__)


class UserModelEmailBackend(ModelBackend):
Expand All @@ -24,3 +31,34 @@ class CustomAxesBackend(AxesBackend):
def authenticate(self, request=None, *args, **kwargs):
if request:
return super().authenticate(request, *args, **kwargs)


class CustomOIDCBackend(OIDCAuthenticationBackend):
def create_user(self, claims):
"""Return object for a newly created user account."""
unique_id = self.retrieve_identifier_claim(claims)

email = f"{unique_id}@openinwoner.nl"
if "email" in claims:
email = claims["email"]

logger.debug("Creating OIDC user: %s", unique_id)

kwargs = {
"oidc_id": unique_id,
"email": email,
"login_type": LoginTypeChoices.oidc,
}

user = self.UserModel.objects.create_user(**kwargs)
self.update_user(user, claims)

return user

def filter_users_by_claims(self, claims):
"""Return all users matching the specified subject."""
unique_id = self.retrieve_identifier_claim(claims)

if not unique_id:
return self.UserModel.objects.none()
return self.UserModel.objects.filter(**{"oidc_id__iexact": unique_id})
1 change: 1 addition & 0 deletions src/open_inwoner/accounts/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class LoginTypeChoices(DjangoChoices):
default = ChoiceItem("default", _("E-mail en Wachtwoord"))
digid = ChoiceItem("digid", _("DigiD"))
eherkenning = ChoiceItem("eherkenning", _("eHerkenning"))
oidc = ChoiceItem("oidc", _("OpenId connect"))


# Created because of a filter that needs to happen. This way the form can take the empty choice and the modal is still filled.
Expand Down
18 changes: 18 additions & 0 deletions src/open_inwoner/accounts/migrations/0044_user_oidc_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.13 on 2022-06-22 13:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("accounts", "0043_change_digid_email"),
]

operations = [
migrations.AddField(
model_name="user",
name="oidc_id",
field=models.CharField(blank=True, default="", max_length=250),
),
]
Loading