Skip to content

Commit

Permalink
pro_connect: Add a new SSO
Browse files Browse the repository at this point in the history
  • Loading branch information
tonial committed Jun 17, 2024
1 parent e04beb3 commit c5bffd3
Show file tree
Hide file tree
Showing 28 changed files with 1,587 additions and 36 deletions.
5 changes: 5 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"itou.openid_connect.france_connect",
"itou.openid_connect.inclusion_connect",
"itou.openid_connect.pe_connect",
"itou.openid_connect.pro_connect",
"itou.invitations",
"itou.external_data",
"itou.metabase",
Expand Down Expand Up @@ -401,6 +402,10 @@
INCLUSION_CONNECT_CLIENT_ID = os.getenv("INCLUSION_CONNECT_CLIENT_ID")
INCLUSION_CONNECT_CLIENT_SECRET = os.getenv("INCLUSION_CONNECT_CLIENT_SECRET")

PRO_CONNECT_BASE_URL = os.getenv("PRO_CONNECT_BASE_URL")
PRO_CONNECT_CLIENT_ID = os.getenv("PRO_CONNECT_CLIENT_ID")
PRO_CONNECT_CLIENT_SECRET = os.getenv("PRO_CONNECT_CLIENT_SECRET")

TALLY_URL = os.getenv("TALLY_URL")

METABASE_HOST = os.getenv("METABASE_HOST")
Expand Down
2 changes: 2 additions & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
path("franceconnect/", include("itou.openid_connect.france_connect.urls")),
# Inclusion Connect URLs.
path("inclusion_connect/", include("itou.openid_connect.inclusion_connect.urls")),
# Pro Connect URLs.
path("pro_connect/", include("itou.openid_connect.pro_connect.urls")),
# --------------------------------------------------------------------------------------
# API.
path("api/v1/", include("itou.api.urls", namespace="v1")),
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions itou/openid_connect/pro_connect/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ProConnectConfig(AppConfig):
name = "itou.openid_connect.pro_connect"
verbose_name = "Pro Connect"
19 changes: 19 additions & 0 deletions itou/openid_connect/pro_connect/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.conf import settings


# https://github.com/france-connect/Documentation-AgentConnect/blob/main/doc_fs/technique_fca/technique_fca_scope.md
PRO_CONNECT_SCOPES = "openid email given_name usual_name"

PRO_CONNECT_CLIENT_ID = settings.PRO_CONNECT_CLIENT_ID
PRO_CONNECT_CLIENT_SECRET = settings.PRO_CONNECT_CLIENT_SECRET

PRO_CONNECT_ENDPOINT_BASE = f"{settings.PRO_CONNECT_BASE_URL}/api/v2"
PRO_CONNECT_ENDPOINT_AUTHORIZE = f"{PRO_CONNECT_ENDPOINT_BASE}/authorize"
PRO_CONNECT_ENDPOINT_TOKEN = f"{PRO_CONNECT_ENDPOINT_BASE}/token"
PRO_CONNECT_ENDPOINT_USERINFO = f"{PRO_CONNECT_ENDPOINT_BASE}/userinfo"
PRO_CONNECT_ENDPOINT_LOGOUT = f"{PRO_CONNECT_ENDPOINT_BASE}/session/end"

# These expiration times have been chosen arbitrarily.
PRO_CONNECT_TIMEOUT = 60

PRO_CONNECT_SESSION_KEY = "pro_connect"
11 changes: 11 additions & 0 deletions itou/openid_connect/pro_connect/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import enum


class ProConnectChannel(str, enum.Enum):
"""This enum is stored in the session, and allow us to change the error message
in the callback view depending on where the user came from.
"""

INVITATION = "invitation"
POLE_EMPLOI = "pole_emploi"
MAP_CONSEILLER = "map_conseiller"
31 changes: 31 additions & 0 deletions itou/openid_connect/pro_connect/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 5.0.3 on 2024-03-22 09:37

import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):
initial = True

dependencies = []

operations = [
migrations.CreateModel(
name="ProConnectState",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
(
"created_at",
models.DateTimeField(
db_index=True, default=django.utils.timezone.now, verbose_name="date de création"
),
),
("used_at", models.DateTimeField(null=True, verbose_name="date d'utilisation")),
("data", models.JSONField(blank=True, default=dict, verbose_name="données de session")),
("state", models.CharField(max_length=12, unique=True)),
],
options={
"abstract": False,
},
),
]
Empty file.
55 changes: 55 additions & 0 deletions itou/openid_connect/pro_connect/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import dataclasses
import logging

from django.db import models

from itou.prescribers.models import PrescriberOrganization
from itou.users.enums import IdentityProvider, UserKind
from itou.users.models import User

from ..models import OIDConnectState, OIDConnectUserData


logger = logging.getLogger(__name__)


class ProConnectState(OIDConnectState):
data = models.JSONField(verbose_name="données de session", default=dict, blank=True)

class Meta:
abstract = False


@dataclasses.dataclass
class ProConnectUserData(OIDConnectUserData):
@staticmethod
def user_info_mapping_dict(user_info: dict):
return {
"username": user_info["sub"],
"first_name": user_info["given_name"],
"last_name": user_info["usual_name"],
"email": user_info["email"],
}


@dataclasses.dataclass
class ProConnectPrescriberData(ProConnectUserData):
kind: str = UserKind.PRESCRIBER
identity_provider: IdentityProvider = IdentityProvider.PRO_CONNECT
login_allowed_user_kinds = [UserKind.PRESCRIBER, UserKind.EMPLOYER]

def join_org(self, user: User, safir: str):
try:
organization = PrescriberOrganization.objects.get(code_safir_pole_emploi=safir)
except PrescriberOrganization.DoesNotExist:
logger.error(f"Organization with SAFIR {safir} does not exist. Unable to add user {user.email}.")
raise
if not organization.has_member(user):
organization.add_member(user)


@dataclasses.dataclass
class ProConnectEmployerData(ProConnectUserData):
kind: str = UserKind.EMPLOYER
identity_provider: IdentityProvider = IdentityProvider.PRO_CONNECT
login_allowed_user_kinds = [UserKind.PRESCRIBER, UserKind.EMPLOYER]
14 changes: 14 additions & 0 deletions itou/openid_connect/pro_connect/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.urls import path

from . import views


app_name = "pro_connect"

urlpatterns = [
path("authorize", views.pro_connect_authorize, name="authorize"),
path("activate_account", views.pro_connect_activate_account, name="activate_account"),
path("callback", views.pro_connect_callback, name="callback"),
path("logout", views.pro_connect_logout, name="logout"),
path("logout_callback", views.pro_connect_logout_callback, name="logout_callback"),
]
Loading

0 comments on commit c5bffd3

Please sign in to comment.