authentik.providers.oauth2.tests.test_token_cc_standard

Test token view

  1"""Test token view"""
  2
  3from json import loads
  4
  5from django.test import RequestFactory
  6from django.urls import reverse
  7from jwt import decode
  8
  9from authentik.blueprints.tests import apply_blueprint
 10from authentik.common.oauth.constants import (
 11    GRANT_TYPE_CLIENT_CREDENTIALS,
 12    GRANT_TYPE_PASSWORD,
 13    SCOPE_OPENID,
 14    SCOPE_OPENID_EMAIL,
 15    SCOPE_OPENID_PROFILE,
 16    TOKEN_TYPE,
 17)
 18from authentik.core.models import Application, Group, Token, TokenIntents, UserTypes
 19from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
 20from authentik.policies.models import PolicyBinding
 21from authentik.providers.oauth2.errors import TokenError
 22from authentik.providers.oauth2.models import (
 23    AccessToken,
 24    GrantType,
 25    OAuth2Provider,
 26    RedirectURI,
 27    RedirectURIMatchingMode,
 28    ScopeMapping,
 29)
 30from authentik.providers.oauth2.tests.utils import OAuthTestCase
 31
 32
 33class TestTokenClientCredentialsStandard(OAuthTestCase):
 34    """Test token (client_credentials) view"""
 35
 36    @apply_blueprint("system/providers-oauth2.yaml")
 37    def setUp(self) -> None:
 38        super().setUp()
 39        self.factory = RequestFactory()
 40        self.provider = OAuth2Provider.objects.create(
 41            name="test",
 42            authorization_flow=create_test_flow(),
 43            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
 44            signing_key=create_test_cert(),
 45            grant_types=[GrantType.CLIENT_CREDENTIALS, GrantType.PASSWORD],
 46        )
 47        self.provider.property_mappings.set(ScopeMapping.objects.all())
 48        self.app = Application.objects.create(name="test", slug="test", provider=self.provider)
 49        self.user = create_test_admin_user("sa")
 50        self.user.type = UserTypes.SERVICE_ACCOUNT
 51        self.user.save()
 52        self.token = Token.objects.create(
 53            identifier="sa-token",
 54            user=self.user,
 55            intent=TokenIntents.INTENT_APP_PASSWORD,
 56            expiring=False,
 57        )
 58
 59    def test_wrong_user(self):
 60        """test invalid username"""
 61        response = self.client.post(
 62            reverse("authentik_providers_oauth2:token"),
 63            {
 64                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
 65                "scope": SCOPE_OPENID,
 66                "client_id": self.provider.client_id,
 67                "client_secret": self.provider.client_secret + "foo",
 68            },
 69        )
 70        self.assertEqual(response.status_code, 400)
 71        self.assertJSONEqual(
 72            response.content.decode(),
 73            {
 74                "error": "invalid_grant",
 75                "error_description": TokenError.errors["invalid_grant"],
 76                "request_id": response.headers["X-authentik-id"],
 77            },
 78        )
 79
 80    def test_no_provider(self):
 81        """test no provider"""
 82        self.app.provider = None
 83        self.app.save()
 84        response = self.client.post(
 85            reverse("authentik_providers_oauth2:token"),
 86            {
 87                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
 88                "scope": SCOPE_OPENID,
 89                "client_id": self.provider.client_id,
 90                "client_secret": self.provider.client_secret,
 91            },
 92        )
 93        self.assertEqual(response.status_code, 400)
 94        self.assertJSONEqual(
 95            response.content.decode(),
 96            {
 97                "error": "invalid_grant",
 98                "error_description": TokenError.errors["invalid_grant"],
 99                "request_id": response.headers["X-authentik-id"],
100            },
101        )
102
103    def test_permission_denied(self):
104        """test permission denied"""
105        group = Group.objects.create(name="foo")
106        PolicyBinding.objects.create(
107            group=group,
108            target=self.app,
109            order=0,
110        )
111        response = self.client.post(
112            reverse("authentik_providers_oauth2:token"),
113            {
114                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
115                "scope": SCOPE_OPENID,
116                "client_id": self.provider.client_id,
117                "client_secret": self.provider.client_secret,
118            },
119        )
120        self.assertEqual(response.status_code, 400)
121        self.assertJSONEqual(
122            response.content.decode(),
123            {
124                "error": "invalid_grant",
125                "error_description": TokenError.errors["invalid_grant"],
126                "request_id": response.headers["X-authentik-id"],
127            },
128        )
129
130    def test_incorrect_scopes(self):
131        """test scope that isn't configured"""
132        response = self.client.post(
133            reverse("authentik_providers_oauth2:token"),
134            {
135                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
136                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE} extra_scope",
137                "client_id": self.provider.client_id,
138                "client_secret": self.provider.client_secret,
139            },
140        )
141        self.assertEqual(response.status_code, 200)
142        body = loads(response.content.decode())
143        self.assertEqual(body["token_type"], TOKEN_TYPE)
144        token = AccessToken.objects.filter(
145            provider=self.provider, token=body["access_token"]
146        ).first()
147        self.assertSetEqual(
148            set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE}
149        )
150        _, alg = self.provider.jwt_key
151        jwt = decode(
152            body["access_token"],
153            key=self.provider.signing_key.public_key,
154            algorithms=[alg],
155            audience=self.provider.client_id,
156        )
157        self.assertEqual(
158            jwt["given_name"], "Autogenerated user from application test (client credentials)"
159        )
160        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
161        jwt = decode(
162            body["id_token"],
163            key=self.provider.signing_key.public_key,
164            algorithms=[alg],
165            audience=self.provider.client_id,
166        )
167        self.assertEqual(
168            jwt["given_name"], "Autogenerated user from application test (client credentials)"
169        )
170        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
171
172    def test_successful(self):
173        """test successful"""
174        response = self.client.post(
175            reverse("authentik_providers_oauth2:token"),
176            {
177                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
178                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
179                "client_id": self.provider.client_id,
180                "client_secret": self.provider.client_secret,
181            },
182        )
183        self.assertEqual(response.status_code, 200)
184        body = loads(response.content.decode())
185        self.assertEqual(body["token_type"], TOKEN_TYPE)
186        _, alg = self.provider.jwt_key
187        jwt = decode(
188            body["access_token"],
189            key=self.provider.signing_key.public_key,
190            algorithms=[alg],
191            audience=self.provider.client_id,
192        )
193        self.assertEqual(
194            jwt["given_name"], "Autogenerated user from application test (client credentials)"
195        )
196        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
197        jwt = decode(
198            body["id_token"],
199            key=self.provider.signing_key.public_key,
200            algorithms=[alg],
201            audience=self.provider.client_id,
202        )
203        self.assertEqual(
204            jwt["given_name"], "Autogenerated user from application test (client credentials)"
205        )
206        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
207
208    def test_successful_password(self):
209        """test successful (password grant)"""
210        response = self.client.post(
211            reverse("authentik_providers_oauth2:token"),
212            {
213                "grant_type": GRANT_TYPE_PASSWORD,
214                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
215                "client_id": self.provider.client_id,
216                "client_secret": self.provider.client_secret,
217            },
218        )
219        self.assertEqual(response.status_code, 200)
220        body = loads(response.content.decode())
221        self.assertEqual(body["token_type"], TOKEN_TYPE)
222        _, alg = self.provider.jwt_key
223        jwt = decode(
224            body["access_token"],
225            key=self.provider.signing_key.public_key,
226            algorithms=[alg],
227            audience=self.provider.client_id,
228        )
229        self.assertEqual(
230            jwt["given_name"], "Autogenerated user from application test (client credentials)"
231        )
232        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
class TestTokenClientCredentialsStandard(authentik.providers.oauth2.tests.utils.OAuthTestCase):
 34class TestTokenClientCredentialsStandard(OAuthTestCase):
 35    """Test token (client_credentials) view"""
 36
 37    @apply_blueprint("system/providers-oauth2.yaml")
 38    def setUp(self) -> None:
 39        super().setUp()
 40        self.factory = RequestFactory()
 41        self.provider = OAuth2Provider.objects.create(
 42            name="test",
 43            authorization_flow=create_test_flow(),
 44            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
 45            signing_key=create_test_cert(),
 46            grant_types=[GrantType.CLIENT_CREDENTIALS, GrantType.PASSWORD],
 47        )
 48        self.provider.property_mappings.set(ScopeMapping.objects.all())
 49        self.app = Application.objects.create(name="test", slug="test", provider=self.provider)
 50        self.user = create_test_admin_user("sa")
 51        self.user.type = UserTypes.SERVICE_ACCOUNT
 52        self.user.save()
 53        self.token = Token.objects.create(
 54            identifier="sa-token",
 55            user=self.user,
 56            intent=TokenIntents.INTENT_APP_PASSWORD,
 57            expiring=False,
 58        )
 59
 60    def test_wrong_user(self):
 61        """test invalid username"""
 62        response = self.client.post(
 63            reverse("authentik_providers_oauth2:token"),
 64            {
 65                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
 66                "scope": SCOPE_OPENID,
 67                "client_id": self.provider.client_id,
 68                "client_secret": self.provider.client_secret + "foo",
 69            },
 70        )
 71        self.assertEqual(response.status_code, 400)
 72        self.assertJSONEqual(
 73            response.content.decode(),
 74            {
 75                "error": "invalid_grant",
 76                "error_description": TokenError.errors["invalid_grant"],
 77                "request_id": response.headers["X-authentik-id"],
 78            },
 79        )
 80
 81    def test_no_provider(self):
 82        """test no provider"""
 83        self.app.provider = None
 84        self.app.save()
 85        response = self.client.post(
 86            reverse("authentik_providers_oauth2:token"),
 87            {
 88                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
 89                "scope": SCOPE_OPENID,
 90                "client_id": self.provider.client_id,
 91                "client_secret": self.provider.client_secret,
 92            },
 93        )
 94        self.assertEqual(response.status_code, 400)
 95        self.assertJSONEqual(
 96            response.content.decode(),
 97            {
 98                "error": "invalid_grant",
 99                "error_description": TokenError.errors["invalid_grant"],
100                "request_id": response.headers["X-authentik-id"],
101            },
102        )
103
104    def test_permission_denied(self):
105        """test permission denied"""
106        group = Group.objects.create(name="foo")
107        PolicyBinding.objects.create(
108            group=group,
109            target=self.app,
110            order=0,
111        )
112        response = self.client.post(
113            reverse("authentik_providers_oauth2:token"),
114            {
115                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
116                "scope": SCOPE_OPENID,
117                "client_id": self.provider.client_id,
118                "client_secret": self.provider.client_secret,
119            },
120        )
121        self.assertEqual(response.status_code, 400)
122        self.assertJSONEqual(
123            response.content.decode(),
124            {
125                "error": "invalid_grant",
126                "error_description": TokenError.errors["invalid_grant"],
127                "request_id": response.headers["X-authentik-id"],
128            },
129        )
130
131    def test_incorrect_scopes(self):
132        """test scope that isn't configured"""
133        response = self.client.post(
134            reverse("authentik_providers_oauth2:token"),
135            {
136                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
137                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE} extra_scope",
138                "client_id": self.provider.client_id,
139                "client_secret": self.provider.client_secret,
140            },
141        )
142        self.assertEqual(response.status_code, 200)
143        body = loads(response.content.decode())
144        self.assertEqual(body["token_type"], TOKEN_TYPE)
145        token = AccessToken.objects.filter(
146            provider=self.provider, token=body["access_token"]
147        ).first()
148        self.assertSetEqual(
149            set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE}
150        )
151        _, alg = self.provider.jwt_key
152        jwt = decode(
153            body["access_token"],
154            key=self.provider.signing_key.public_key,
155            algorithms=[alg],
156            audience=self.provider.client_id,
157        )
158        self.assertEqual(
159            jwt["given_name"], "Autogenerated user from application test (client credentials)"
160        )
161        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
162        jwt = decode(
163            body["id_token"],
164            key=self.provider.signing_key.public_key,
165            algorithms=[alg],
166            audience=self.provider.client_id,
167        )
168        self.assertEqual(
169            jwt["given_name"], "Autogenerated user from application test (client credentials)"
170        )
171        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
172
173    def test_successful(self):
174        """test successful"""
175        response = self.client.post(
176            reverse("authentik_providers_oauth2:token"),
177            {
178                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
179                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
180                "client_id": self.provider.client_id,
181                "client_secret": self.provider.client_secret,
182            },
183        )
184        self.assertEqual(response.status_code, 200)
185        body = loads(response.content.decode())
186        self.assertEqual(body["token_type"], TOKEN_TYPE)
187        _, alg = self.provider.jwt_key
188        jwt = decode(
189            body["access_token"],
190            key=self.provider.signing_key.public_key,
191            algorithms=[alg],
192            audience=self.provider.client_id,
193        )
194        self.assertEqual(
195            jwt["given_name"], "Autogenerated user from application test (client credentials)"
196        )
197        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
198        jwt = decode(
199            body["id_token"],
200            key=self.provider.signing_key.public_key,
201            algorithms=[alg],
202            audience=self.provider.client_id,
203        )
204        self.assertEqual(
205            jwt["given_name"], "Autogenerated user from application test (client credentials)"
206        )
207        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
208
209    def test_successful_password(self):
210        """test successful (password grant)"""
211        response = self.client.post(
212            reverse("authentik_providers_oauth2:token"),
213            {
214                "grant_type": GRANT_TYPE_PASSWORD,
215                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
216                "client_id": self.provider.client_id,
217                "client_secret": self.provider.client_secret,
218            },
219        )
220        self.assertEqual(response.status_code, 200)
221        body = loads(response.content.decode())
222        self.assertEqual(body["token_type"], TOKEN_TYPE)
223        _, alg = self.provider.jwt_key
224        jwt = decode(
225            body["access_token"],
226            key=self.provider.signing_key.public_key,
227            algorithms=[alg],
228            audience=self.provider.client_id,
229        )
230        self.assertEqual(
231            jwt["given_name"], "Autogenerated user from application test (client credentials)"
232        )
233        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")

Test token (client_credentials) view

@apply_blueprint('system/providers-oauth2.yaml')
def setUp(self) -> None:
37    @apply_blueprint("system/providers-oauth2.yaml")
38    def setUp(self) -> None:
39        super().setUp()
40        self.factory = RequestFactory()
41        self.provider = OAuth2Provider.objects.create(
42            name="test",
43            authorization_flow=create_test_flow(),
44            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
45            signing_key=create_test_cert(),
46            grant_types=[GrantType.CLIENT_CREDENTIALS, GrantType.PASSWORD],
47        )
48        self.provider.property_mappings.set(ScopeMapping.objects.all())
49        self.app = Application.objects.create(name="test", slug="test", provider=self.provider)
50        self.user = create_test_admin_user("sa")
51        self.user.type = UserTypes.SERVICE_ACCOUNT
52        self.user.save()
53        self.token = Token.objects.create(
54            identifier="sa-token",
55            user=self.user,
56            intent=TokenIntents.INTENT_APP_PASSWORD,
57            expiring=False,
58        )

Hook method for setting up the test fixture before exercising it.

def test_wrong_user(self):
60    def test_wrong_user(self):
61        """test invalid username"""
62        response = self.client.post(
63            reverse("authentik_providers_oauth2:token"),
64            {
65                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
66                "scope": SCOPE_OPENID,
67                "client_id": self.provider.client_id,
68                "client_secret": self.provider.client_secret + "foo",
69            },
70        )
71        self.assertEqual(response.status_code, 400)
72        self.assertJSONEqual(
73            response.content.decode(),
74            {
75                "error": "invalid_grant",
76                "error_description": TokenError.errors["invalid_grant"],
77                "request_id": response.headers["X-authentik-id"],
78            },
79        )

