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    AppleNonce,
 15    DeviceToken,
 16    EnrollmentToken,
 17)
 18from authentik.endpoints.models import Device
 19from authentik.events.models import Event, EventAction
 20from authentik.lib.generators import generate_id
 21from authentik.providers.oauth2.models import JWTAlgorithms
 22
 23
 24class TestAppleToken(TestCase):
 25
 26    def setUp(self):
 27        self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA)
 28        sign_key_pem = self.apple_sign_key.public_key.public_bytes(
 29            encoding=serialization.Encoding.PEM,
 30            format=serialization.PublicFormat.SubjectPublicKeyInfo,
 31        ).decode()
 32
 33        self.enc_key = ec.generate_private_key(curve=ec.SECP256R1())
 34        self.enc_pub = (
 35            self.enc_key.public_key()
 36            .public_bytes(
 37                encoding=serialization.Encoding.PEM,
 38                format=serialization.PublicFormat.SubjectPublicKeyInfo,
 39            )
 40            .decode()
 41        )
 42
 43        self.connector = AgentConnector.objects.create(name=generate_id())
 44        self.token = EnrollmentToken.objects.create(name=generate_id(), connector=self.connector)
 45        self.device = Device.objects.create(
 46            name=generate_id(),
 47            identifier=generate_id(),
 48        )
 49        self.connection = AgentDeviceConnection.objects.create(
 50            device=self.device,
 51            connector=self.connector,
 52            apple_sign_key_id=self.apple_sign_key.kid,
 53            apple_signing_key=sign_key_pem,
 54            apple_encryption_key=self.enc_pub,
 55        )
 56        self.user = create_test_user()
 57        AgentDeviceUserBinding.objects.create(
 58            target=self.device,
 59            user=self.user,
 60            order=0,
 61            apple_enclave_key_id=self.apple_sign_key.kid,
 62            apple_secure_enclave_key=sign_key_pem,
 63        )
 64        self.device_token = DeviceToken.objects.create(device=self.connection)
 65
 66    @reconcile_app("authentik_crypto")
 67    def test_token(self):
 68        nonce = generate_id()
 69        AppleNonce.objects.create(
 70            device_token=self.device_token,
 71            nonce=nonce,
 72        )
 73        embedded = encode(
 74            {"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce},
 75            self.apple_sign_key.private_key,
 76            headers={
 77                "kid": self.apple_sign_key.kid,
 78            },
 79            algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key),
 80        )
 81        assertion = encode(
 82            {
 83                "iss": str(self.connector.pk),
 84                "aud": "http://testserver/endpoints/agent/psso/token/",
 85                "request_nonce": nonce,
 86                "assertion": embedded,
 87                "jwe_crypto": {
 88                    "apv": (
 89                        "AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE"
 90                        "aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw"
 91                    )
 92                },
 93            },
 94            self.apple_sign_key.private_key,
 95            headers={
 96                "kid": self.apple_sign_key.kid,
 97            },
 98            algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key),
 99        )
100        res = self.client.post(
101            reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"),
102            data={
103                "assertion": assertion,
104                "platform_sso_version": "1.0",
105                "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
106            },
107        )
108
109        self.assertEqual(res.status_code, 200)
110        event = Event.objects.filter(
111            action=EventAction.LOGIN,
112            app="authentik.endpoints.connectors.agent",
113        ).first()
114        self.assertIsNotNone(event)
115        self.assertEqual(event.context["device"]["name"], self.device.name)
class TestAppleToken(django.test.testcases.TestCase):
 25class TestAppleToken(TestCase):
 26
 27    def setUp(self):
 28        self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA)
 29        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=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=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)

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):
27    def setUp(self):
28        self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA)
29        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=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=sign_key_pem,
64        )
65        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):
 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)