Skip to content

Commit

Permalink
Intégration de ProConnect (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
tut-tuuut authored Oct 30, 2024
2 parents db21a52 + 00b52c1 commit 4898c75
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 17 deletions.
13 changes: 12 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,15 @@ DATABASE_PORT=5432
DATABASE_URL=postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}

# see https://doc.demarches-simplifiees.fr/api-graphql/jeton-dauthentification
DS_API_TOKEN=
DS_API_TOKEN=

# Pro Connect / Agent Connect - see colleagues
PROCONNECT_CLIENT_ID=
PROCONNECT_CLIENT_SECRET=
PROCONNECT_DOMAIN="fca.integ01.dev-agentconnect.fr"

PROCONNECT_AUTHORIZATION_ENDPOINT="https://fca.integ01.dev-agentconnect.fr/api/v2/authorize"
PROCONNECT_TOKEN_ENDPOINT="https://fca.integ01.dev-agentconnect.fr/api/v2/token"
PROCONNECT_USER_ENDPOINT="https://fca.integ01.dev-agentconnect.fr/api/v2/userinfo"
PROCONNECT_JWKS_ENDPOINT="https://fca.integ01.dev-agentconnect.fr/api/v2/jwks"
PROCONNECT_SESSION_END="https://fca.integ01.dev-agentconnect.fr/session/end"
31 changes: 30 additions & 1 deletion gsl/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"mozilla_django_oidc",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
Expand All @@ -83,6 +84,11 @@
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

AUTHENTICATION_BACKENDS = [
"gsl_oidc.backends.OIDCAuthenticationBackend",
"django.contrib.auth.backends.ModelBackend",
]

AUTH_USER_MODEL = "gsl_core.Collegue"
ROOT_URLCONF = "gsl.urls"
LANGUAGE_CODE = "fr"
Expand Down Expand Up @@ -150,7 +156,7 @@
# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = "en-us"
LANGUAGE_CODE = "fr-fr"

TIME_ZONE = "UTC"

Expand All @@ -174,3 +180,26 @@
DS_API_URL = os.getenv(
"DS_API_URL", "https://www.demarches-simplifiees.fr/api/v2/graphql"
)

# Redirect after login/logout - used by OIDC backends

LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

# Connection to "Pro Connect" (OIDC)

OIDC_RP_SIGN_ALGO = "RS256"
OIDC_OP_JWKS_ENDPOINT = os.getenv("PROCONNECT_JWKS_ENDPOINT")
OIDC_RP_CLIENT_ID = os.getenv("PROCONNECT_CLIENT_ID")
OIDC_RP_CLIENT_SECRET = os.getenv("PROCONNECT_CLIENT_SECRET")
OIDC_RP_SCOPES = "openid email given_name usual_name uid siret idp_id"
OIDC_OP_AUTHORIZATION_ENDPOINT = os.getenv("PROCONNECT_AUTHORIZATION_ENDPOINT")
OIDC_OP_TOKEN_ENDPOINT = os.getenv("PROCONNECT_TOKEN_ENDPOINT")
OIDC_OP_USER_ENDPOINT = os.getenv("PROCONNECT_USER_ENDPOINT")

OIDC_OP_LOGOUT_ENDPOINT = os.getenv("PROCONNECT_SESSION_END")

OIDC_AUTH_REQUEST_EXTRA_PARAMS = {"acr_values": "eidas1"}
OIDC_RENEW_ID_TOKEN_EXPIRY_SECONDS = 4 * 60 * 60
OIDC_STORE_ID_TOKEN = True
ALLOW_LOGOUT_GET_METHOD = True
17 changes: 6 additions & 11 deletions gsl/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""

from django.contrib import admin
from django.urls import include, path

urlpatterns = [path("admin/", admin.site.urls), path("", include("gsl_pages.urls"))]
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("gsl_pages.urls")),
path("oidc/", include("mozilla_django_oidc.urls")),
]
13 changes: 13 additions & 0 deletions gsl_core/templates/blocks/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
{% translate "Display settings" %}
</button>
</li>
<li>
{% if user.is_authenticated %}
{{ user.email }}
<form action="{% url 'oidc_logout' %}" method="post">
{% csrf_token %}
<input type="submit" value="Déconnexion">
</form>
{% else %}
<a class="fr-btn fr-icon-lock-line" href="{% url 'oidc_authentication_init' %}">
Se connecter
</a>
{% endif %}
</li>
{% endblock header_tools %}

{% block operator_logo %}
Expand Down
Empty file added gsl_oidc/__init__.py
Empty file.
1 change: 1 addition & 0 deletions gsl_oidc/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Register your models here.
6 changes: 6 additions & 0 deletions gsl_oidc/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class GslOidcConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "gsl_oidc"
33 changes: 33 additions & 0 deletions gsl_oidc/backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from logging import getLogger

import requests
from mozilla_django_oidc.auth import (
OIDCAuthenticationBackend as MozillaOIDCAuthenticationBackend,
)

logger = getLogger(__name__)


