authentik.providers.oauth2.tests.test_token_device
Test token view
1"""Test token view""" 2 3from json import loads 4 5from django.test import RequestFactory 6from django.urls import reverse 7 8from authentik.blueprints.tests import apply_blueprint 9from authentik.common.oauth.constants import ( 10 GRANT_TYPE_DEVICE_CODE, 11 SCOPE_OPENID, 12 SCOPE_OPENID_EMAIL, 13) 14from authentik.core.models import Application 15from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow 16from authentik.lib.generators import generate_code_fixed_length, generate_id 17from authentik.providers.oauth2.models import ( 18 AccessToken, 19 DeviceToken, 20 GrantType, 21 OAuth2Provider, 22 RedirectURI, 23 RedirectURIMatchingMode, 24 ScopeMapping, 25) 26from authentik.providers.oauth2.tests.utils import OAuthTestCase 27 28 29class TestTokenDeviceCode(OAuthTestCase): 30 """Test token (device code) view""" 31 32 @apply_blueprint("system/providers-oauth2.yaml") 33 def setUp(self) -> None: 34 super().setUp() 35 self.factory = RequestFactory() 36 self.provider = OAuth2Provider.objects.create( 37 name="test", 38 authorization_flow=create_test_flow(), 39 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")], 40 signing_key=create_test_cert(), 41 grant_types=[GrantType.DEVICE_CODE], 42 ) 43 self.provider.property_mappings.set(ScopeMapping.objects.all()) 44 self.app = Application.objects.create(name="test", slug="test", provider=self.provider) 45 self.user = create_test_admin_user() 46 47 def test_code_no_code(self): 48 """Test code without code""" 49 res = self.client.post( 50 reverse("authentik_providers_oauth2:token"), 51 data={ 52 "client_id": self.provider.client_id, 53 "client_secret": self.provider.client_secret, 54 "grant_type": GRANT_TYPE_DEVICE_CODE, 55 }, 56 ) 57 self.assertEqual(res.status_code, 400) 58 body = loads(res.content.decode()) 59 self.assertEqual(body["error"], "invalid_grant") 60 61 def test_code_no_user(self): 62 """Test code without user""" 63 device_token = DeviceToken.objects.create( 64 provider=self.provider, 65 user_code=generate_code_fixed_length(), 66 device_code=generate_id(), 67 ) 68 res = self.client.post( 69 reverse("authentik_providers_oauth2:token"), 70 data={ 71 "client_id": self.provider.client_id, 72 "client_secret": self.provider.client_secret, 73 "grant_type": GRANT_TYPE_DEVICE_CODE, 74 "device_code": device_token.device_code, 75 }, 76 ) 77 self.assertEqual(res.status_code, 400) 78 body = loads(res.content.decode()) 79 self.assertEqual(body["error"], "authorization_pending") 80 81 def test_code_no_auth(self): 82 """Test code with user""" 83 device_token = DeviceToken.objects.create( 84 provider=self.provider, 85 user_code=generate_code_fixed_length(), 86 device_code=generate_id(), 87 user=self.user, 88 ) 89 res = self.client.post( 90 reverse("authentik_providers_oauth2:token"), 91 data={ 92 "client_id": self.provider.client_id, 93 "grant_type": GRANT_TYPE_DEVICE_CODE, 94 "device_code": device_token.device_code, 95 }, 96 ) 97 self.assertEqual(res.status_code, 400) 98 body = loads(res.content.decode()) 99 self.assertEqual(body["error"], "invalid_client") 100 101 def test_code(self): 102 """Test code with user""" 103 device_token = DeviceToken.objects.create( 104 provider=self.provider, 105 user_code=generate_code_fixed_length(), 106 device_code=generate_id(), 107 user=self.user, 108 ) 109 res = self.client.post( 110 reverse("authentik_providers_oauth2:token"), 111 data={ 112 "client_id": self.provider.client_id, 113 "client_secret": self.provider.client_secret, 114 "grant_type": GRANT_TYPE_DEVICE_CODE, 115 "device_code": device_token.device_code, 116 }, 117 ) 118 self.assertEqual(res.status_code, 200) 119 120 def test_code_mismatched_scope(self): 121 """Test code with user (mismatched scopes)""" 122 device_token = DeviceToken.objects.create( 123 provider=self.provider, 124 user_code=generate_code_fixed_length(), 125 device_code=generate_id(), 126 user=self.user, 127 scope=[SCOPE_OPENID, SCOPE_OPENID_EMAIL], 128 ) 129 res = self.client.post( 130 reverse("authentik_providers_oauth2:token"), 131 data={ 132 "client_id": self.provider.client_id, 133 "client_secret": self.provider.client_secret, 134 "grant_type": GRANT_TYPE_DEVICE_CODE, 135 "device_code": device_token.device_code, 136 "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} invalid", 137 }, 138 ) 139 self.assertEqual(res.status_code, 200) 140 body = loads(res.content) 141 token = AccessToken.objects.filter( 142 provider=self.provider, token=body["access_token"] 143 ).first() 144 self.assertSetEqual(set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL})
30class TestTokenDeviceCode(OAuthTestCase): 31 """Test token (device code) view""" 32 33 @apply_blueprint("system/providers-oauth2.yaml") 34 def setUp(self) -> None: 35 super().setUp() 36 self.factory = RequestFactory() 37 self.provider = OAuth2Provider.objects.create( 38 name="test", 39 authorization_flow=create_test_flow(), 40 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")], 41 signing_key=create_test_cert(), 42 grant_types=[GrantType.DEVICE_CODE], 43 ) 44 self.provider.property_mappings.set(ScopeMapping.objects.all()) 45 self.app = Application.objects.create(name="test", slug="test", provider=self.provider) 46 self.user = create_test_admin_user() 47 48 def test_code_no_code(self): 49 """Test code without code""" 50 res = self.client.post( 51 reverse("authentik_providers_oauth2:token"), 52 data={ 53 "client_id": self.provider.client_id, 54 "client_secret": self.provider.client_secret, 55 "grant_type": GRANT_TYPE_DEVICE_CODE, 56 }, 57 ) 58 self.assertEqual(res.status_code, 400) 59 body = loads(res.content.decode()) 60 self.assertEqual(body["error"], "invalid_grant") 61 62 def test_code_no_user(self): 63 """Test code without user""" 64 device_token = DeviceToken.objects.create( 65 provider=self.provider, 66 user_code=generate_code_fixed_length(), 67 device_code=generate_id(), 68 ) 69 res = self.client.post( 70 reverse("authentik_providers_oauth2:token"), 71 data={ 72 "client_id": self.provider.client_id, 73 "client_secret": self.provider.client_secret, 74 "grant_type": GRANT_TYPE_DEVICE_CODE, 75 "device_code": device_token.device_code, 76 }, 77 ) 78 self.assertEqual(res.status_code, 400) 79 body = loads(res.content.decode()) 80 self.assertEqual(body["error"], "authorization_pending") 81 82 def test_code_no_auth(self): 83 """Test code with user""" 84 device_token = DeviceToken.objects.create( 85 provider=self.provider, 86 user_code=generate_code_fixed_length(), 87 device_code=generate_id(), 88 user=self.user, 89 ) 90 res = self.client.post( 91 reverse("authentik_providers_oauth2:token"), 92 data={ 93 "client_id": self.provider.client_id, 94 "grant_type": GRANT_TYPE_DEVICE_CODE, 95 "device_code": device_token.device_code, 96 }, 97 ) 98 self.assertEqual(res.status_code, 400) 99 body = loads(res.content.decode()) 100 self.assertEqual(body["error"], "invalid_client") 101 102 def test_code(self): 103 """Test code with user""" 104 device_token = DeviceToken.objects.create( 105 provider=self.provider, 106 user_code=generate_code_fixed_length(), 107 device_code=generate_id(), 108 user=self.user, 109 ) 110 res = self.client.post( 111 reverse("authentik_providers_oauth2:token"), 112 data={ 113 "client_id": self.provider.client_id, 114 "client_secret": self.provider.client_secret, 115 "grant_type": GRANT_TYPE_DEVICE_CODE, 116 "device_code": device_token.device_code, 117 }, 118 ) 119 self.assertEqual(res.status_code, 200) 120 121 def test_code_mismatched_scope(self): 122 """Test code with user (mismatched scopes)""" 123 device_token = DeviceToken.objects.create( 124 provider=self.provider, 125 user_code=generate_code_fixed_length(), 126 device_code=generate_id(), 127 user=self.user, 128 scope=[SCOPE_OPENID, SCOPE_OPENID_EMAIL], 129 ) 130 res = self.client.post( 131 reverse("authentik_providers_oauth2:token"), 132 data={ 133 "client_id": self.provider.client_id, 134 "client_secret": self.provider.client_secret, 135 "grant_type": GRANT_TYPE_DEVICE_CODE, 136 "device_code": device_token.device_code, 137 "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} invalid", 138 }, 139 ) 140 self.assertEqual(res.status_code, 200) 141 body = loads(res.content) 142 token = AccessToken.objects.filter( 143 provider=self.provider, token=body["access_token"] 144 ).first() 145 self.assertSetEqual(set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL})
Test token (device code) view
@apply_blueprint('system/providers-oauth2.yaml')
def
setUp(self) -> None:
33 @apply_blueprint("system/providers-oauth2.yaml") 34 def setUp(self) -> None: 35 super().setUp() 36 self.factory = RequestFactory() 37 self.provider = OAuth2Provider.objects.create( 38 name="test", 39 authorization_flow=create_test_flow(), 40 redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")], 41 signing_key=create_test_cert(), 42 grant_types=[GrantType.DEVICE_CODE], 43 ) 44 self.provider.property_mappings.set(ScopeMapping.objects.all()) 45 self.app = Application.objects.create(name="test", slug="test", provider=self.provider) 46 self.user = create_test_admin_user()
Hook method for setting up the test fixture before exercising it.
def
test_code_no_code(self):
48 def test_code_no_code(self): 49 """Test code without code""" 50 res = self.client.post( 51 reverse("authentik_providers_oauth2:token"), 52 data={ 53 "client_id": self.provider.client_id, 54 "client_secret": self.provider.client_secret, 55 "grant_type": GRANT_TYPE_DEVICE_CODE, 56 }, 57 ) 58 self.assertEqual(res.status_code, 400) 59 body = loads(res.content.decode()) 60 self.assertEqual(body["error"], "invalid_grant")
Test code without code
def
test_code_no_user(self):
62 def test_code_no_user(self): 63 """Test code without user""" 64 device_token = DeviceToken.objects.create( 65 provider=self.provider, 66 user_code=generate_code_fixed_length(), 67 device_code=generate_id(), 68 ) 69 res = self.client.post( 70 reverse("authentik_providers_oauth2:token"), 71 data={ 72 "client_id": self.provider.client_id, 73 "client_secret": self.provider.client_secret, 74 "grant_type": GRANT_TYPE_DEVICE_CODE, 75 "device_code": device_token.device_code, 76 }, 77 ) 78 self.assertEqual(res.status_code, 400) 79 body = loads(res.content.decode()) 80 self.assertEqual(body["error"], "authorization_pending")
Test code without user
def
test_code_no_auth(self):
82 def test_code_no_auth(self): 83 """Test code with user""" 84 device_token = DeviceToken.objects.create( 85 provider=self.provider, 86 user_code=generate_code_fixed_length(), 87 device_code=generate_id(), 88 user=self.user, 89 ) 90 res = self.client.post( 91 reverse("authentik_providers_oauth2:token"), 92 data={ 93 "client_id": self.provider.client_id, 94 "grant_type": GRANT_TYPE_DEVICE_CODE, 95 "device_code": device_token.device_code, 96 }, 97 ) 98 self.assertEqual(res.status_code, 400) 99 body = loads(res.content.decode()) 100 self.assertEqual(body["error"], "invalid_client")
Test code with user
def
test_code(self):
102 def test_code(self): 103 """Test code with user""" 104 device_token = DeviceToken.objects.create( 105 provider=self.provider, 106 user_code=generate_code_fixed_length(), 107 device_code=generate_id(), 108 user=self.user, 109 ) 110 res = self.client.post( 111 reverse("authentik_providers_oauth2:token"), 112 data={ 113 "client_id": self.provider.client_id, 114 "client_secret": self.provider.client_secret, 115 "grant_type": GRANT_TYPE_DEVICE_CODE, 116 "device_code": device_token.device_code, 117 }, 118 ) 119 self.assertEqual(res.status_code, 200)
Test code with user
def
test_code_mismatched_scope(self):
121 def test_code_mismatched_scope(self): 122 """Test code with user (mismatched scopes)""" 123 device_token = DeviceToken.objects.create( 124 provider=self.provider, 125 user_code=generate_code_fixed_length(), 126 device_code=generate_id(), 127 user=self.user, 128 scope=[SCOPE_OPENID, SCOPE_OPENID_EMAIL], 129 ) 130 res = self.client.post( 131 reverse("authentik_providers_oauth2:token"), 132 data={ 133 "client_id": self.provider.client_id, 134 "client_secret": self.provider.client_secret, 135 "grant_type": GRANT_TYPE_DEVICE_CODE, 136 "device_code": device_token.device_code, 137 "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} invalid", 138 }, 139 ) 140 self.assertEqual(res.status_code, 200) 141 body = loads(res.content) 142 token = AccessToken.objects.filter( 143 provider=self.provider, token=body["access_token"] 144 ).first() 145 self.assertSetEqual(set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL})
Test code with user (mismatched scopes)