"""OpenID Connect OAuth Views"""
from typing import Any

from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect


class OpenIDConnectOAuthRedirect(OAuthRedirect):
    """OpenIDConnect OAuth2 Redirect"""

    def get_additional_parameters(self, source: OAuthSource):  # pragma: no cover
        return {
            "scope": ["openid", "email", "profile"],
        }


class OpenIDConnectOAuth2Callback(OAuthCallback):
    """OpenIDConnect OAuth2 Callback"""

    client_class: UserprofileHeaderAuthClient

    def get_user_id(self, info: dict[str, str]) -> str:
        return info.get("sub", "")

    def get_user_enroll_context(
        self,
        info: dict[str, Any],
    ) -> dict[str, Any]:
        return {
            "username": info.get("nickname", info.get("preferred_username")),
            "email": info.get("email"),
            "name": info.get("name"),
        }


@registry.register()
class OpenIDConnectType(SourceType):
    """OpenIDConnect Type definition"""

    callback_view = OpenIDConnectOAuth2Callback
    redirect_view = OpenIDConnectOAuthRedirect
    name = "OpenID Connect"
    slug = "openidconnect"

    urls_customizable = True

authentik/sources/oauth/types/oidc.py
"""OpenID Connect OAuth Views"""
from typing import Any

from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect


class OpenIDConnectOAuthRedirect(OAuthRedirect):
    """OpenIDConnect OAuth2 Redirect"""

    def get_additional_parameters(self, source: OAuthSource):  # pragma: no cover
        return {
            "scope": ["openid", "email", "profile"],
        }


class OpenIDConnectOAuth2Callback(OAuthCallback):
    """OpenIDConnect OAuth2 Callback"""

    client_class = UserprofileHeaderAuthClient

    def get_user_id(self, info: dict[str, str]) -> str:
        return info.get("sub", "")

    def get_user_enroll_context(
        self,
        info: dict[str, Any],
    ) -> dict[str, Any]:
        return {
            "username": info.get("nickname", info.get("preferred_username")),
            "email": info.get("email"),
            "name": info.get("name"),
        }


@registry.register()
class OpenIDConnectType(SourceType):
    """OpenIDConnect Type definition"""

    callback_view = OpenIDConnectOAuth2Callback
    redirect_view = OpenIDConnectOAuthRedirect
    name = "OpenID Connect"
    slug = "openidconnect"

    urls_customizable = True

authentik/sources/oauth/types/oidc.py
diff --git a/authentik/sources/oauth/tests/test_type_openid.py b/authentik/sources/oauth/tests/test_type_openid.py
index 2f7395071331..e04bea4b0c7c 100644
--- a/authentik/sources/oauth/tests/test_type_openid.py
+++ b/authentik/sources/oauth/tests/test_type_openid.py
@@ -1,6 +1,8 @@
 """OpenID Type tests"""
-from django.test import TestCase
+from django.test import RequestFactory, TestCase
+from requests_mock import Mocker
 
+from authentik.lib.generators import generate_id
 from authentik.sources.oauth.models import OAuthSource
 from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
 
@@ -24,9 +26,10 @@ def setUp(self):
             slug="test",
             provider_type="openidconnect",
             authorization_url="",
-            profile_url="",
+            profile_url="http://localhost/userinfo",
             consumer_key="",
         )
+        self.factory = RequestFactory()
 
     def test_enroll_context(self):
         """Test OpenID Enrollment context"""
@@ -34,3 +37,19 @@ def test_enroll_context(self):
         self.assertEqual(ak_context["username"], OPENID_USER["nickname"])
         self.assertEqual(ak_context["email"], OPENID_USER["email"])
         self.assertEqual(ak_context["name"], OPENID_USER["name"])
+
+    @Mocker()
+    def test_userinfo(self, mock: Mocker):
+        """Test userinfo API call"""
+        mock.get("http://localhost/userinfo", json=OPENID_USER)
+        token = generate_id()
+        OpenIDConnectOAuth2Callback(request=self.factory.get("/")).get_client(
+            self.source
+        ).get_profile_info(
+            {
+                "token_type": "foo",
+                "access_token": token,
+            }
+        )
+        self.assertEqual(mock.last_request.query, "")
+        self.assertEqual(mock.last_request.headers["Authorization"], f"foo {token}")
diff --git a/authentik/sources/oauth/types/oidc.py b/authentik/sources/oauth/types/oidc.py
index 189209c43646..7ebd24579aab 100644
--- a/authentik/sources/oauth/types/oidc.py
+++ b/authentik/sources/oauth/types/oidc.py
@@ -20,7 +20,7 @@ def get_additional_parameters(self, source: OAuthSource):  # pragma: no cover
 class OpenIDConnectOAuth2Callback(OAuthCallback):
     """OpenIDConnect OAuth2 Callback"""
 
-    client_class: UserprofileHeaderAuthClient
+    client_class = UserprofileHeaderAuthClient
 
     def get_user_id(self, info: dict[str, str]) -> str:
         return info.get("sub", "")

Not sure that OAuth2 client source should use authorization header
I've been testing authentik using an Auth0 openIDC source as well as a google source. I have gotten both to work, but Auth0 was not working before a fix to prevent adding the access token to the authorizaton Bearer headers. Google auth works fine with or without this fix. 

https://auth0.com/blog/id-token-access-token-what-is-the-difference/ suggests that many endpoints should not be given the access token. Not sure this is relevant.

I think Auth0 is less permissive and prefers the access_token param rather than the Authorization Bearer token

in sources/oauth/clients/oauth2.py
```
class OAuth2Client(BaseOAuthClient):
    """OAuth2 Client"""

   ...

    def do_request(self, method: str, url: str, **kwargs) -> Response:
        """Build remote url request. Constructs necessary auth."""
        if "token" in kwargs:
            token = kwargs.pop("token")

            params = kwargs.get("params", {})
            params["access_token"] = token["access_token"]
            kwargs["params"] = params

            headers = kwargs.get("headers", {})
            # Note this fix
            # headers["Authorization"] = f"{token['token_type']} {token['access_token']}"
            kwargs["headers"] = headers
        return super().do_request(method, url, **kwargs)
```


