Repository: goauthentik/authentik

Issue:
Add `x5c` and `x5t`to the `jwks` response
**Is your feature request related to a problem? Please describe.**
I am trying to use Authentik as the identity provider for netbird via OAuth2/OIDC

**Describe the solution you'd like**
netbird expects the JWKS endpoint which is `/application/o/<provider name>/jwks/` to have a property for the `x5c`. The `x5c` (X.509 certificate chain) Header Parameter contains the X.509 public key certificate or certificate chain corresponding to the key used to digitally sign the JWS (JSON Web Signature).

**Describe alternatives you've considered**
n/a

**Additional context**
For the OAuth2 Provider, I specified a signing key which populated the `jwks` endpoint response with the following values:
```
{
    "keys": [
        {
            "kty": "RSA",
            "alg": "RS256",
            "use": "sig",
            "kid": "*REDACTED*",
            "n": "*REDACTED*",
            "e": "AQAB"
        }
    ]
}
```

Comparing it to the example here: https://example.eu.auth0.com/.well-known/jwks.json , it is missing the `x5t` and `x5c` properties.


Discussion:

Resolving patch:
diff --git a/authentik/providers/oauth2/views/jwks.py b/authentik/providers/oauth2/views/jwks.py
--- a/authentik/providers/oauth2/views/jwks.py
+++ b/authentik/providers/oauth2/views/jwks.py
@@ -1,12 +1,14 @@
 """authentik OAuth2 JWKS Views"""
-from base64 import urlsafe_b64encode
+from base64 import b64encode, urlsafe_b64encode
 from typing import Optional
 
+from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric.ec import (
     EllipticCurvePrivateKey,
     EllipticCurvePublicKey,
 )
 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
+from cryptography.hazmat.primitives.serialization import Encoding
 from django.http import HttpRequest, HttpResponse, JsonResponse
 from django.shortcuts import get_object_or_404
 from django.views import View
@@ -30,12 +32,13 @@ class JWKSView(View):
     def get_jwk_for_key(self, key: CertificateKeyPair) -> Optional[dict]:
         """Convert a certificate-key pair into JWK"""
         private_key = key.private_key
+        key_data = None
         if not private_key:
-            return None
+            return key_data
         if isinstance(private_key, RSAPrivateKey):
             public_key: RSAPublicKey = private_key.public_key()
             public_numbers = public_key.public_numbers()
-            return {
+            key_data = {
                 "kty": "RSA",
                 "alg": JWTAlgorithms.RS256,
                 "use": "sig",
@@ -43,10 +46,10 @@ def get_jwk_for_key(self, key: CertificateKeyPair) -> Optional[dict]:
                 "n": b64_enc(public_numbers.n),
                 "e": b64_enc(public_numbers.e),
             }
-        if isinstance(private_key, EllipticCurvePrivateKey):
+        elif isinstance(private_key, EllipticCurvePrivateKey):
             public_key: EllipticCurvePublicKey = private_key.public_key()
             public_numbers = public_key.public_numbers()
-            return {
+            key_data = {
                 "kty": "EC",
                 "alg": JWTAlgorithms.ES256,
                 "use": "sig",
@@ -54,7 +57,20 @@ def get_jwk_for_key(self, key: CertificateKeyPair) -> Optional[dict]:
                 "n": b64_enc(public_numbers.n),
                 "e": b64_enc(public_numbers.e),
             }
-        return None
+        else:
+            return key_data
+        key_data["x5c"] = [b64encode(key.certificate.public_bytes(Encoding.DER)).decode("utf-8")]
+        key_data["x5t"] = (
+            urlsafe_b64encode(key.certificate.fingerprint(hashes.SHA1()))  # nosec
+            .decode("utf-8")
+            .rstrip("=")
+        )
+        key_data["x5t#S256"] = (
+            urlsafe_b64encode(key.certificate.fingerprint(hashes.SHA256()))
+            .decode("utf-8")
+            .rstrip("=")
+        )
+        return key_data
 
     def get(self, request: HttpRequest, application_slug: str) -> HttpResponse:
         """Show JWK Key data for Provider"""


Test patch: