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

Test token (client_credentials) view

@apply_blueprint('system/providers-oauth2.yaml')
def setUp(self) -> None:
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        )
46        self.provider.property_mappings.set(ScopeMapping.objects.all())
47        self.app = Application.objects.create(name="test", slug="test", provider=self.provider)
48        self.user = create_test_admin_user("sa")
49        self.user.type = UserTypes.SERVICE_ACCOUNT
50        self.user.save()
51        self.token = Token.objects.create(
52            identifier="sa-token",
53            user=self.user,
54            intent=TokenIntents.INTENT_APP_PASSWORD,
55            expiring=False,
56        )

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

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

test invalid username

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

test no provider

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

test permission denied

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

test scope that isn't configured

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

test successful

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

test successful (password grant)