sanic-security 1.12.4__tar.gz → 1.12.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {sanic_security-1.12.4/sanic_security.egg-info → sanic_security-1.12.6}/PKG-INFO +20 -24
  2. {sanic_security-1.12.4 → sanic_security-1.12.6}/README.md +18 -22
  3. {sanic_security-1.12.4 → sanic_security-1.12.6}/pyproject.toml +2 -2
  4. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/authentication.py +16 -0
  5. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/exceptions.py +1 -1
  6. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/test/server.py +2 -8
  7. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/test/tests.py +1 -3
  8. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/utils.py +4 -1
  9. {sanic_security-1.12.4 → sanic_security-1.12.6/sanic_security.egg-info}/PKG-INFO +20 -24
  10. {sanic_security-1.12.4 → sanic_security-1.12.6}/LICENSE +0 -0
  11. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/__init__.py +0 -0
  12. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/authorization.py +0 -0
  13. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/configuration.py +0 -0
  14. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/models.py +0 -0
  15. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/test/__init__.py +0 -0
  16. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security/verification.py +0 -0
  17. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security.egg-info/SOURCES.txt +0 -0
  18. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security.egg-info/dependency_links.txt +0 -0
  19. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security.egg-info/requires.txt +0 -0
  20. {sanic_security-1.12.4 → sanic_security-1.12.6}/sanic_security.egg-info/top_level.txt +0 -0
  21. {sanic_security-1.12.4 → sanic_security-1.12.6}/setup.cfg +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sanic-security
3
- Version: 1.12.4
3
+ Version: 1.12.6
4
4
  Summary: An async security library for the Sanic framework.
5
- Author-email: Aidan Stewart <na.stewart365@gmail.com>
5
+ Author-email: Aidan Stewart <me@na-stewart.com>
6
6
  Project-URL: Documentation, https://security.na-stewart.com/
7
7
  Project-URL: Repository, https://github.com/na-stewart/sanic-security
8
8
  Keywords: security,authentication,authorization,verification,async,sanic
@@ -197,7 +197,7 @@ async def on_register(request):
197
197
  account = await register(request)
198
198
  two_step_session = await request_two_step_verification(request, account)
199
199
  await email_code(
200
- account.email, two_step_session.code # Code = 197251
200
+ account.email, two_step_session.code # Code = 24KF19
201
201
  ) # Custom method for emailing verification code.
