authentik.providers.oauth2.tests.test_jwks
JWKS tests
1"""JWKS tests""" 2 3import base64 4import json 5 6from cryptography.hazmat.backends import default_backend 7from cryptography.x509 import load_der_x509_certificate 8from django.urls.base import reverse 9from jwt import PyJWKSet 10 11from authentik.core.models import Application 12from authentik.core.tests.utils import create_test_cert, create_test_flow 13from authentik.crypto.builder import PrivateKeyAlg 14from authentik.crypto.models import CertificateKeyPair 15from authentik.lib.generators import generate_id 16from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode 17from authentik.providers.oauth2.tests.utils import OAuthTestCase 18 19TEST_CORDS_CERT = """ 20-----BEGIN CERTIFICATE----- 21MIIB6jCCAZCgAwIBAgIRAOsdE3N7zETzs+7shTXGj5wwCgYIKoZIzj0EAwIwHjEc 22MBoGA1UEAwwTYXV0aGVudGlrIDIwMjIuMTIuMjAeFw0yMzAxMTYyMjU2MjVaFw0y 23NDAxMTIyMjU2MjVaMHgxTDBKBgNVBAMMQ0NsbDR2TzFJSGxvdFFhTGwwMHpES2tM 24WENYdzRPUFF2eEtZN1NrczAuc2VsZi1zaWduZWQuZ29hdXRoZW50aWsuaW8xEjAQ 25BgNVBAoMCWF1dGhlbnRpazEUMBIGA1UECwwLU2VsZi1zaWduZWQwWTATBgcqhkjO 26PQIBBggqhkjOPQMBBwNCAAQAwOGam7AKOi5LKmb9lK1rAzA2JTppqrFiIaUdjqmH 27ZICJP00Wt0dfqOtEjgMEv1Hhu1DmKZn2ehvpxwPSzBr5o1UwUzBRBgNVHREBAf8E 28RzBFgkNCNkw4YlI0UldJRU42NUZLamdUTzV1YmRvNUZWdkpNS2lxdjFZeTRULnNl 29bGYtc2lnbmVkLmdvYXV0aGVudGlrLmlvMAoGCCqGSM49BAMCA0gAMEUCIC/JAfnl 30uC30ihqepbiMCaTaPMbL8Ka2Lk92IYfMhf46AiEAz9Kmv6HF2D4MK54iwhz2WqvF 318vo+OiGdTQ1Qoj7fgYU= 32-----END CERTIFICATE----- 33""" 34TEST_CORDS_KEY = """ 35-----BEGIN EC PRIVATE KEY----- 36MHcCAQEEIKy6mPLJc5v71InMMvYaxyXI3xXpwQTPLyAYWVFnZHVioAoGCCqGSM49 37AwEHoUQDQgAEAMDhmpuwCjouSypm/ZStawMwNiU6aaqxYiGlHY6ph2SAiT9NFrdH 38X6jrRI4DBL9R4btQ5imZ9nob6ccD0swa+Q== 39-----END EC PRIVATE KEY----- 40""" 41 42 43class TestJWKS(OAuthTestCase): 44 """Test JWKS view""" 45 46 def test_rs256(self): 47 """Test JWKS request with RS256""" 48 provider = OAuth2Provider.objects.create( 49 name="test", 50 client_id="test", 51 authorization_flow=create_test_flow(), 52 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 53 signing_key=create_test_cert(), 54 ) 55 app = Application.objects.create(name="test", slug="test", provider=provider) 56 response = self.client.get( 57 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 58 ) 59 body = json.loads(response.content.decode()) 60 self.assertEqual(len(body["keys"]), 1) 61 PyJWKSet.from_dict(body) 62 key = body["keys"][0] 63 load_der_x509_certificate(base64.b64decode(key["x5c"][0]), default_backend()).public_key() 64 65 def test_hs256(self): 66 """Test JWKS request with HS256""" 67 provider = OAuth2Provider.objects.create( 68 name="test", 69 client_id="test", 70 authorization_flow=create_test_flow(), 71 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 72 ) 73 app = Application.objects.create(name="test", slug="test", provider=provider) 74 response = self.client.get( 75 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 76 ) 77 self.assertJSONEqual(response.content.decode(), {}) 78 79 def test_es256(self): 80 """Test JWKS request with ES256""" 81 provider = OAuth2Provider.objects.create( 82 name="test", 83 client_id="test", 84 authorization_flow=create_test_flow(), 85 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 86 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 87 ) 88 app = Application.objects.create(name="test", slug="test", provider=provider) 89 response = self.client.get( 90 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 91 ) 92 body = json.loads(response.content.decode()) 93 self.assertEqual(len(body["keys"]), 1) 94 PyJWKSet.from_dict(body) 95 96 def test_enc(self): 97 """Test with JWE""" 98 provider = OAuth2Provider.objects.create( 99 name="test", 100 client_id="test", 101 authorization_flow=create_test_flow(), 102 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 103 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 104 encryption_key=create_test_cert(PrivateKeyAlg.ECDSA), 105 ) 106 app = Application.objects.create(name="test", slug="test", provider=provider) 107 response = self.client.get( 108 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 109 ) 110 body = json.loads(response.content.decode()) 111 self.assertEqual(len(body["keys"]), 2) 112 PyJWKSet.from_dict(body) 113 114 def test_ecdsa_coords_mismatched(self): 115 """Test JWKS request with ES256""" 116 cert = CertificateKeyPair.objects.create( 117 name=generate_id(), 118 key_data=TEST_CORDS_KEY, 119 certificate_data=TEST_CORDS_CERT, 120 ) 121 provider = OAuth2Provider.objects.create( 122 name="test", 123 client_id="test", 124 authorization_flow=create_test_flow(), 125 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 126 signing_key=cert, 127 ) 128 app = Application.objects.create(name="test", slug="test", provider=provider) 129 response = self.client.get( 130 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 131 ) 132 body = json.loads(response.content.decode()) 133 self.assertEqual(len(body["keys"]), 1) 134 PyJWKSet.from_dict(body)
TEST_CORDS_CERT =
'\n-----BEGIN CERTIFICATE-----\nMIIB6jCCAZCgAwIBAgIRAOsdE3N7zETzs+7shTXGj5wwCgYIKoZIzj0EAwIwHjEc\nMBoGA1UEAwwTYXV0aGVudGlrIDIwMjIuMTIuMjAeFw0yMzAxMTYyMjU2MjVaFw0y\nNDAxMTIyMjU2MjVaMHgxTDBKBgNVBAMMQ0NsbDR2TzFJSGxvdFFhTGwwMHpES2tM\nWENYdzRPUFF2eEtZN1NrczAuc2VsZi1zaWduZWQuZ29hdXRoZW50aWsuaW8xEjAQ\nBgNVBAoMCWF1dGhlbnRpazEUMBIGA1UECwwLU2VsZi1zaWduZWQwWTATBgcqhkjO\nPQIBBggqhkjOPQMBBwNCAAQAwOGam7AKOi5LKmb9lK1rAzA2JTppqrFiIaUdjqmH\nZICJP00Wt0dfqOtEjgMEv1Hhu1DmKZn2ehvpxwPSzBr5o1UwUzBRBgNVHREBAf8E\nRzBFgkNCNkw4YlI0UldJRU42NUZLamdUTzV1YmRvNUZWdkpNS2lxdjFZeTRULnNl\nbGYtc2lnbmVkLmdvYXV0aGVudGlrLmlvMAoGCCqGSM49BAMCA0gAMEUCIC/JAfnl\nuC30ihqepbiMCaTaPMbL8Ka2Lk92IYfMhf46AiEAz9Kmv6HF2D4MK54iwhz2WqvF\n8vo+OiGdTQ1Qoj7fgYU=\n-----END CERTIFICATE-----\n'
TEST_CORDS_KEY =
'\n-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIKy6mPLJc5v71InMMvYaxyXI3xXpwQTPLyAYWVFnZHVioAoGCCqGSM49\nAwEHoUQDQgAEAMDhmpuwCjouSypm/ZStawMwNiU6aaqxYiGlHY6ph2SAiT9NFrdH\nX6jrRI4DBL9R4btQ5imZ9nob6ccD0swa+Q==\n-----END EC PRIVATE KEY-----\n'
44class TestJWKS(OAuthTestCase): 45 """Test JWKS view""" 46 47 def test_rs256(self): 48 """Test JWKS request with RS256""" 49 provider = OAuth2Provider.objects.create( 50 name="test", 51 client_id="test", 52 authorization_flow=create_test_flow(), 53 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 54 signing_key=create_test_cert(), 55 ) 56 app = Application.objects.create(name="test", slug="test", provider=provider) 57 response = self.client.get( 58 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 59 ) 60 body = json.loads(response.content.decode()) 61 self.assertEqual(len(body["keys"]), 1) 62 PyJWKSet.from_dict(body) 63 key = body["keys"][0] 64 load_der_x509_certificate(base64.b64decode(key["x5c"][0]), default_backend()).public_key() 65 66 def test_hs256(self): 67 """Test JWKS request with HS256""" 68 provider = OAuth2Provider.objects.create( 69 name="test", 70 client_id="test", 71 authorization_flow=create_test_flow(), 72 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 73 ) 74 app = Application.objects.create(name="test", slug="test", provider=provider) 75 response = self.client.get( 76 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 77 ) 78 self.assertJSONEqual(response.content.decode(), {}) 79 80 def test_es256(self): 81 """Test JWKS request with ES256""" 82 provider = OAuth2Provider.objects.create( 83 name="test", 84 client_id="test", 85 authorization_flow=create_test_flow(), 86 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 87 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 88 ) 89 app = Application.objects.create(name="test", slug="test", provider=provider) 90 response = self.client.get( 91 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 92 ) 93 body = json.loads(response.content.decode()) 94 self.assertEqual(len(body["keys"]), 1) 95 PyJWKSet.from_dict(body) 96 97 def test_enc(self): 98 """Test with JWE""" 99 provider = OAuth2Provider.objects.create( 100 name="test", 101 client_id="test", 102 authorization_flow=create_test_flow(), 103 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 104 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 105 encryption_key=create_test_cert(PrivateKeyAlg.ECDSA), 106 ) 107 app = Application.objects.create(name="test", slug="test", provider=provider) 108 response = self.client.get( 109 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 110 ) 111 body = json.loads(response.content.decode()) 112 self.assertEqual(len(body["keys"]), 2) 113 PyJWKSet.from_dict(body) 114 115 def test_ecdsa_coords_mismatched(self): 116 """Test JWKS request with ES256""" 117 cert = CertificateKeyPair.objects.create( 118 name=generate_id(), 119 key_data=TEST_CORDS_KEY, 120 certificate_data=TEST_CORDS_CERT, 121 ) 122 provider = OAuth2Provider.objects.create( 123 name="test", 124 client_id="test", 125 authorization_flow=create_test_flow(), 126 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 127 signing_key=cert, 128 ) 129 app = Application.objects.create(name="test", slug="test", provider=provider) 130 response = self.client.get( 131 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 132 ) 133 body = json.loads(response.content.decode()) 134 self.assertEqual(len(body["keys"]), 1) 135 PyJWKSet.from_dict(body)
Test JWKS view
def
test_rs256(self):
47 def test_rs256(self): 48 """Test JWKS request with RS256""" 49 provider = OAuth2Provider.objects.create( 50 name="test", 51 client_id="test", 52 authorization_flow=create_test_flow(), 53 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 54 signing_key=create_test_cert(), 55 ) 56 app = Application.objects.create(name="test", slug="test", provider=provider) 57 response = self.client.get( 58 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 59 ) 60 body = json.loads(response.content.decode()) 61 self.assertEqual(len(body["keys"]), 1) 62 PyJWKSet.from_dict(body) 63 key = body["keys"][0] 64 load_der_x509_certificate(base64.b64decode(key["x5c"][0]), default_backend()).public_key()
Test JWKS request with RS256
def
test_hs256(self):
66 def test_hs256(self): 67 """Test JWKS request with HS256""" 68 provider = OAuth2Provider.objects.create( 69 name="test", 70 client_id="test", 71 authorization_flow=create_test_flow(), 72 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 73 ) 74 app = Application.objects.create(name="test", slug="test", provider=provider) 75 response = self.client.get( 76 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 77 ) 78 self.assertJSONEqual(response.content.decode(), {})
Test JWKS request with HS256
def
test_es256(self):
80 def test_es256(self): 81 """Test JWKS request with ES256""" 82 provider = OAuth2Provider.objects.create( 83 name="test", 84 client_id="test", 85 authorization_flow=create_test_flow(), 86 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 87 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 88 ) 89 app = Application.objects.create(name="test", slug="test", provider=provider) 90 response = self.client.get( 91 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 92 ) 93 body = json.loads(response.content.decode()) 94 self.assertEqual(len(body["keys"]), 1) 95 PyJWKSet.from_dict(body)
Test JWKS request with ES256
def
test_enc(self):
97 def test_enc(self): 98 """Test with JWE""" 99 provider = OAuth2Provider.objects.create( 100 name="test", 101 client_id="test", 102 authorization_flow=create_test_flow(), 103 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 104 signing_key=create_test_cert(PrivateKeyAlg.ECDSA), 105 encryption_key=create_test_cert(PrivateKeyAlg.ECDSA), 106 ) 107 app = Application.objects.create(name="test", slug="test", provider=provider) 108 response = self.client.get( 109 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 110 ) 111 body = json.loads(response.content.decode()) 112 self.assertEqual(len(body["keys"]), 2) 113 PyJWKSet.from_dict(body)
Test with JWE
def
test_ecdsa_coords_mismatched(self):
115 def test_ecdsa_coords_mismatched(self): 116 """Test JWKS request with ES256""" 117 cert = CertificateKeyPair.objects.create( 118 name=generate_id(), 119 key_data=TEST_CORDS_KEY, 120 certificate_data=TEST_CORDS_CERT, 121 ) 122 provider = OAuth2Provider.objects.create( 123 name="test", 124 client_id="test", 125 authorization_flow=create_test_flow(), 126 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")], 127 signing_key=cert, 128 ) 129 app = Application.objects.create(name="test", slug="test", provider=provider) 130 response = self.client.get( 131 reverse("authentik_providers_oauth2:jwks", kwargs={"application_slug": app.slug}) 132 ) 133 body = json.loads(response.content.decode()) 134 self.assertEqual(len(body["keys"]), 1) 135 PyJWKSet.from_dict(body)
Test JWKS request with ES256