test invalid username

def test_no_provider(self):
 81    def test_no_provider(self):
 82        """test no provider"""
 83        self.app.provider = None
 84        self.app.save()
 85        response = self.client.post(
 86            reverse("authentik_providers_oauth2:token"),
 87            {
 88                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
 89                "scope": SCOPE_OPENID,
 90                "client_id": self.provider.client_id,
 91                "client_secret": self.provider.client_secret,
 92            },
 93        )
 94        self.assertEqual(response.status_code, 400)
 95        self.assertJSONEqual(
 96            response.content.decode(),
 97            {
 98                "error": "invalid_grant",
 99                "error_description": TokenError.errors["invalid_grant"],
100                "request_id": response.headers["X-authentik-id"],
101            },
102        )

test no provider

def test_permission_denied(self):
104    def test_permission_denied(self):
105        """test permission denied"""
106        group = Group.objects.create(name="foo")
107        PolicyBinding.objects.create(
108            group=group,
109            target=self.app,
110            order=0,
111        )
112        response = self.client.post(
113            reverse("authentik_providers_oauth2:token"),
114            {
115                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
116                "scope": SCOPE_OPENID,
117                "client_id": self.provider.client_id,
118                "client_secret": self.provider.client_secret,
119            },
120        )
121        self.assertEqual(response.status_code, 400)
122        self.assertJSONEqual(
123            response.content.decode(),
124            {
125                "error": "invalid_grant",
126                "error_description": TokenError.errors["invalid_grant"],
127                "request_id": response.headers["X-authentik-id"],
128            },
129        )

test permission denied

def test_incorrect_scopes(self):
131    def test_incorrect_scopes(self):
132        """test scope that isn't configured"""
133        response = self.client.post(
134            reverse("authentik_providers_oauth2:token"),
135            {
136                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
137                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE} extra_scope",
138                "client_id": self.provider.client_id,
139                "client_secret": self.provider.client_secret,
140            },
141        )
142        self.assertEqual(response.status_code, 200)
143        body = loads(response.content.decode())
144        self.assertEqual(body["token_type"], TOKEN_TYPE)
145        token = AccessToken.objects.filter(
146            provider=self.provider, token=body["access_token"]
147        ).first()
148        self.assertSetEqual(
149            set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE}
150        )
151        _, alg = self.provider.jwt_key
152        jwt = decode(
153            body["access_token"],
154            key=self.provider.signing_key.public_key,
155            algorithms=[alg],
156            audience=self.provider.client_id,
157        )
158        self.assertEqual(
159            jwt["given_name"], "Autogenerated user from application test (client credentials)"
160        )
161        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
162        jwt = decode(
163            body["id_token"],
164            key=self.provider.signing_key.public_key,
165            algorithms=[alg],
166            audience=self.provider.client_id,
167        )
168        self.assertEqual(
169            jwt["given_name"], "Autogenerated user from application test (client credentials)"
170        )
171        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")