202
202
  response = json(
203
203
  "Registration successful! Email verification required.",
@@ -213,7 +213,7 @@ Verifies the client's account via two-step session code.
213
213
 
214
214
  | Key | Value |
215
215
  |----------|--------|
216
- | **code** | 197251 |
216
+ | **code** | 24KF19 |
217
217
 
218
218
  ```python
219
219
  @app.post("api/security/verify")
@@ -237,7 +237,7 @@ async def on_login(request):
237
237
  request, authentication_session.bearer
238
238
  )
239
239
  await email_code(
240
- authentication_session.bearer.email, two_step_session.code # Code = 197251
240
+ authentication_session.bearer.email, two_step_session.code # Code = XGED2U
241
241
  ) # Custom method for emailing verification code.
242
242
  response = json(
243
243
  "Login successful! Two-factor authentication required.",
@@ -248,7 +248,7 @@ async def on_login(request):
248
248
  return response
249
249
  ```
250
250
 
251
- If this isn't desired, you can pass an account and password attempt directly into the login instead.
251
+ If this isn't desired, you can pass an account and password attempt directly into the login method instead.
252
252
 
253
253
  * Fulfill Second Factor
254
254
 
@@ -256,7 +256,7 @@ Fulfills client authentication session's second factor requirement via two-step
256
256
 
257
257
  | Key | Value |
258
258
  |----------|--------|
259
- | **code** | 197251 |
259
+ | **code** | XGED2U |
260
260
 
261
261
  ```python
262
262
  @app.post("api/security/fulfill-2fa")
@@ -321,19 +321,15 @@ async def on_authenticate(request):
321
321
  return response
322
322
  ```
323
323
 
324
- * Authentication Middleware
324
+ * Refresh Encoder
325
325
 
326
- New/Refreshed session returned if client's session expired during authentication, requires encoding.
327
-
328
- Middleware is recommended to automatically encode the refreshed session.
326
+ A new/refreshed session is returned during authentication when the client's current session expires and it
327
+ requires encoding. This should be be done automatically via middleware.
329
328
 
330
329
  ```python
331
- @app.on_response
332
- async def authentication_refresh_encoder(request, response):
333
- if hasattr(request.ctx, "authentication_session"):
334
- authentication_session = request.ctx.authentication_session
335
- if authentication_session.is_refresh:
336
- authentication_session.encode(response)
330
+ attach_refresh_encoder(app)
331
+ if __name__ == "__main__":
332
+ app.run(host="127.0.0.1", port=8000)
337
333
  ```
338
334
 
339
335
  ## Captcha
@@ -351,7 +347,7 @@ downloading a .ttf font and defining the file's path in the configuration.
351
347
  @app.get("api/security/captcha")
352
348
  async def on_captcha_img_request(request):
353
349
  captcha_session = await request_captcha(request)
354
- response = captcha_session.get_image() # Captcha: 192731
350
+ response = captcha_session.get_image() # Captcha: LJ0F3U
355
351
  captcha_session.encode(response)
356
352
  return response
357
353
  ```
@@ -360,7 +356,7 @@ async def on_captcha_img_request(request):
360
356
 
361
357
  | Key | Value |
362
358
  |-------------|--------|
363
- | **captcha** | 192731 |
359
+ | **captcha** | LJ0F3U |
364
360
 
365
361
  ```python
366
362
  @app.post("api/security/captcha")
@@ -373,7 +369,7 @@ async def on_captcha(request):
373
369
 
374
370
  | Key | Value |
375
371
  |-------------|--------|
376
- | **captcha** | 192731 |
372
+ | **captcha** | LJ0F3U |
377
373
 
378
374
  ```python
379
375
  @app.post("api/security/captcha")
@@ -395,7 +391,7 @@ Two-step verification should be integrated with other custom functionality. For
395
391
  ```python
396
392
  @app.post("api/security/two-step/request")
397
393
  async def on_two_step_request(request):
398
- two_step_session = await request_two_step_verification(request) # Code = 197251
394
+ two_step_session = await request_two_step_verification(request) # Code = T2I58I
399
395
  await email_code(
400
396
  two_step_session.bearer.email, two_step_session.code
401
397
  ) # Custom method for emailing verification code.
@@ -409,7 +405,7 @@ async def on_two_step_request(request):
409
405
  ```python
410
406
  @app.post("api/security/two-step/resend")
411
407
  async def on_two_step_resend(request):
412
- two_step_session = await TwoStepSession.decode(request) # Code = 197251
408
+ two_step_session = await TwoStepSession.decode(request) # Code = T2I58I
413
409
  await email_code(
414
410
  two_step_session.bearer.email, two_step_session.code
415
411
  ) # Custom method for emailing verification code.
@@ -420,7 +416,7 @@ async def on_two_step_resend(request):
420
416
 
421
417
  | Key | Value |
422
418
  |----------|--------|
423
- | **code** | 197251 |
419
+ | **code** | T2I58I |
424
420
 
425
421
  ```python
426
422
  @app.post("api/security/two-step")
@@ -434,7 +430,7 @@ async def on_two_step_verification(request):
434
430
 
435
431
  | Key | Value |
436
432
  |----------|--------|
437
- | **code** | 197251 |
433
+ | **code** | T2I58I |
438
434
 
439
435
  ```python
440
436
  @app.post("api/security/two-step")
@@ -166,7 +166,7 @@ async def on_register(request):
166
166
  account = await register(request)
167
167
  two_step_session = await request_two_step_verification(request, account)
168
168
  await email_code(
169
- account.email, two_step_session.code # Code = 197251
169
+ account.email, two_step_session.code # Code = 24KF19
170
170
  ) # Custom method for emailing verification code.
171
171
  response = json(
172
172
  "Registration successful! Email verification required.",
@@ -182,7 +182,7 @@ Verifies the client's account via two-step session code.
182
182
 
183
183
  | Key | Value |
184
184
  |----------|--------|
185
- | **code** | 197251 |
185
+ | **code** | 24KF19 |
186
186
 
187
187
  ```python
188
188
  @app.post("api/security/verify")
@@ -206,7 +206,7 @@ async def on_login(request):
206
206
  request, authentication_session.bearer
207
207
  )
