Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
7 changes: 2 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.12', '3.13']
django: ['4.2', '5.2']
python: ['3.12', '3.13', '3.14']
django: ['5.2']
mozilla_django_oidc: ['5.0']
setup_config_enabled: ['no', 'yes']
exclude:
- python: '3.13'
django: '4.2'

name: "Run the test suite (Python ${{ matrix.python }}, Django ${{ matrix.django }},
mozilla-django-oidc ${{ matrix.mozilla_django_oidc }}, Setup Config: ${{ matrix.setup_config_enabled }}))"
Expand Down
4 changes: 1 addition & 3 deletions mozilla_django_oidc_db/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from collections.abc import Mapping

from .typing import EndpointFieldNames

# Mapping the configuration model fieldnames for endpoints to their
# corresponding names in the OIDC spec
OIDC_MAPPING: Mapping[EndpointFieldNames, str] = {
OIDC_MAPPING: dict[EndpointFieldNames, str] = {
"oidc_op_authorization_endpoint": "authorization_endpoint",
"oidc_op_token_endpoint": "token_endpoint",
"oidc_op_user_endpoint": "userinfo_endpoint",
Expand Down
5 changes: 3 additions & 2 deletions mozilla_django_oidc_db/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from collections.abc import Mapping
from collections.abc import Mapping, Sequence
from typing import ClassVar
from urllib.parse import urljoin

from django import forms
Expand All @@ -15,7 +16,7 @@


class OIDCProviderForm(forms.ModelForm):
required_endpoints = [
required_endpoints: ClassVar[Sequence[str]] = [
"oidc_op_authorization_endpoint",
"oidc_op_token_endpoint",
"oidc_op_user_endpoint",
Expand Down
10 changes: 6 additions & 4 deletions mozilla_django_oidc_db/setup_configuration/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Annotated, Literal
from collections.abc import Sequence
from typing import Annotated, ClassVar, Literal

from django.db.models import Model
from django.utils.translation import gettext_lazy as _

from django_setup_configuration.fields import DjangoModelRef
Expand Down Expand Up @@ -76,7 +78,7 @@ class OIDCConfigProviderModel(ConfigurationModel):
endpoint_config: OIDCProviderConfigUnion

class Meta:
django_model_refs = {
django_model_refs: ClassVar[dict[type[Model], Sequence[str]]] = {
OIDCProvider: [
"oidc_token_use_basic_auth",
"oidc_use_nonce",
Expand Down Expand Up @@ -217,7 +219,7 @@ class AdminOIDCConfigurationModelItem(ConfigurationModel):
)

class Meta:
django_model_refs = {
django_model_refs: ClassVar[dict[type[Model], Sequence[str]]] = {
OIDCClient: [
"oidc_rp_client_id",
"oidc_rp_client_secret",
Expand All @@ -227,7 +229,7 @@ class Meta:
"userinfo_claims_source",
]
}
extra_kwargs = {
extra_kwargs: ClassVar[dict[str, dict[str, object]]] = {
"oidc_rp_client_id": {"examples": ["modify-this"]},
"oidc_rp_client_secret": {"examples": ["modify-this"]},
"oidc_rp_idp_sign_key": {"examples": ["modify-this"]},
Expand Down
11 changes: 7 additions & 4 deletions mozilla_django_oidc_db/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def keycloak_login(
``state`` query parameters. Consume this with ``response = client.get(url)``.
"""
cm = Session() if session is None else nullcontext(session)
with cm as session:
login_page = session.get(login_url)
with cm as _session:
login_page = _session.get(login_url)
assert login_page.status_code == 200

# process keycloak's login form and submit the username + password to
Expand All @@ -40,7 +40,7 @@ def keycloak_login(
login_form = document("form#kc-form-login")
submit_url = login_form.attr("action")
assert isinstance(submit_url, str)
login_response = session.post(
login_response = _session.post(
submit_url,
data={
"username": username,
Expand All @@ -52,6 +52,9 @@ def keycloak_login(
)

assert login_response.status_code == 302
assert (redirect_uri := login_response.headers["Location"]).startswith(host)

redirect_uri = login_response.headers["Location"]

assert redirect_uri.startswith(host)

return redirect_uri
10 changes: 7 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ keywords = ["OIDC", "django", "database", "authentication"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Django",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.2",
"Intended Audience :: Developers",
"Operating System :: Unix",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Software Development :: Libraries :: Python Modules",
]
requires-python = ">=3.12"
dependencies = [
"django>=4.2",
"django>=5.2",
"django-jsonform>=2.12",
"glom",
"mozilla-django-oidc>=5.0.0",
Expand All @@ -44,7 +44,8 @@ Changelog = "https://github.com/maykinmedia/mozilla-django-oidc-db/blob/master/C

[project.optional-dependencies]
setup-configuration = [
"django-setup-configuration>=0.11.0",
# TODO
"django-setup-configuration @ git+https://github.com/maykinmedia/django-setup-configuration.git@chore/upgrade-dependencies",
]
tests = [
"psycopg",
Expand Down Expand Up @@ -160,3 +161,6 @@ section-order = [

[tool.ruff.lint.isort.sections]
"django" = ["django"]

[tool.ruff.lint.per-file-ignores]
"*/migrations/*.py" = ["RUF012"]
2 changes: 1 addition & 1 deletion testapp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"USER": os.getenv("PGUSER", "mozilla_django_oidc_db"),
"PASSWORD": os.getenv("PGPASSWORD", "mozilla_django_oidc_db"),
"HOST": os.getenv("DB_HOST", "localhost"),
"PORT": os.getenv("DB_PORT", 5432),
"PORT": int(os.getenv("DB_PORT", "5432")),
}
}

Expand Down
11 changes: 5 additions & 6 deletions tests/test_admin_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import requests_mock
from requests.exceptions import RequestException

from mozilla_django_oidc_db.forms import OIDCProviderForm
from mozilla_django_oidc_db.constants import EndpointFieldNames
from mozilla_django_oidc_db.forms import OIDC_MAPPING, OIDCProviderForm
from mozilla_django_oidc_db.models import OIDCClient
from tests.factories import UserFactory

Expand Down Expand Up @@ -65,10 +66,8 @@ def test_derive_endpoints_extra_field():
class ExtendedOIDCProviderForm(OIDCProviderForm):
required_endpoints = OIDCProviderForm.required_endpoints
# Define an extra field to derive from the configuration
oidc_mapping = dict(
**OIDCProviderForm.oidc_mapping,
**{"logout_endpoint": "end_session_endpoint"},
)
oidc_mapping: dict[EndpointFieldNames, str] = OIDC_MAPPING
oidc_mapping["oidc_op_logout_endpoint"] = "end_session_endpoint"

form = ExtendedOIDCProviderForm(data=form_data)

Expand All @@ -89,7 +88,7 @@ class ExtendedOIDCProviderForm(OIDCProviderForm):
# The endpoint that was added to the mapping on the extended form
# should be present in the cleaned data
assert (
form.cleaned_data["logout_endpoint"]
form.cleaned_data["oidc_op_logout_endpoint"]
== "http://provider.com/auth/realms/master/protocol/openid-connect/logout"
)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_callback_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,10 @@ def test_wrong_config_model_used(
init_view = OIDCAuthenticationRequestInitView.as_view(identifier="test-oidc")
init_view(auth_request)
# there is only one state expected
state_key = list(auth_request.session["oidc_states"].keys())[0]
state_key = next(iter(auth_request.session["oidc_states"].keys()))
callback_url = reverse("oidc_authentication_callback")
session = client.session
for key in auth_request.session.keys():
for key in auth_request.session.keys(): # ruff: ignore[SIM118]
session[key] = auth_request.session[key]
session.save()

Expand Down
5 changes: 1 addition & 4 deletions tests/test_logout.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,4 @@ def test_logout_response_has_redirect(dummy_config: OIDCClient, requests_mock):
headers={"Location": "http://testserver/endpoint-that-does-not-exist"},
)

try:
do_op_logout(dummy_config, id_token="dummy-id-token")
except Exception:
pytest.fail("Logout should not crash")
do_op_logout(dummy_config, id_token="dummy-id-token")
5 changes: 2 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[tox]
envlist =
py{312}-django{42,52}-mozilla_django_oidc{50}-setup_config_{enabled,disabled}
py{313}-django{52}-mozilla_django_oidc{50}-setup_config_{enabled,disabled}
py{312,313,314}-django{52}-mozilla_django_oidc{50}-setup_config_{enabled,disabled}
ruff
docs
typecheck
Expand All @@ -11,10 +10,10 @@ skip_missing_interpreters = true
python =
3.12: py312
3.13: py313
3.14: py314

[gh-actions:env]
DJANGO =
4.2: django42
5.2: django52
MOZILLA_DJANGO_OIDC =
5.0: mozilla_django_oidc50
Expand Down