authentik.enterprise.endpoints.connectors.agent.tests.test_apple_token
1from cryptography.hazmat.primitives import serialization 2from cryptography.hazmat.primitives.asymmetric import ec 3from django.test import TestCase 4from django.urls import reverse 5from jwt import encode 6 7from authentik.blueprints.tests import reconcile_app 8from authentik.core.tests.utils import create_test_cert, create_test_user 9from authentik.crypto.builder import PrivateKeyAlg 10from authentik.endpoints.connectors.agent.models import ( 11 AgentConnector, 12 AgentDeviceConnection, 13 AgentDeviceUserBinding, 14 AppleIndependentSecureEnclave, 15 AppleNonce, 16 DeviceToken, 17 EnrollmentToken, 18) 19from authentik.endpoints.models import Device 20from authentik.events.models import Event, EventAction 21from authentik.lib.generators import generate_id 22from authentik.providers.oauth2.models import JWTAlgorithms 23 24 25class TestAppleToken(TestCase): 26 27 def setUp(self): 28 self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA) 29 self.sign_key_pem = self.apple_sign_key.public_key.public_bytes( 30 encoding=serialization.Encoding.PEM, 31 format=serialization.PublicFormat.SubjectPublicKeyInfo, 32 ).decode() 33 34 self.enc_key = ec.generate_private_key(curve=ec.SECP256R1()) 35 self.enc_pub = ( 36 self.enc_key.public_key() 37 .public_bytes( 38 encoding=serialization.Encoding.PEM, 39 format=serialization.PublicFormat.SubjectPublicKeyInfo, 40 ) 41 .decode() 42 ) 43 44 self.connector = AgentConnector.objects.create(name=generate_id()) 45 self.token = EnrollmentToken.objects.create(name=generate_id(), connector=self.connector) 46 self.device = Device.objects.create( 47 name=generate_id(), 48 identifier=generate_id(), 49 ) 50 self.connection = AgentDeviceConnection.objects.create( 51 device=self.device, 52 connector=self.connector, 53 apple_sign_key_id=self.apple_sign_key.kid, 54 apple_signing_key=self.sign_key_pem, 55 apple_encryption_key=self.enc_pub, 56 ) 57 self.user = create_test_user() 58 AgentDeviceUserBinding.objects.create( 59 target=self.device, 60 user=self.user, 61 order=0, 62 apple_enclave_key_id=self.apple_sign_key.kid, 63 apple_secure_enclave_key=self.sign_key_pem, 64 ) 65 self.device_token = DeviceToken.objects.create(device=self.connection) 66 67 @reconcile_app("authentik_crypto") 68 def test_token(self): 69 nonce = generate_id() 70 AppleNonce.objects.create( 71 device_token=self.device_token, 72 nonce=nonce, 73 ) 74 embedded = encode( 75 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 76 self.apple_sign_key.private_key, 77 headers={ 78 "kid": self.apple_sign_key.kid, 79 }, 80 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 81 ) 82 assertion = encode( 83 { 84 "iss": str(self.connector.pk), 85 "aud": "http://testserver/endpoints/agent/psso/token/", 86 "request_nonce": nonce, 87 "assertion": embedded, 88 "jwe_crypto": { 89 "apv": ( 90 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 91 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 92 ) 93 }, 94 }, 95 self.apple_sign_key.private_key, 96 headers={ 97 "kid": self.apple_sign_key.kid, 98 }, 99 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 100 ) 101 res = self.client.post( 102 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 103 data={ 104 "assertion": assertion, 105 "platform_sso_version": "1.0", 106 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 107 }, 108 ) 109 110 self.assertEqual(res.status_code, 200) 111 event = Event.objects.filter( 112 action=EventAction.LOGIN, 113 app="authentik.endpoints.connectors.agent", 114 ).first() 115 self.assertIsNotNone(event) 116 self.assertEqual(event.context["device"]["name"], self.device.name) 117 118 @reconcile_app("authentik_crypto") 119 def test_token_independent(self): 120 nonce = generate_id() 121 122 AgentDeviceUserBinding.objects.all().delete() 123 AppleIndependentSecureEnclave.objects.create( 124 user=self.user, 125 apple_enclave_key_id=self.apple_sign_key.kid, 126 apple_secure_enclave_key=self.sign_key_pem, 127 ) 128 129 AppleNonce.objects.create( 130 device_token=self.device_token, 131 nonce=nonce, 132 ) 133 embedded = encode( 134 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 135 self.apple_sign_key.private_key, 136 headers={ 137 "kid": self.apple_sign_key.kid, 138 }, 139 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 140 ) 141 assertion = encode( 142 { 143 "iss": str(self.connector.pk), 144 "aud": "http://testserver/endpoints/agent/psso/token/", 145 "request_nonce": nonce, 146 "assertion": embedded, 147 "jwe_crypto": { 148 "apv": ( 149 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 150 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 151 ) 152 }, 153 }, 154 self.apple_sign_key.private_key, 155 headers={ 156 "kid": self.apple_sign_key.kid, 157 }, 158 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 159 ) 160 res = self.client.post( 161 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 162 data={ 163 "assertion": assertion, 164 "platform_sso_version": "1.0", 165 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 166 }, 167 ) 168 169 self.assertEqual(res.status_code, 200) 170 event = Event.objects.filter( 171 action=EventAction.LOGIN, 172 app="authentik.endpoints.connectors.agent", 173 ).first() 174 self.assertIsNotNone(event) 175 self.assertEqual(event.context["device"]["name"], self.device.name)
class
TestAppleToken(django.test.testcases.TestCase):
26class TestAppleToken(TestCase): 27 28 def setUp(self): 29 self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA) 30 self.sign_key_pem = self.apple_sign_key.public_key.public_bytes( 31 encoding=serialization.Encoding.PEM, 32 format=serialization.PublicFormat.SubjectPublicKeyInfo, 33 ).decode() 34 35 self.enc_key = ec.generate_private_key(curve=ec.SECP256R1()) 36 self.enc_pub = ( 37 self.enc_key.public_key() 38 .public_bytes( 39 encoding=serialization.Encoding.PEM, 40 format=serialization.PublicFormat.SubjectPublicKeyInfo, 41 ) 42 .decode() 43 ) 44 45 self.connector = AgentConnector.objects.create(name=generate_id()) 46 self.token = EnrollmentToken.objects.create(name=generate_id(), connector=self.connector) 47 self.device = Device.objects.create( 48 name=generate_id(), 49 identifier=generate_id(), 50 ) 51 self.connection = AgentDeviceConnection.objects.create( 52 device=self.device, 53 connector=self.connector, 54 apple_sign_key_id=self.apple_sign_key.kid, 55 apple_signing_key=self.sign_key_pem, 56 apple_encryption_key=self.enc_pub, 57 ) 58 self.user = create_test_user() 59 AgentDeviceUserBinding.objects.create( 60 target=self.device, 61 user=self.user, 62 order=0, 63 apple_enclave_key_id=self.apple_sign_key.kid, 64 apple_secure_enclave_key=self.sign_key_pem, 65 ) 66 self.device_token = DeviceToken.objects.create(device=self.connection) 67 68 @reconcile_app("authentik_crypto") 69 def test_token(self): 70 nonce = generate_id() 71 AppleNonce.objects.create( 72 device_token=self.device_token, 73 nonce=nonce, 74 ) 75 embedded = encode( 76 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 77 self.apple_sign_key.private_key, 78 headers={ 79 "kid": self.apple_sign_key.kid, 80 }, 81 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 82 ) 83 assertion = encode( 84 { 85 "iss": str(self.connector.pk), 86 "aud": "http://testserver/endpoints/agent/psso/token/", 87 "request_nonce": nonce, 88 "assertion": embedded, 89 "jwe_crypto": { 90 "apv": ( 91 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 92 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 93 ) 94 }, 95 }, 96 self.apple_sign_key.private_key, 97 headers={ 98 "kid": self.apple_sign_key.kid, 99 }, 100 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 101 ) 102 res = self.client.post( 103 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 104 data={ 105 "assertion": assertion, 106 "platform_sso_version": "1.0", 107 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 108 }, 109 ) 110 111 self.assertEqual(res.status_code, 200) 112 event = Event.objects.filter( 113 action=EventAction.LOGIN, 114 app="authentik.endpoints.connectors.agent", 115 ).first() 116 self.assertIsNotNone(event) 117 self.assertEqual(event.context["device"]["name"], self.device.name) 118 119 @reconcile_app("authentik_crypto") 120 def test_token_independent(self): 121 nonce = generate_id() 122 123 AgentDeviceUserBinding.objects.all().delete() 124 AppleIndependentSecureEnclave.objects.create( 125 user=self.user, 126 apple_enclave_key_id=self.apple_sign_key.kid, 127 apple_secure_enclave_key=self.sign_key_pem, 128 ) 129 130 AppleNonce.objects.create( 131 device_token=self.device_token, 132 nonce=nonce, 133 ) 134 embedded = encode( 135 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 136 self.apple_sign_key.private_key, 137 headers={ 138 "kid": self.apple_sign_key.kid, 139 }, 140 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 141 ) 142 assertion = encode( 143 { 144 "iss": str(self.connector.pk), 145 "aud": "http://testserver/endpoints/agent/psso/token/", 146 "request_nonce": nonce, 147 "assertion": embedded, 148 "jwe_crypto": { 149 "apv": ( 150 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 151 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 152 ) 153 }, 154 }, 155 self.apple_sign_key.private_key, 156 headers={ 157 "kid": self.apple_sign_key.kid, 158 }, 159 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 160 ) 161 res = self.client.post( 162 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 163 data={ 164 "assertion": assertion, 165 "platform_sso_version": "1.0", 166 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 167 }, 168 ) 169 170 self.assertEqual(res.status_code, 200) 171 event = Event.objects.filter( 172 action=EventAction.LOGIN, 173 app="authentik.endpoints.connectors.agent", 174 ).first() 175 self.assertIsNotNone(event) 176 self.assertEqual(event.context["device"]["name"], self.device.name)
Similar to TransactionTestCase, but use transaction.atomic() to achieve
test isolation.
In most situations, TestCase should be preferred to TransactionTestCase as it allows faster execution. However, there are some situations where using TransactionTestCase might be necessary (e.g. testing some transactional behavior).
On database backends with no transaction support, TestCase behaves as TransactionTestCase.
def
setUp(self):
28 def setUp(self): 29 self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA) 30 self.sign_key_pem = self.apple_sign_key.public_key.public_bytes( 31 encoding=serialization.Encoding.PEM, 32 format=serialization.PublicFormat.SubjectPublicKeyInfo, 33 ).decode() 34 35 self.enc_key = ec.generate_private_key(curve=ec.SECP256R1()) 36 self.enc_pub = ( 37 self.enc_key.public_key() 38 .public_bytes( 39 encoding=serialization.Encoding.PEM, 40 format=serialization.PublicFormat.SubjectPublicKeyInfo, 41 ) 42 .decode() 43 ) 44 45 self.connector = AgentConnector.objects.create(name=generate_id()) 46 self.token = EnrollmentToken.objects.create(name=generate_id(), connector=self.connector) 47 self.device = Device.objects.create( 48 name=generate_id(), 49 identifier=generate_id(), 50 ) 51 self.connection = AgentDeviceConnection.objects.create( 52 device=self.device, 53 connector=self.connector, 54 apple_sign_key_id=self.apple_sign_key.kid, 55 apple_signing_key=self.sign_key_pem, 56 apple_encryption_key=self.enc_pub, 57 ) 58 self.user = create_test_user() 59 AgentDeviceUserBinding.objects.create( 60 target=self.device, 61 user=self.user, 62 order=0, 63 apple_enclave_key_id=self.apple_sign_key.kid, 64 apple_secure_enclave_key=self.sign_key_pem, 65 ) 66 self.device_token = DeviceToken.objects.create(device=self.connection)
Hook method for setting up the test fixture before exercising it.
@reconcile_app('authentik_crypto')
def
test_token(self):
68 @reconcile_app("authentik_crypto") 69 def test_token(self): 70 nonce = generate_id() 71 AppleNonce.objects.create( 72 device_token=self.device_token, 73 nonce=nonce, 74 ) 75 embedded = encode( 76 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 77 self.apple_sign_key.private_key, 78 headers={ 79 "kid": self.apple_sign_key.kid, 80 }, 81 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 82 ) 83 assertion = encode( 84 { 85 "iss": str(self.connector.pk), 86 "aud": "http://testserver/endpoints/agent/psso/token/", 87 "request_nonce": nonce, 88 "assertion": embedded, 89 "jwe_crypto": { 90 "apv": ( 91 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 92 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 93 ) 94 }, 95 }, 96 self.apple_sign_key.private_key, 97 headers={ 98 "kid": self.apple_sign_key.kid, 99 }, 100 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 101 ) 102 res = self.client.post( 103 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 104 data={ 105 "assertion": assertion, 106 "platform_sso_version": "1.0", 107 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 108 }, 109 ) 110 111 self.assertEqual(res.status_code, 200) 112 event = Event.objects.filter( 113 action=EventAction.LOGIN, 114 app="authentik.endpoints.connectors.agent", 115 ).first() 116 self.assertIsNotNone(event) 117 self.assertEqual(event.context["device"]["name"], self.device.name)
@reconcile_app('authentik_crypto')
def
test_token_independent(self):
119 @reconcile_app("authentik_crypto") 120 def test_token_independent(self): 121 nonce = generate_id() 122 123 AgentDeviceUserBinding.objects.all().delete() 124 AppleIndependentSecureEnclave.objects.create( 125 user=self.user, 126 apple_enclave_key_id=self.apple_sign_key.kid, 127 apple_secure_enclave_key=self.sign_key_pem, 128 ) 129 130 AppleNonce.objects.create( 131 device_token=self.device_token, 132 nonce=nonce, 133 ) 134 embedded = encode( 135 {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce}, 136 self.apple_sign_key.private_key, 137 headers={ 138 "kid": self.apple_sign_key.kid, 139 }, 140 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 141 ) 142 assertion = encode( 143 { 144 "iss": str(self.connector.pk), 145 "aud": "http://testserver/endpoints/agent/psso/token/", 146 "request_nonce": nonce, 147 "assertion": embedded, 148 "jwe_crypto": { 149 "apv": ( 150 "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE" 151 "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw" 152 ) 153 }, 154 }, 155 self.apple_sign_key.private_key, 156 headers={ 157 "kid": self.apple_sign_key.kid, 158 }, 159 algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key), 160 ) 161 res = self.client.post( 162 reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"), 163 data={ 164 "assertion": assertion, 165 "platform_sso_version": "1.0", 166 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", 167 }, 168 ) 169 170 self.assertEqual(res.status_code, 200) 171 event = Event.objects.filter( 172 action=EventAction.LOGIN, 173 app="authentik.endpoints.connectors.agent", 174 ).first() 175 self.assertIsNotNone(event) 176 self.assertEqual(event.context["device"]["name"], self.device.name)