mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-09 02:10:34 +00:00
271b598cee
In this commit, we'll integrate a third-party service to track user events. We start by using the `identify` method to track sign-ins and sign-ups. Additionally, we use the `track` method to monitor custom events such as room creation, access token generation, and logouts. This will provide us with valuable data on current usage patterns. The analytics library operates by opening a queue in a separate thread for posting events, ensuring it remains non-blocking for the API. Let's test this in a real-world scenario.
104 lines
3.4 KiB
Python
104 lines
3.4 KiB
Python
"""Authentication Backends for the Meet core app."""
|
|
|
|
from django.core.exceptions import SuspiciousOperation
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
import requests
|
|
from mozilla_django_oidc.auth import (
|
|
OIDCAuthenticationBackend as MozillaOIDCAuthenticationBackend,
|
|
)
|
|
|
|
from core.models import User
|
|
|
|
from ..analytics import analytics
|
|
|
|
|
|
class OIDCAuthenticationBackend(MozillaOIDCAuthenticationBackend):
|
|
"""Custom OpenID Connect (OIDC) Authentication Backend.
|
|
|
|
This class overrides the default OIDC Authentication Backend to accommodate differences
|
|
in the User and Identity models, and handles signed and/or encrypted UserInfo response.
|
|
"""
|
|
|
|
def get_userinfo(self, access_token, id_token, payload):
|
|
"""Return user details dictionary.
|
|
|
|
Parameters:
|
|
- access_token (str): The access token.
|
|
- id_token (str): The id token (unused).
|
|
- payload (dict): The token payload (unused).
|
|
|
|
Note: The id_token and payload parameters are unused in this implementation,
|
|
but were kept to preserve base method signature.
|
|
|
|
Note: It handles signed and/or encrypted UserInfo Response. It is required by
|
|
Agent Connect, which follows the OIDC standard. It forces us to override the
|
|
base method, which deal with 'application/json' response.
|
|
|
|
Returns:
|
|
- dict: User details dictionary obtained from the OpenID Connect user endpoint.
|
|
"""
|
|
|
|
user_response = requests.get(
|
|
self.OIDC_OP_USER_ENDPOINT,
|
|
headers={"Authorization": f"Bearer {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()
|
|
userinfo = self.verify_token(user_response.text)
|
|
return userinfo
|
|
|
|
def get_or_create_user(self, access_token, id_token, payload):
|
|
"""Return a User based on userinfo. Get or create a new user if no user matches the Sub.
|
|
|
|
Parameters:
|
|
- access_token (str): The access token.
|
|
- id_token (str): The ID token.
|
|
- payload (dict): The user payload.
|
|
|
|
Returns:
|
|
- User: An existing or newly created User instance.
|
|
|
|
Raises:
|
|
- Exception: Raised when user creation is not allowed and no existing user is found.
|
|
"""
|
|
|
|
user_info = self.get_userinfo(access_token, id_token, payload)
|
|
sub = user_info.get("sub")
|
|
|
|
if sub is None:
|
|
raise SuspiciousOperation(
|
|
_("User info contained no recognizable user identification")
|
|
)
|
|
|
|
try:
|
|
user = User.objects.get(sub=sub)
|
|
except User.DoesNotExist:
|
|
if self.get_settings("OIDC_CREATE_USER", True):
|
|
user = self.create_user(user_info)
|
|
else:
|
|
user = None
|
|
|
|
analytics.identify(user=user)
|
|
return user
|
|
|
|
def create_user(self, claims):
|
|
"""Return a newly created User instance."""
|
|
|
|
sub = claims.get("sub")
|
|
|
|
if sub is None:
|
|
raise SuspiciousOperation(
|
|
_("Claims contained no recognizable user identification")
|
|
)
|
|
|
|
user = User.objects.create(
|
|
sub=sub,
|
|
email=claims.get("email"),
|
|
password="!", # noqa: S106
|
|
)
|
|
|
|
return user
|