authentik.providers.oauth2.tests.test_revoke

Test revoke view

  1"""Test revoke view"""
  2
  3import json
  4from base64 import b64encode
  5from dataclasses import asdict
  6
  7from django.urls import reverse
  8from django.utils import timezone
  9
 10from authentik.core.models import Application, AuthenticatedSession, Session
 11from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
 12from authentik.lib.generators import generate_id
 13from authentik.providers.oauth2.id_token import IDToken
 14from authentik.providers.oauth2.models import (
 15    AccessToken,
 16    ClientTypes,
 17    DeviceToken,
 18    OAuth2Provider,
 19    RedirectURI,
 20    RedirectURIMatchingMode,
 21    RefreshToken,
 22)
 23from authentik.providers.oauth2.tests.utils import OAuthTestCase
 24from authentik.root.middleware import ClientIPMiddleware
 25
 26
 27class TesOAuth2Revoke(OAuthTestCase):
 28    """Test revoke view"""
 29
 30    def setUp(self) -> None:
 31        super().setUp()
 32        self.provider: OAuth2Provider = OAuth2Provider.objects.create(
 33            name=generate_id(),
 34            authorization_flow=create_test_flow(),
 35            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
 36            signing_key=create_test_cert(),
 37        )
 38        self.app = Application.objects.create(
 39            name=generate_id(), slug=generate_id(), provider=self.provider
 40        )
 41        self.app.save()
 42        self.user = create_test_admin_user()
 43        self.auth = b64encode(
 44            f"{self.provider.client_id}:{self.provider.client_secret}".encode()
 45        ).decode()
 46
 47    def test_revoke_refresh(self):
 48        """Test revoke"""
 49        token: RefreshToken = RefreshToken.objects.create(
 50            provider=self.provider,
 51            user=self.user,
 52            token=generate_id(),
 53            auth_time=timezone.now(),
 54            _scope="openid user profile",
 55            _id_token=json.dumps(
 56                asdict(
 57                    IDToken("foo", "bar"),
 58                )
 59            ),
 60        )
 61        res = self.client.post(
 62            reverse("authentik_providers_oauth2:token-revoke"),
 63            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 64            data={
 65                "token": token.token,
 66            },
 67        )
 68        self.assertEqual(res.status_code, 200)
 69
 70    def test_revoke_access(self):
 71        """Test revoke"""
 72        token: AccessToken = AccessToken.objects.create(
 73            provider=self.provider,
 74            user=self.user,
 75            token=generate_id(),
 76            auth_time=timezone.now(),
 77            _scope="openid user profile",
 78            _id_token=json.dumps(
 79                asdict(
 80                    IDToken("foo", "bar"),
 81                )
 82            ),
 83        )
 84        res = self.client.post(
 85            reverse("authentik_providers_oauth2:token-revoke"),
 86            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 87            data={
 88                "token": token.token,
 89            },
 90        )
 91        self.assertEqual(res.status_code, 200)
 92
 93    def test_revoke_invalid(self):
 94        """Test revoke (invalid token)"""
 95        res = self.client.post(
 96            reverse("authentik_providers_oauth2:token-revoke"),
 97            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 98            data={
 99                "token": generate_id(),
100            },
101        )
102        self.assertEqual(res.status_code, 200)
103
104    def test_revoke_invalid_auth(self):
105        """Test revoke (invalid auth)"""
106        res = self.client.post(
107            reverse("authentik_providers_oauth2:token-revoke"),
108            HTTP_AUTHORIZATION="Basic fqewr",
109            data={
110                "token": generate_id(),
111            },
112        )
113        self.assertEqual(res.status_code, 401)
114
115    def test_revoke_public(self):
116        """Test revoke public client"""
117        self.provider.client_type = ClientTypes.PUBLIC
118        self.provider.save()
119        token: AccessToken = AccessToken.objects.create(
120            provider=self.provider,
121            user=self.user,
122            token=generate_id(),
123            auth_time=timezone.now(),
124            _scope="openid user profile",
125            _id_token=json.dumps(
126                asdict(
127                    IDToken("foo", "bar"),
128                )
129            ),
130        )
131        auth_public = b64encode(f"{self.provider.client_id}:{generate_id()}".encode()).decode()
132        res = self.client.post(
133            reverse("authentik_providers_oauth2:token-revoke"),
134            HTTP_AUTHORIZATION=f"Basic {auth_public}",
135            data={
136                "token": token.token,
137            },
138        )
139        self.assertEqual(res.status_code, 200)
140
141    def test_revoke_logout(self):
142        """Test revoke on logout"""
143        self.client.force_login(self.user)
144        AccessToken.objects.create(
145            provider=self.provider,
146            user=self.user,
147            session=self.client.session["authenticatedsession"],
148            token=generate_id(),
149            auth_time=timezone.now(),
150            _scope="openid user profile",
151            _id_token=json.dumps(
152                asdict(
153                    IDToken("foo", "bar"),
154                )
155            ),
156        )
157        self.client.logout()
158        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
159
160    def test_revoke_session_delete(self):
161        """Test revoke on logout"""
162        session = AuthenticatedSession.objects.create(
163            session=Session.objects.create(
164                session_key=generate_id(),
165                last_ip=ClientIPMiddleware.default_ip,
166            ),
167            user=self.user,
168        )
169        AccessToken.objects.create(
170            provider=self.provider,
171            user=self.user,
172            session=session,
173            token=generate_id(),
174            auth_time=timezone.now(),
175            _scope="openid user profile",
176            _id_token=json.dumps(
177                asdict(
178                    IDToken("foo", "bar"),
179                )
180            ),
181        )
182        session.delete()
183        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
184
185    def test_revoke_user_deactivated(self):
186        """Test revoke on logout"""
187        AccessToken.objects.create(
188            provider=self.provider,
189            user=self.user,
190            token=generate_id(),
191            auth_time=timezone.now(),
192            _scope="openid user profile",
193            _id_token=json.dumps(
194                asdict(
195                    IDToken("foo", "bar"),
196                )
197            ),
198        )
199        RefreshToken.objects.create(
200            provider=self.provider,
201            user=self.user,
202            token=generate_id(),
203            auth_time=timezone.now(),
204            _scope="openid user profile",
205            _id_token=json.dumps(
206                asdict(
207                    IDToken("foo", "bar"),
208                )
209            ),
210        )
211        DeviceToken.objects.create(
212            provider=self.provider,
213            user=self.user,
214            _scope="openid user profile",
215        )
216
217        self.user.is_active = False
218        self.user.save()
219
220        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
221        self.assertEqual(RefreshToken.objects.including_expired().all().count(), 0)
222        self.assertEqual(DeviceToken.objects.including_expired().all().count(), 0)
class TesOAuth2Revoke(authentik.providers.oauth2.tests.utils.OAuthTestCase):
 28class TesOAuth2Revoke(OAuthTestCase):
 29    """Test revoke view"""
 30
 31    def setUp(self) -> None:
 32        super().setUp()
 33        self.provider: OAuth2Provider = OAuth2Provider.objects.create(
 34            name=generate_id(),
 35            authorization_flow=create_test_flow(),
 36            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
 37            signing_key=create_test_cert(),
 38        )
 39        self.app = Application.objects.create(
 40            name=generate_id(), slug=generate_id(), provider=self.provider
 41        )
 42        self.app.save()
 43        self.user = create_test_admin_user()
 44        self.auth = b64encode(
 45            f"{self.provider.client_id}:{self.provider.client_secret}".encode()
 46        ).decode()
 47
 48    def test_revoke_refresh(self):
 49        """Test revoke"""
 50        token: RefreshToken = RefreshToken.objects.create(
 51            provider=self.provider,
 52            user=self.user,
 53            token=generate_id(),
 54            auth_time=timezone.now(),
 55            _scope="openid user profile",
 56            _id_token=json.dumps(
 57                asdict(
 58                    IDToken("foo", "bar"),
 59                )
 60            ),
 61        )
 62        res = self.client.post(
 63            reverse("authentik_providers_oauth2:token-revoke"),
 64            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 65            data={
 66                "token": token.token,
 67            },
 68        )
 69        self.assertEqual(res.status_code, 200)
 70
 71    def test_revoke_access(self):
 72        """Test revoke"""
 73        token: AccessToken = AccessToken.objects.create(
 74            provider=self.provider,
 75            user=self.user,
 76            token=generate_id(),
 77            auth_time=timezone.now(),
 78            _scope="openid user profile",
 79            _id_token=json.dumps(
 80                asdict(
 81                    IDToken("foo", "bar"),
 82                )
 83            ),
 84        )
 85        res = self.client.post(
 86            reverse("authentik_providers_oauth2:token-revoke"),
 87            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 88            data={
 89                "token": token.token,
 90            },
 91        )
 92        self.assertEqual(res.status_code, 200)
 93
 94    def test_revoke_invalid(self):
 95        """Test revoke (invalid token)"""
 96        res = self.client.post(
 97            reverse("authentik_providers_oauth2:token-revoke"),
 98            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 99            data={
100                "token": generate_id(),
101            },
102        )
103        self.assertEqual(res.status_code, 200)
104
105    def test_revoke_invalid_auth(self):
106        """Test revoke (invalid auth)"""
107        res = self.client.post(
108            reverse("authentik_providers_oauth2:token-revoke"),
109            HTTP_AUTHORIZATION="Basic fqewr",
110            data={
111                "token": generate_id(),
112            },
113        )
114        self.assertEqual(res.status_code, 401)
115
116    def test_revoke_public(self):
117        """Test revoke public client"""
118        self.provider.client_type = ClientTypes.PUBLIC
119        self.provider.save()
120        token: AccessToken = AccessToken.objects.create(
121            provider=self.provider,
122            user=self.user,
123            token=generate_id(),
124            auth_time=timezone.now(),
125            _scope="openid user profile",
126            _id_token=json.dumps(
127                asdict(
128                    IDToken("foo", "bar"),
129                )
130            ),
131        )
132        auth_public = b64encode(f"{self.provider.client_id}:{generate_id()}".encode()).decode()
133        res = self.client.post(
134            reverse("authentik_providers_oauth2:token-revoke"),
135            HTTP_AUTHORIZATION=f"Basic {auth_public}",
136            data={
137                "token": token.token,
138            },
139        )
140        self.assertEqual(res.status_code, 200)
141
142    def test_revoke_logout(self):
143        """Test revoke on logout"""
144        self.client.force_login(self.user)
145        AccessToken.objects.create(
146            provider=self.provider,
147            user=self.user,
148            session=self.client.session["authenticatedsession"],
149            token=generate_id(),
150            auth_time=timezone.now(),
151            _scope="openid user profile",
152            _id_token=json.dumps(
153                asdict(
154                    IDToken("foo", "bar"),
155                )
156            ),
157        )
158        self.client.logout()
159        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
160
161    def test_revoke_session_delete(self):
162        """Test revoke on logout"""
163        session = AuthenticatedSession.objects.create(
164            session=Session.objects.create(
165                session_key=generate_id(),
166                last_ip=ClientIPMiddleware.default_ip,
167            ),
168            user=self.user,
169        )
170        AccessToken.objects.create(
171            provider=self.provider,
172            user=self.user,
173            session=session,
174            token=generate_id(),
175            auth_time=timezone.now(),
176            _scope="openid user profile",
177            _id_token=json.dumps(
178                asdict(
179                    IDToken("foo", "bar"),
180                )
181            ),
182        )
183        session.delete()
184        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
185
186    def test_revoke_user_deactivated(self):
187        """Test revoke on logout"""
188        AccessToken.objects.create(
189            provider=self.provider,
190            user=self.user,
191            token=generate_id(),
192            auth_time=timezone.now(),
193            _scope="openid user profile",
194            _id_token=json.dumps(
195                asdict(
196                    IDToken("foo", "bar"),
197                )
198            ),
199        )
200        RefreshToken.objects.create(
201            provider=self.provider,
202            user=self.user,
203            token=generate_id(),
204            auth_time=timezone.now(),
205            _scope="openid user profile",
206            _id_token=json.dumps(
207                asdict(
208                    IDToken("foo", "bar"),
209                )
210            ),
211        )
212        DeviceToken.objects.create(
213            provider=self.provider,
214            user=self.user,
215            _scope="openid user profile",
216        )
217
218        self.user.is_active = False
219        self.user.save()
220
221        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
222        self.assertEqual(RefreshToken.objects.including_expired().all().count(), 0)
223        self.assertEqual(DeviceToken.objects.including_expired().all().count(), 0)

Test revoke view

def setUp(self) -> None:
31    def setUp(self) -> None:
32        super().setUp()
33        self.provider: OAuth2Provider = OAuth2Provider.objects.create(
34            name=generate_id(),
35            authorization_flow=create_test_flow(),
36            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
37            signing_key=create_test_cert(),
38        )
39        self.app = Application.objects.create(
40            name=generate_id(), slug=generate_id(), provider=self.provider
41        )
42        self.app.save()
43        self.user = create_test_admin_user()
44        self.auth = b64encode(
45            f"{self.provider.client_id}:{self.provider.client_secret}".encode()
46        ).decode()

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

def test_revoke_refresh(self):
48    def test_revoke_refresh(self):
49        """Test revoke"""
50        token: RefreshToken = RefreshToken.objects.create(
51            provider=self.provider,
52            user=self.user,
53            token=generate_id(),
54            auth_time=timezone.now(),
55            _scope="openid user profile",
56            _id_token=json.dumps(
57                asdict(
58                    IDToken("foo", "bar"),
59                )
60            ),
61        )
62        res = self.client.post(
63            reverse("authentik_providers_oauth2:token-revoke"),
64            HTTP_AUTHORIZATION=f"Basic {self.auth}",
65            data={
66                "token": token.token,
67            },
68        )
69        self.assertEqual(res.status_code, 200)

Test revoke

def test_revoke_access(self):
71    def test_revoke_access(self):
72        """Test revoke"""
73        token: AccessToken = AccessToken.objects.create(
74            provider=self.provider,
75            user=self.user,
76            token=generate_id(),
77            auth_time=timezone.now(),
78            _scope="openid user profile",
79            _id_token=json.dumps(
80                asdict(
81                    IDToken("foo", "bar"),
82                )
83            ),
84        )
85        res = self.client.post(
86            reverse("authentik_providers_oauth2:token-revoke"),
87            HTTP_AUTHORIZATION=f"Basic {self.auth}",
88            data={
89                "token": token.token,
90            },
91        )
92        self.assertEqual(res.status_code, 200)

Test revoke

def test_revoke_invalid(self):
 94    def test_revoke_invalid(self):
 95        """Test revoke (invalid token)"""
 96        res = self.client.post(
 97            reverse("authentik_providers_oauth2:token-revoke"),
 98            HTTP_AUTHORIZATION=f"Basic {self.auth}",
 99            data={
100                "token": generate_id(),
101            },
102        )
103        self.assertEqual(res.status_code, 200)

Test revoke (invalid token)

def test_revoke_invalid_auth(self):
105    def test_revoke_invalid_auth(self):
106        """Test revoke (invalid auth)"""
107        res = self.client.post(
108            reverse("authentik_providers_oauth2:token-revoke"),
109            HTTP_AUTHORIZATION="Basic fqewr",
110            data={
111                "token": generate_id(),
112            },
113        )
114        self.assertEqual(res.status_code, 401)

Test revoke (invalid auth)

def test_revoke_public(self):
116    def test_revoke_public(self):
117        """Test revoke public client"""
118        self.provider.client_type = ClientTypes.PUBLIC
119        self.provider.save()
120        token: AccessToken = AccessToken.objects.create(
121            provider=self.provider,
122            user=self.user,
123            token=generate_id(),
124            auth_time=timezone.now(),
125            _scope="openid user profile",
126            _id_token=json.dumps(
127                asdict(
128                    IDToken("foo", "bar"),
129                )
130            ),
131        )
132        auth_public = b64encode(f"{self.provider.client_id}:{generate_id()}".encode()).decode()
133        res = self.client.post(
134            reverse("authentik_providers_oauth2:token-revoke"),
135            HTTP_AUTHORIZATION=f"Basic {auth_public}",
136            data={
137                "token": token.token,
138            },
139        )
140        self.assertEqual(res.status_code, 200)

Test revoke public client

def test_revoke_logout(self):
142    def test_revoke_logout(self):
143        """Test revoke on logout"""
144        self.client.force_login(self.user)
145        AccessToken.objects.create(
146            provider=self.provider,
147            user=self.user,
148            session=self.client.session["authenticatedsession"],
149            token=generate_id(),
150            auth_time=timezone.now(),
151            _scope="openid user profile",
152            _id_token=json.dumps(
153                asdict(
154                    IDToken("foo", "bar"),
155                )
156            ),
157        )
158        self.client.logout()
159        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)

Test revoke on logout

def test_revoke_session_delete(self):
161    def test_revoke_session_delete(self):
162        """Test revoke on logout"""
163        session = AuthenticatedSession.objects.create(
164            session=Session.objects.create(
165                session_key=generate_id(),
166                last_ip=ClientIPMiddleware.default_ip,
167            ),
168            user=self.user,
169        )
170        AccessToken.objects.create(
171            provider=self.provider,
172            user=self.user,
173            session=session,
174            token=generate_id(),
175            auth_time=timezone.now(),
176            _scope="openid user profile",
177            _id_token=json.dumps(
178                asdict(
179                    IDToken("foo", "bar"),
180                )
181            ),
182        )
183        session.delete()
184        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)

Test revoke on logout

def test_revoke_user_deactivated(self):
186    def test_revoke_user_deactivated(self):
187        """Test revoke on logout"""
188        AccessToken.objects.create(
189            provider=self.provider,
190            user=self.user,
191            token=generate_id(),
192            auth_time=timezone.now(),
193            _scope="openid user profile",
194            _id_token=json.dumps(
195                asdict(
196                    IDToken("foo", "bar"),
197                )
198            ),
199        )
200        RefreshToken.objects.create(
201            provider=self.provider,
202            user=self.user,
203            token=generate_id(),
204            auth_time=timezone.now(),
205            _scope="openid user profile",
206            _id_token=json.dumps(
207                asdict(
208                    IDToken("foo", "bar"),
209                )
210            ),
211        )
212        DeviceToken.objects.create(
213            provider=self.provider,
214            user=self.user,
215            _scope="openid user profile",
216        )
217
218        self.user.is_active = False
219        self.user.save()
220
221        self.assertEqual(AccessToken.objects.including_expired().all().count(), 0)
222        self.assertEqual(RefreshToken.objects.including_expired().all().count(), 0)
223        self.assertEqual(DeviceToken.objects.including_expired().all().count(), 0)

Test revoke on logout