test scope that isn't configured

def test_successful(self):
173    def test_successful(self):
174        """test successful"""
175        response = self.client.post(
176            reverse("authentik_providers_oauth2:token"),
177            {
178                "grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
179                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
180                "client_id": self.provider.client_id,
181                "client_secret": self.provider.client_secret,
182            },
183        )
184        self.assertEqual(response.status_code, 200)
185        body = loads(response.content.decode())
186        self.assertEqual(body["token_type"], TOKEN_TYPE)
187        _, alg = self.provider.jwt_key
188        jwt = decode(
189            body["access_token"],
190            key=self.provider.signing_key.public_key,
191            algorithms=[alg],
192            audience=self.provider.client_id,
193        )
194        self.assertEqual(
195            jwt["given_name"], "Autogenerated user from application test (client credentials)"
196        )
197        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
198        jwt = decode(
199            body["id_token"],
200            key=self.provider.signing_key.public_key,
201            algorithms=[alg],
202            audience=self.provider.client_id,
203        )
204        self.assertEqual(
205            jwt["given_name"], "Autogenerated user from application test (client credentials)"
206        )
207        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")

test successful

def test_successful_password(self):
209    def test_successful_password(self):
210        """test successful (password grant)"""
211        response = self.client.post(
212            reverse("authentik_providers_oauth2:token"),
213            {
214                "grant_type": GRANT_TYPE_PASSWORD,
215                "scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE}",
216                "client_id": self.provider.client_id,
217                "client_secret": self.provider.client_secret,
218            },
219        )
220        self.assertEqual(response.status_code, 200)
221        body = loads(response.content.decode())
222        self.assertEqual(body["token_type"], TOKEN_TYPE)
223        _, alg = self.provider.jwt_key
224        jwt = decode(
225            body["access_token"],
226            key=self.provider.signing_key.public_key,
227            algorithms=[alg],
228            audience=self.provider.client_id,
229        )
230        self.assertEqual(
231            jwt["given_name"], "Autogenerated user from application test (client credentials)"
232        )
233        self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")

test successful (password grant)