(backend) add ServiceProvider

This adds the ServiceProvider notion to allow to better
manage which teams is available for each service provider.
This commit is contained in:
Quentin BEY
2024-11-04 11:32:41 +01:00
committed by BEY Quentin
parent 512d9fe82c
commit a041296f8a
27 changed files with 1392 additions and 10 deletions

View File

@@ -53,3 +53,20 @@ class ResourceServerAuthentication(OIDCAuthentication):
pass
return access_token
def authenticate(self, request):
"""
Authenticate the request and return a tuple of (user, token) or None.
We override the 'authenticate' method from the parent class to store
the introspected token audience inside the request.
"""
result = super().authenticate(request) # Might raise AuthenticationFailed
if result is None: # Case when there is no access token
return None
# Note: at this stage, the request is a "drf_request" object
request.resource_server_token_audience = self.backend.token_origin_audience
return result

View File

@@ -61,6 +61,10 @@ class ResourceServerBackend:
token_introspection={"essential": True},
)
# Declare the token origin audience: to know where the token comes from
# and store it for further use in the application
self.token_origin_audience = None
# pylint: disable=unused-argument
def get_or_create_user(self, access_token, id_token, payload):
"""Maintain API compatibility with OIDCAuthentication class from mozilla-django-oidc
@@ -85,6 +89,8 @@ class ResourceServerBackend:
that extends RFC 7662 by returning a signed and encrypted JWT for stronger assurance that
the authorization server issued the token introspection response.
"""
self.token_origin_audience = None # Reset the token origin audience
jwt = self._introspect(access_token)
claims = self._verify_claims(jwt)
user_info = self._verify_user_info(claims["token_introspection"])
@@ -100,6 +106,8 @@ class ResourceServerBackend:
logger.debug("Login failed: No user with %s found", sub)
return None
self.token_origin_audience = str(user_info["aud"])
return user
def _verify_user_info(self, introspection_response):
@@ -127,6 +135,12 @@ class ResourceServerBackend:
logger.debug(message)
raise SuspiciousOperation(message)
audience = introspection_response.get("aud", None)
if not audience:
raise SuspiciousOperation(
"Introspection response does not provide source audience."
)
return introspection_response
def _introspect(self, token):
@@ -219,6 +233,8 @@ class ResourceServerBackend:
class ResourceServerImproperlyConfiguredBackend:
"""Fallback backend for improperly configured Resource Servers."""
token_origin_audience = None
def get_or_create_user(self, access_token, id_token, payload):
"""Indicate that the Resource Server is improperly configured."""
raise AuthenticationFailed("Resource Server is improperly configured")