# Path: core/helpers.py
# def filter_dict_keys(obj: dict, whitelist: Sequence) -> dict:
#     """
#     Filter dictionnary keys from a whitelist
# 
#     Args:
#         obj: the dictionnary to filter
#         whitelist: the whitelist of keys to keep
# 
#     Returns:
#         dict: the filtered dictionnary
#     """
#     return { k: v for k, v in obj.items() if k in whitelist }
# 
# Path: authentication/exceptions.py
# class OAuthException(APIException):
#     """
#     Custom OAuth Error for better feedback
#     """
#     status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
#     default_detail = "Une erreur est survenue avec l'authentification, veuillez contactez un administrateur"
#     default_code = 'oauth_error'
# 
#     @classmethod
#     def from_response(cls, response, code: str = None) -> 'OAuthException':
#         """
#         Create a OAuthException from an OAuth response
#         """
#         message = response.json().get('message', 'Unknown error')
#         details = None
# 
#         if 'unauthenticated' in message.lower():
#             details = message
#             code = code or 'unauthenticated'
#             message = "Requête OAuth non authentifié"  # TODO Better message
#             return OAuthTokenException(message, code, details)
# 
#         return cls(message, code, details)
# 
# class OAuthTokenException(OAuthException):
# 
#     default_code = 'token_error'


from typing import Union
from authlib.common.errors import AuthlibBaseError
from authlib.integrations.requests_client import OAuth2Session
from django.conf import settings
from django.core.cache import cache
from django.contrib import auth as django_auth
from django.contrib.auth.backends import ModelBackend
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import AuthenticationFailed
from core.helpers import filter_dict_keys
from authentication.exceptions import OAuthException, OAuthTokenException
import requests
        django_auth.logout(request)

        # Redirect to logout
        return self.config['logout_url']

    def fetch_resource(self, query: str) -> Union[dict, list]:
        """
        Return data from the API if valid else raise an OAuthException
        """
        if self.client.token:
            try:
                resp = self.client.get(self.config['base_url'] + query)
            except AuthlibBaseError as error:
                code = getattr(error, 'error', None)
                raise OAuthTokenException(code=code) from error
        else:
            # Try vanilla request if no token is specified
            try:
                resp = requests.get(self.config['base_url'] + query)
                if not resp.ok:
                    resp.raise_for_status()
            except requests.RequestException as error:
                raise OAuthTokenException(
                    message="Erreur lors de la requête, essayez avec un token valide.",
                    code="vanilla_request_error",
                ) from error

        if resp.ok:
            return resp.json()


# Path: core/helpers.py
# def filter_dict_keys(obj: dict, whitelist: Sequence) -> dict:
#     """
#     Filter dictionnary keys from a whitelist
# 
#     Args:
#         obj: the dictionnary to filter
#         whitelist: the whitelist of keys to keep
# 
#     Returns:
#         dict: the filtered dictionnary
#     """
#     return { k: v for k, v in obj.items() if k in whitelist }
# 
# Path: authentication/exceptions.py
# class OAuthException(APIException):
#     """
#     Custom OAuth Error for better feedback
#     """
#     status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
#     default_detail = "Une erreur est survenue avec l'authentification, veuillez contactez un administrateur"
#     default_code = 'oauth_error'
# 
#     @classmethod
#     def from_response(cls, response, code: str = None) -> 'OAuthException':
#         """
#         Create a OAuthException from an OAuth response
#         """
#         message = response.json().get('message', 'Unknown error')
#         details = None
# 
#         if 'unauthenticated' in message.lower():
#             details = message
#             code = code or 'unauthenticated'
#             message = "Requête OAuth non authentifié"  # TODO Better message
#             return OAuthTokenException(message, code, details)
# 
#         return cls(message, code, details)
# 
# class OAuthTokenException(OAuthException):
# 
#     default_code = 'token_error'


# Path: authentication/oauth.py
from typing import Union
from authlib.common.errors import AuthlibBaseError
from authlib.integrations.requests_client import OAuth2Session
from django.conf import settings
from django.core.cache import cache
from django.contrib import auth as django_auth
from django.contrib.auth.backends import ModelBackend
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import AuthenticationFailed
from core.helpers import filter_dict_keys
from authentication.exceptions import OAuthException, OAuthTokenException
import requests

        django_auth.logout(request)

        # Redirect to logout
        return self.config['logout_url']

    def fetch_resource(self, query: str) -> Union[dict, list]:
        """
        Return data from the API if valid else raise an OAuthException
        """
        if self.client.token:
            try:
                resp = self.client.get(self.config['base_url'] + query)
            except AuthlibBaseError as error:
                code = getattr(error, 'error', None)
                raise OAuthTokenException(code=code) from error
        else:
            # Try vanilla request if no token is specified
            try:
                resp = requests.get(self.config['base_url'] + query)
                if not resp.ok:
                    resp.raise_for_status()
            except requests.RequestException as error:
                raise OAuthTokenException(
                    message="Erreur lors de la requête, essayez avec un token valide.",
                    code="vanilla_request_error",
                ) from error

        if resp.ok:
            return resp.json()


        raise OAuthException.from_response(resp)