208
208
  await email_code(
209
- authentication_session.bearer.email, two_step_session.code # Code = 197251
209
+ authentication_session.bearer.email, two_step_session.code # Code = XGED2U
210
210
  ) # Custom method for emailing verification code.
211
211
  response = json(
212
212
  "Login successful! Two-factor authentication required.",
@@ -217,7 +217,7 @@ async def on_login(request):
217
217
  return response
218
218
  ```
219
219
 
220
- If this isn't desired, you can pass an account and password attempt directly into the login instead.
220
+ If this isn't desired, you can pass an account and password attempt directly into the login method instead.
221
221
 
222
222
  * Fulfill Second Factor
223
223
 
@@ -225,7 +225,7 @@ Fulfills client authentication session's second factor requirement via two-step
225
225
 
226
226
  | Key | Value |
227
227
  |----------|--------|
228
- | **code** | 197251 |
228
+ | **code** | XGED2U |
229
229
 
230
230
  ```python
231
231
  @app.post("api/security/fulfill-2fa")
@@ -290,19 +290,15 @@ async def on_authenticate(request):
290
290
  return response
291
291
  ```
292
292
 
293
- * Authentication Middleware
293
+ * Refresh Encoder
294
294
 
295
- New/Refreshed session returned if client's session expired during authentication, requires encoding.
296
-
297
- Middleware is recommended to automatically encode the refreshed session.
295
+ A new/refreshed session is returned during authentication when the client's current session expires and it
296
+ requires encoding. This should be be done automatically via middleware.
298
297
 
299
298
  ```python
300
- @app.on_response
301
- async def authentication_refresh_encoder(request, response):
302
- if hasattr(request.ctx, "authentication_session"):
303
- authentication_session = request.ctx.authentication_session
304
- if authentication_session.is_refresh:
305
- authentication_session.encode(response)
299
+ attach_refresh_encoder(app)
300
+ if __name__ == "__main__":
301
+ app.run(host="127.0.0.1", port=8000)
306
302
  ```
307
303
 
308
304
  ## Captcha
@@ -320,7 +316,7 @@ downloading a .ttf font and defining the file's path in the configuration.
320
316
  @app.get("api/security/captcha")
321
317
  async def on_captcha_img_request(request):
322
318
  captcha_session = await request_captcha(request)
323
- response = captcha_session.get_image() # Captcha: 192731
319
+ response = captcha_session.get_image() # Captcha: LJ0F3U
324
320
  captcha_session.encode(response)
325
321
  return response
326
322
  ```
@@ -329,7 +325,7 @@ async def on_captcha_img_request(request):
329
325
 
330
326
  | Key | Value |
331
327
  |-------------|--------|
332
- | **captcha** | 192731 |
328
+ | **captcha** | LJ0F3U |
333
329
 
334
330
  ```python
335
331
  @app.post("api/security/captcha")
@@ -342,7 +338,7 @@ async def on_captcha(request):
342
338
 
343
339
  | Key | Value |
344
340
  |-------------|--------|
345
- | **captcha** | 192731 |
341
+ | **captcha** | LJ0F3U |
346
342
 
347
343
  ```python
348
344
  @app.post("api/security/captcha")
@@ -364,7 +360,7 @@ Two-step verification should be integrated with other custom functionality. For
364
360
  ```python
365
361
  @app.post("api/security/two-step/request")
366
362
  async def on_two_step_request(request):
367
- two_step_session = await request_two_step_verification(request) # Code = 197251
363
+ two_step_session = await request_two_step_verification(request) # Code = T2I58I
368
364
  await email_code(
369
365
  two_step_session.bearer.email, two_step_session.code
370
366
  ) # Custom method for emailing verification code.
@@ -378,7 +374,7 @@ async def on_two_step_request(request):
378
374
  ```python
379
375
  @app.post("api/security/two-step/resend")
380
376
  async def on_two_step_resend(request):
381
- two_step_session = await TwoStepSession.decode(request) # Code = 197251
377
+ two_step_session = await TwoStepSession.decode(request) # Code = T2I58I
382
378
  await email_code(
383
379
  two_step_session.bearer.email, two_step_session.code
384
380
  ) # Custom method for emailing verification code.
@@ -389,7 +385,7 @@ async def on_two_step_resend(request):
389
385
 
390
386
  | Key | Value |
391
387
  |----------|--------|
392
- | **code** | 197251 |
388
+ | **code** | T2I58I |
393
389
 
394
390
  ```python
395
391
  @app.post("api/security/two-step")
@@ -403,7 +399,7 @@ async def on_two_step_verification(request):
403
399
 
404
400
  | Key | Value |
405
401
  |----------|--------|
406
- | **code** | 197251 |
402
+ | **code** | T2I58I |
407
403
 
408
404
  ```python
409
405
  @app.post("api/security/two-step")
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sanic-security"
7
- version = "1.12.4"
7
+ version = "1.12.6"
8
8
  requires-python = ">=3.8"
9
9
  dependencies = [
10
10
  "tortoise-orm>=0.17.0",
@@ -16,7 +16,7 @@ dependencies = [
16
16
  ]
17
17
  description = "An async security library for the Sanic framework."
18
18
  authors = [
19
- { name="Aidan Stewart", email="na.stewart365@gmail.com" },
19
+ { name="Aidan Stewart", email="me@na-stewart.com" },
20
20
  ]
21
21
  readme = "README.md"
22
22
  keywords = ["security", "authentication", "authorization", "verification", "async", "sanic"]
@@ -249,6 +249,22 @@ def requires_authentication(arg=None):
249
249
  return decorator(arg) if callable(arg) else decorator
250
250
 
251
251
 
252
+ def attach_refresh_encoder(app: Sanic):
253
+ """
254
+ Automatically encodes the new/refreshed session returned during authentication when client's current session expires.
255
+
256
+ Args:
257
+ app: (Sanic): The main Sanic application instance.
258
+ """
259
+
260
+ @app.on_response
261
+ async def refresh_encoder_middleware(request, response):
262
+ if hasattr(request.ctx, "authentication_session"):
263
+ authentication_session = request.ctx.authentication_session
264
+ if authentication_session.is_refresh:
265
+ authentication_session.encode(response)
266
+
267
+
252
268
  def create_initial_admin_account(app: Sanic) -> None:
253
269
  """
254
270
  Creates the initial admin account that can be logged into and has complete authoritative access.
@@ -130,7 +130,7 @@ class DeactivatedError(SessionError):
130
130
 
131
131
  def __init__(
132
132
  self,
133
- message: str = "Session has been deactivated or refreshed.",
133
+ message: str = "Session has been deactivated.",
134
134
  code: int = 401,
135
135
  ):
136
136
  super().__init__(message, code)
@@ -12,6 +12,7 @@ from sanic_security.authentication import (
12
12
  logout,
13
13
  create_initial_admin_account,
14
14
  fulfill_second_factor,
15
+ attach_refresh_encoder,
15
16
  )
16
17
  from sanic_security.authorization import (
17
18
  assign_role,
@@ -173,14 +174,6 @@ async def on_authenticate(request):
173
174
  return response
174
175
 
175
176
 
176
- @app.on_response
177
- async def authentication_refresh_encoder(request, response):
178
- if hasattr(request.ctx, "authentication_session"):
179
- authentication_session = request.ctx.authentication_session
180
- if authentication_session.is_refresh:
181
- authentication_session.encode(response)
182
-
183
-
184
177
  @app.post("api/test/auth/expire")
185
178
  @requires_authentication
186
179
  async def on_authentication_expire(request):
@@ -351,6 +344,7 @@ register_tortoise(
351
344
  modules={"models": ["sanic_security.models"]},
352
345
  generate_schemas=True,
353
346
  )
347
+ attach_refresh_encoder(app)
354
348
  create_initial_admin_account(app)
355
349
  if __name__ == "__main__":
356
350
  app.run(host="127.0.0.1", port=8000, workers=1, debug=True)
@@ -576,6 +576,4 @@ class MiscTest(TestCase):
576
576
  authenticate_response = self.client.post(
577
577
  "http://127.0.0.1:8000/api/test/auth",
578
578
  ) # Since session refresh handling is complete, it will be returned as a regular session now.
579
- assert (
580
- json.loads(authenticate_response.text)["data"]["refresh"] is False
581
- ), authenticate_response.text
579
+ assert authenticate_response.status_code == 200, authenticate_response.text
@@ -1,5 +1,6 @@
1
1
  import datetime
2
2
  import random
3
+ import string
3
4
 
4
5
  from sanic.request import Request
5
6
  from sanic.response import json as sanic_json, HTTPResponse
@@ -47,7 +48,9 @@ def get_code() -> str:
47
48
  Returns:
48
49
  code
49
50
  """
50
- return str(random.randint(100000, 999999))
51
+ return "".join(
52
+ random.choice(string.ascii_uppercase + string.digits) for _ in range(6)
53
+ )
51
54
 
52
55
 
53
56
  def json(
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sanic-security
3
- Version: 1.12.4
3
+ Version: 1.12.6
4
4
  Summary: An async security library for the Sanic framework.
5
- Author-email: Aidan Stewart <na.stewart365@gmail.com>
5
+ Author-email: Aidan Stewart <me@na-stewart.com>
6
6
  Project-URL: Documentation, https://security.na-stewart.com/
7
7
  Project-URL: Repository, https://github.com/na-stewart/sanic-security
8
8
  Keywords: security,authentication,authorization,verification,async,sanic
@@ -197,7 +197,7 @@ async def on_register(request):
197
197
  account = await register(request)
198
198
  two_step_session = await request_two_step_verification(request, account)
199
199
  await email_code(
200
- account.email, two_step_session.code # Code = 197251
200
+ account.email, two_step_session.code # Code = 24KF19
201
201
  ) # Custom method for emailing verification code.
202
202
  response = json(
203
203
  "Registration successful! Email verification required.",
@@ -213,7 +213,7 @@ Verifies the client's account via two-step session code.
213
213
 
214
214
  | Key | Value |
215
215
  |----------|--------|
216
- | **code** | 197251 |
216
+ | **code** | 24KF19 |
217
217
 
218
218
  ```python
219
219
  @app.post("api/security/verify")
@@ -237,7 +237,7 @@ async def on_login(request):
237
237
  request, authentication_session.bearer
238
238
  )
239
239
  await email_code(
240
- authentication_session.bearer.email, two_step_session.code # Code = 197251
240
+ authentication_session.bearer.email, two_step_session.code # Code = XGED2U
241
241
  ) # Custom method for emailing verification code.
242
242
  response = json(
243
243
  "Login successful! Two-factor authentication required.",
@@ -248,7 +248,7 @@ async def on_login(request):
248
248
  return response
249
249
  ```
250
250
 
251
- If this isn't desired, you can pass an account and password attempt directly into the login instead.
251
+ If this isn't desired, you can pass an account and password attempt directly into the login method instead.
252
252
 
253
253
  * Fulfill Second Factor
254
254
 
@@ -256,7 +256,7 @@ Fulfills client authentication session's second factor requirement via two-step
256
256
 
257
257
  | Key | Value |
258
258
  |----------|--------|
259
- | **code** | 197251 |
259
+ | **code** | XGED2U |
260
260
 
261
261
  ```python
262
262
  @app.post("api/security/fulfill-2fa")
@@ -321,19 +321,15 @@ async def on_authenticate(request):
321
321
  return response
322
322
  ```
323
323
 
324
- * Authentication Middleware
324
+ * Refresh Encoder
325
325
 
326
- New/Refreshed session returned if client's session expired during authentication, requires encoding.
327
-
328
- Middleware is recommended to automatically encode the refreshed session.
326
+ A new/refreshed session is returned during authentication when the client's current session expires and it
327
+ requires encoding. This should be be done automatically via middleware.
329
328
 
330
329
  ```python
331
- @app.on_response
332
- async def authentication_refresh_encoder(request, response):
333
- if hasattr(request.ctx, "authentication_session"):
334
- authentication_session = request.ctx.authentication_session
335
- if authentication_session.is_refresh:
336
- authentication_session.encode(response)
330
+ attach_refresh_encoder(app)
331
+ if __name__ == "__main__":
332
+ app.run(host="127.0.0.1", port=8000)
337
333
  ```
338
334
 
339
335
  ## Captcha
@@ -351,7 +347,7 @@ downloading a .ttf font and defining the file's path in the configuration.
351
347
  @app.get("api/security/captcha")
352
348
  async def on_captcha_img_request(request):
353
349
  captcha_session = await request_captcha(request)
354
- response = captcha_session.get_image() # Captcha: 192731
350
+ response = captcha_session.get_image() # Captcha: LJ0F3U
355
351
  captcha_session.encode(response)
356
352
  return response
357
353
  ```
@@ -360,7 +356,7 @@ async def on_captcha_img_request(request):
360
356
 
361
357
  | Key | Value |
362
358
  |-------------|--------|
363
- | **captcha** | 192731 |
359
+ | **captcha** | LJ0F3U |
364
360
 
365
361
  ```python
366
362
  @app.post("api/security/captcha")
@@ -373,7 +369,7 @@ async def on_captcha(request):
373
369
 
374
370
  | Key | Value |
375
371
  |-------------|--------|
376
- | **captcha** | 192731 |
372
+ | **captcha** | LJ0F3U |
377
373
 
378
374
  ```python
379
375
  @app.post("api/security/captcha")
@@ -395,7 +391,7 @@ Two-step verification should be integrated with other custom functionality. For
395
391
  ```python
396
392
  @app.post("api/security/two-step/request")
397
393
  async def on_two_step_request(request):
398
- two_step_session = await request_two_step_verification(request) # Code = 197251
394
+ two_step_session = await request_two_step_verification(request) # Code = T2I58I
399
395
  await email_code(
400
396
  two_step_session.bearer.email, two_step_session.code
401
397
  ) # Custom method for emailing verification code.
@@ -409,7 +405,7 @@ async def on_two_step_request(request):
409
405
  ```python
410
406
  @app.post("api/security/two-step/resend")
411
407
  async def on_two_step_resend(request):
412
- two_step_session = await TwoStepSession.decode(request) # Code = 197251
408
+ two_step_session = await TwoStepSession.decode(request) # Code = T2I58I
413
409
  await email_code(
414
410
  two_step_session.bearer.email, two_step_session.code
415
411
  ) # Custom method for emailing verification code.
@@ -420,7 +416,7 @@ async def on_two_step_resend(request):
420
416
 
421
417
  | Key | Value |
422
418
  |----------|--------|
423
- | **code** | 197251 |
419
+ | **code** | T2I58I |
424
420
 
425
421
  ```python
426
422
  @app.post("api/security/two-step")
@@ -434,7 +430,7 @@ async def on_two_step_verification(request):
434
430
 
435
431
  | Key | Value |
436
432
  |----------|--------|
437
- | **code** | 197251 |
433
+ | **code** | T2I58I |
438
434
 
439
435
  ```python
440
436
  @app.post("api/security/two-step")
File without changes