Source code for simple_openid_connect.client_authentication

"""
Utilities and data types used when authenticating the relying party (client).

This should not be confused with authenticating a user as the user authentication at the OP is of no concern to us.
Instead, these authenticate the relying party when e.g. exchanging tokens or requesting user information.
It is a necessary process because while access tokens grant a relying party access to certain user information, the
relying party must still identify itself to the OP when accessing that information.

For more information visit `Section 9 of OpenID Connect Core 1.0 <https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication>`_ and `Section 2.3 of OAuth 2.0 [RFC6749] <https://www.rfc-editor.org/rfc/rfc6749#section-2.3>`_.
"""

import abc
from typing import Any

from requests import models
from requests.auth import AuthBase, HTTPBasicAuth

# TODO Implement more client authentication methods


[docs] class ClientAuthenticationMethod(AuthBase, metaclass=abc.ABCMeta): """ A base class for client authentication methods which describes the interface that each method implements to authenticate requests. This class also extends requests :class:`AuthBase` so that all derived implementations can directly be used with requests to authenticate something. """ NAME: str "How this authentication method is called in the Openid spec" @property @abc.abstractmethod def client_id(self) -> str: """ The client id which is assigned to this app """ raise NotImplementedError()
[docs] class NoneAuth(ClientAuthenticationMethod): """ The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism. """ NAME = "none"
[docs] def __init__(self, client_id: str): self._client_id = client_id
def __call__(self, r: models.PreparedRequest) -> models.PreparedRequest: return r @property def client_id(self) -> str: return self._client_id
[docs] class ClientSecretBasicAuth(ClientAuthenticationMethod, HTTPBasicAuth): """ Clients that have received a `client_secret` value from the Authorization Server authenticate with the Authorization Server using the HTTP Basic authentication scheme. """ NAME = "client_secret_basic" @property def client_id(self) -> str: return str(self.username)
[docs] def __init__(self, client_id: str, client_secret: str): """ :param client_id: The client id which was set or issued during client registration :param client_secret: The client secret which was issued during client registration """ super().__init__(username=client_id, password=client_secret)
[docs] class AccessTokenBearerAuth(AuthBase): """ Authenticate requests using a given bearer token """ access_token: str
[docs] def __init__(self, access_token: str): super().__init__() self.access_token = access_token
def __eq__(self, other: Any) -> bool: return self.access_token == getattr(other, "access_token", None) def __ne__(self, other: Any) -> bool: return not self == other def __call__(self, r: models.PreparedRequest) -> models.PreparedRequest: r.headers["Authorization"] = f"Bearer {self.access_token}" return r