class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
def get_userinfo(self, access_token, id_token, payload):
# Surcharge de la récupération des informations utilisateur:
# le décodage JSON du contenu JWT pose problème avec ProConnect
# qui le retourne en format JWT (content-type: application/jwt)
# d'où ce petit hack.
# Inspiré de : https://github.com/numerique-gouv/people/blob/b637774179d94cecb0ef2454d4762750a6a5e8c0/src/backend/core/authentication/backends.py#L47C1-L47C57
user_response = requests.get(
self.OIDC_OP_USER_ENDPOINT,
headers={"Authorization": "Bearer {0}".format(access_token)},
verify=self.get_settings("OIDC_VERIFY_SSL", True),
timeout=self.get_settings("OIDC_TIMEOUT", None),
proxies=self.get_settings("OIDC_PROXY", None),
)
user_response.raise_for_status()

try:
# cas où le type du token JWT est `application/json`
return user_response.json()
except requests.exceptions.JSONDecodeError:
# sinon, on présume qu'il s'agit d'un token JWT au format `application/jwt`
# comme c'est le cas pour ProConnect.
return self.verify_token(user_response.text)
Empty file added gsl_oidc/migrations/__init__.py
Empty file.
1 change: 1 addition & 0 deletions gsl_oidc/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Create your views here.
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ dependencies = [
"django-dsfr",
"django-referrer-policy",
"django-csp",
"mozilla-django-oidc",
]
# to add someday:
# django-dsfr

[tool.setuptools]
packages = ["gsl"]
Expand Down
20 changes: 19 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ certifi==2024.8.30
# via
# requests
# sentry-sdk
cffi==1.17.1
# via cryptography
cfgv==3.4.0
# via pre-commit
chardet==5.2.0
Expand All @@ -41,6 +43,11 @@ coverage[toml]==7.6.1
# via pytest-cov
cron-descriptor==1.4.5
# via django-celery-beat
cryptography==43.0.3
# via
# josepy
# mozilla-django-oidc
# pyopenssl
diff-cover==9.2.0
# via gsl (pyproject.toml)
distlib==0.3.8
Expand All @@ -58,6 +65,7 @@ django==5.1.1
# django-referrer-policy
# django-timezone-field
# gsl (pyproject.toml)
# mozilla-django-oidc
django-celery-beat==2.7.0
# via gsl (pyproject.toml)
django-celery-results==2.5.1
Expand Down Expand Up @@ -88,10 +96,14 @@ iniconfig==2.0.0
# via pytest
jinja2==3.1.4
# via diff-cover
josepy==1.14.0
# via mozilla-django-oidc
kombu==5.4.2
# via celery
markupsafe==2.1.5
# via jinja2
mozilla-django-oidc==4.0.1
# via gsl (pyproject.toml)
nodeenv==1.9.1
# via pre-commit
packaging==24.1
Expand All @@ -108,8 +120,12 @@ prompt-toolkit==3.0.48
# via click-repl
psycopg2-binary==2.9.9
# via gsl (pyproject.toml)
pycparser==2.22
# via cffi
pygments==2.18.0
# via diff-cover
pyopenssl==24.2.1
# via josepy
pytest==8.3.3
# via
# gsl (pyproject.toml)
Expand Down Expand Up @@ -138,7 +154,9 @@ pyyaml==6.0.2
redis==5.1.0
# via gsl (pyproject.toml)
requests==2.32.3
# via django-dsfr
# via
# django-dsfr
# mozilla-django-oidc
ruff==0.6.8
# via
# gsl (pyproject.toml)
Expand Down
20 changes: 19 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ certifi==2024.8.30
# via
# requests
# sentry-sdk
cffi==1.17.1
# via cryptography
charset-normalizer==3.3.2
# via requests
click==8.1.7
Expand All @@ -35,6 +37,11 @@ click-repl==0.3.0
# via celery
cron-descriptor==1.4.5
# via django-celery-beat
cryptography==43.0.3
# via
# josepy
# mozilla-django-oidc
# pyopenssl
dj-database-url==2.2.0
# via gsl (pyproject.toml)
django==5.1.1
Expand All @@ -48,6 +55,7 @@ django==5.1.1
# django-referrer-policy
# django-timezone-field
# gsl (pyproject.toml)
# mozilla-django-oidc
django-celery-beat==2.7.0
# via gsl (pyproject.toml)
django-celery-results==2.5.1
Expand All @@ -66,12 +74,20 @@ django-widget-tweaks==1.5.0
# via django-dsfr
idna==3.10
# via requests
josepy==1.14.0
# via mozilla-django-oidc
kombu==5.4.2
# via celery
mozilla-django-oidc==4.0.1
# via gsl (pyproject.toml)
prompt-toolkit==3.0.48
# via click-repl
psycopg2-binary==2.9.9
# via gsl (pyproject.toml)
pycparser==2.22
# via cffi
pyopenssl==24.2.1
# via josepy
python-crontab==3.2.0
# via django-celery-beat
python-dateutil==2.9.0.post0
Expand All @@ -83,7 +99,9 @@ python-dotenv==1.0.1
redis==5.1.0
# via gsl (pyproject.toml)
requests==2.32.3
# via django-dsfr
# via
# django-dsfr
# mozilla-django-oidc
sentry-sdk==2.15.0
# via gsl (pyproject.toml)
six==1.16.0
Expand Down

0 comments on commit 4898c75

Please sign in to comment.