sanic-security 1.15.2__py3-none-any.whl → 1.16.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: sanic-security
3
- Version: 1.15.2
3
+ Version: 1.16.0
4
4
  Summary: An async security library for the Sanic framework.
5
5
  Author-email: Aidan Stewart <me@na-stewart.com>
6
6
  Project-URL: Documentation, https://security.na-stewart.com/
@@ -17,11 +17,12 @@ License-File: LICENSE
17
17
  Requires-Dist: tortoise-orm>=0.17.0
18
18
  Requires-Dist: pyjwt>=1.7.0
19
19
  Requires-Dist: captcha>=0.4
20
- Requires-Dist: pillow>=9.5.0
21
20
  Requires-Dist: argon2-cffi>=20.1.0
22
21
  Requires-Dist: sanic>=21.3.0
22
+ Provides-Extra: oauth
23
+ Requires-Dist: httpx-oauth>=0.16.1; extra == "oauth"
23
24
  Provides-Extra: dev
24
- Requires-Dist: httpx; extra == "dev"
25
+ Requires-Dist: httpx-oauth; extra == "dev"
25
26
  Requires-Dist: black; extra == "dev"
26
27
  Requires-Dist: blacken-docs; extra == "dev"
27
28
  Requires-Dist: pdoc3; extra == "dev"
@@ -62,6 +63,7 @@ Requires-Dist: cryptography>=3.3.1; extra == "crypto"
62
63
  * [Installation](#installation)
63
64
  * [Configuration](#configuration)
64
65
  * [Usage](#usage)
66
+ * [OAuth](#oauth)
65
67
  * [Authentication](#authentication)
66
68
  * [CAPTCHA](#captcha)
67
69
  * [Two-step Verification](#two-step-verification)
@@ -79,6 +81,7 @@ Requires-Dist: cryptography>=3.3.1; extra == "crypto"
79
81
  Sanic Security is an authentication, authorization, and verification library designed for use with the
80
82
  [Sanic](https://github.com/huge-success/sanic) framework.
81
83
 
84
+ * OAuth2 integration
82
85
  * Login, registration, and authentication with refresh mechanisms
83
86
  * Role based authorization with wildcard permissions
84
87
  * Image & audio CAPTCHA
@@ -102,7 +105,7 @@ pip3 install sanic-security
102
105
 
103
106
  * Install the Sanic Security pip package with the `cryptography` dependency included.
104
107
 
105
- If you are planning on encoding or decoding JWTs using certain digital signature algorithms (like RSA or ECDSA which use
108
+ If you're planning on encoding or decoding JWTs using certain digital signature algorithms (like RSA or ECDSA which use
106
109
  the public secret and private secret), you will need to install the `cryptography` library. This can be installed explicitly, or
107
110
  as an extra requirement.
108
111
 
@@ -110,7 +113,17 @@ as an extra requirement.
110
113
  pip3 install sanic-security[crypto]
111
114
  ````
112
115
 
113
- * Update sanic-security if already installed.
116
+ * Install the Sanic Security pip package with the `httpx-oauth` dependency included.
117
+
118
+ If you're planning on utilizing OAuth, you will need to install the `httpx-oauth` library. This can be installed explicitly, or
119
+ as an extra requirement.
120
+
121
+ ```shell
122
+ pip3 install sanic-security[oauth]
123
+ ````
124
+
125
+ * Update Sanic Security if already installed.
126
+
114
127
  ```shell
115
128
  pip3 install sanic-security --upgrade
116
129
  ```
@@ -138,41 +151,119 @@ You can load environment variables with a different prefix via `config.load_envi
138
151
 
139
152
  * Default configuration values:
140
153
 
141
- | Key | Value | Description |
142
- |---------------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
143
- | **SECRET** | This is a big secret. Shhhhh | The secret used for generating and signing JWTs. This should be a string unique to your application. Keep it safe. |
144
- | **PUBLIC_SECRET** | None | The secret used for verifying and decoding JWTs and can be publicly shared. This should be a string unique to your application. |
145
- | **SESSION_SAMESITE** | Strict | The SameSite attribute of session cookies. |
146
- | **SESSION_SECURE** | True | The Secure attribute of session cookies. |
147
- | **SESSION_HTTPONLY** | True | The HttpOnly attribute of session cookies. HIGHLY recommended that you do not turn this off, unless you know what you are doing. |
148
- | **SESSION_DOMAIN** | None | The Domain attribute of session cookies. |
149
- | **SESSION_ENCODING_ALGORITHM** | HS256 | The algorithm used to encode and decode session JWT's. |
150
- | **SESSION_PREFIX** | tkn | Prefix attached to the beginning of session cookies. |
151
- | **MAX_CHALLENGE_ATTEMPTS** | 3 | The maximum amount of session challenge attempts allowed. |
152
- | **CAPTCHA_SESSION_EXPIRATION** | 180 | The amount of seconds till captcha session expiration on creation. Setting to 0 will disable expiration. |
153
- | **CAPTCHA_FONT** | captcha-font.ttf | The file path to the font being used for captcha generation. Several fonts can be used by separating them via comma. |
154
- | **CAPTCHA_VOICE** | captcha-voice/ | The directory of the voice library being used for audio captcha generation. |
155
- | **TWO_STEP_SESSION_EXPIRATION** | 300 | The amount of seconds till two-step session expiration on creation. Setting to 0 will disable expiration. |
156
- | **AUTHENTICATION_SESSION_EXPIRATION** | 86400 | The amount of seconds till authentication session expiration on creation. Setting to 0 will disable expiration. |
157
- | **AUTHENTICATION_REFRESH_EXPIRATION** | 604800 | The amount of seconds till authentication refresh expiration. Setting to 0 will disable refresh mechanism. |
158
- | **ALLOW_LOGIN_WITH_USERNAME** | False | Allows login via username; unique constraint is disabled when set to false. |
159
- | **INITIAL_ADMIN_EMAIL** | admin@example.com | Email used when creating the initial admin account. |
160
- | **INITIAL_ADMIN_PASSWORD** | admin123 | Password used when creating the initial admin account. |
154
+ | Key | Value | Description |
155
+ |---------------------------------------|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
156
+ | **SECRET** | This is a big secret. Shhhhh | The secret used for generating and signing JWTs. This should be a string unique to your application. Keep it safe. |
157
+ | **PUBLIC_SECRET** | None | The secret used for verifying and decoding JWTs and can be publicly shared. This should be a string unique to your application. |
158
+ | **OAUTH_CLIENT** | None | The client ID provided by the OAuth provider, this is used to identify the application making the OAuth request. |
159
+ | **OAUTH_SECRET** | None | The client secret provided by the OAuth provider, this is used in conjunction with the client ID to authenticate the application. |
160
+ | **SESSION_SAMESITE** | Strict | The SameSite attribute of session cookies. |
161
+ | **SESSION_SECURE** | True | The Secure attribute of session cookies. |
162
+ | **SESSION_HTTPONLY** | True | The HttpOnly attribute of session cookies. HIGHLY recommended that you do not turn this off, unless you know what you are doing. |
163
+ | **SESSION_DOMAIN** | None | The Domain attribute of session cookies. |
164
+ | **SESSION_ENCODING_ALGORITHM** | HS256 | The algorithm used to encode and decode session JWT's. |
165
+ | **SESSION_PREFIX** | tkn | Prefix attached to the beginning of session cookies. |
166
+ | **MAX_CHALLENGE_ATTEMPTS** | 3 | The maximum amount of session challenge attempts allowed. |
167
+ | **CAPTCHA_SESSION_EXPIRATION** | 180 | The amount of seconds till captcha session expiration on creation. Setting to 0 will disable expiration. |
168
+ | **CAPTCHA_FONT** | captcha-font.ttf | The file path to the font being used for captcha generation. Several fonts can be used by separating them via comma. |
169
+ | **CAPTCHA_VOICE** | captcha-voice/ | The directory of the voice library being used for audio captcha generation. |
170
+ | **TWO_STEP_SESSION_EXPIRATION** | 300 | The amount of seconds till two-step session expiration on creation. Setting to 0 will disable expiration. |
171
+ | **AUTHENTICATION_SESSION_EXPIRATION** | 86400 | The amount of seconds till authentication session expiration on creation. Setting to 0 will disable expiration. |
172
+ | **AUTHENTICATION_REFRESH_EXPIRATION** | 604800 | The amount of seconds till authentication refresh expiration. Setting to 0 will disable refresh mechanism. |
173
+ | **ALLOW_LOGIN_WITH_USERNAME** | False | Allows login via username; unique constraint is disabled when set to false. |
174
+ | **INITIAL_ADMIN_EMAIL** | admin@example.com | Email used when creating the initial admin account. |
175
+ | **INITIAL_ADMIN_PASSWORD** | admin123 | Password used when creating the initial admin account. |
161
176
 
162
177
  ## Usage
163
178
 
164
179
  Sanic Security's authentication and verification functionality is session based. A new session will be created for the user after the user logs in or requests some form of verification (two-step, captcha). The session data is then encoded into a JWT and stored on a cookie on the user’s browser. The session cookie is then sent
165
180
  along with every subsequent request. The server can then compare the session stored on the cookie against the session information stored in the database to verify user’s identity and send a response with the corresponding state.
166
181
 
167
- * Initialize sanic-security as follows:
182
+ * Initialize Sanic Security as follows:
168
183
  ```python
169
184
  initialize_security(app)
185
+ initialize_oauth(app) # Remove if not utilizing OAuth
170
186
  if __name__ == "__main__":
171
187
  app.run(host="127.0.0.1", port=8000, workers=1, debug=True)
172
188
  ```
173
189
 
174
190
  The tables in the below examples represent example [request form-data](https://sanicframework.org/en/guide/basics/request.html#form).
175
191
 
192
+ ## OAuth
193
+
194
+ OAuth2 provides users with a familiar experience by having them register/login using their existing credentials from other trusted services (such as Google, Discord, etc.).
195
+
196
+ This feature is designed to complement existing authentication protocols by linking a Sanic Security account with the user's OAuth credentials. As a result, developers can leverage all of Sanic Security's capabilities including robust session handling and account management.
197
+
198
+ * Define OAuth clients
199
+
200
+ You can [utilize various OAuth clients](https://frankie567.github.io/httpx-oauth/reference/httpx_oauth.clients/) based on your needs or [customize one](https://frankie567.github.io/httpx-oauth/usage/).
201
+ ID and secret should be stored and referenced via configuration.
202
+
203
+ ```python
204
+ discord_oauth = DiscordOAuth2(
205
+ "1325594509043830895",
206
+ "WNMYbkDJjGlC0ej60qM-50tC9mMy0EXa",
207
+ )
208
+ google_oauth = GoogleOAuth2(
209
+ "480512993828-e2e9tqtl2b8or62hc4l7hpoh478s3ni1.apps.googleusercontent.com",
210
+ "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",
211
+ )
212
+ ```
213
+
214
+ * Redirect to authorization URL
215
+
216
+ ```python
217
+ @app.route("api/security/oauth", methods=["GET", "POST"])
218
+ async def on_oauth_request(request):
219
+ return redirect(
220
+ await oauth_url(
221
+ google_oauth, "http://localhost:8000/api/security/oauth/callback"
222
+ )
223
+ )
224
+ ```
225
+
226
+ * Handle OAuth callback
227
+
228
+ ```python
229
+ @app.get("api/security/oauth/callback")
230
+ async def on_oauth_callback(request):
231
+ token_info, authentication_session = await oauth_callback(
232
+ request, google_oauth, "http://localhost:8000/api/security/oauth/callback"
233
+ )
234
+ response = json(
235
+ "Authorization successful.",
236
+ {"token_info": token_info, "auth_session": authentication_session.json},
237
+ )
238
+ oauth_encode(response, token_info)
239
+ authentication_session.encode(response)
240
+ return response
241
+ ```
242
+
243
+ * Get access token
244
+
245
+ ```python
246
+ @app.get("api/security/oauth/token")
247
+ async def on_oauth_token(request):
248
+ token_info = await decode_oauth(request, google_oauth)
249
+ return json(
250
+ "Access token retrieved.",
251
+ token_info,
252
+ )
253
+ ```
254
+
255
+ * Requires access token (This method is not called directly and instead used as a decorator)
256
+
257
+ ```python
258
+ @app.get("api/security/oauth/token")
259
+ @requires_oauth(google_oauth)
260
+ async def on_oauth_token(request):
261
+ return json(
262
+ "Access token retrieved.",
263
+ request.ctx.oauth,
264
+ )
265
+ ```
266
+
176
267
  ## Authentication
177
268
 
178
269
  * Registration (With two-step account verification)
@@ -324,7 +415,9 @@ or you can download/create your own and specify its path in the configuration.
324
415
  @app.get("api/security/captcha")
325
416
  async def on_captcha_img_request(request):
326
417
  captcha_session = await request_captcha(request)
327
- response = captcha_session.get_image() # Captcha: LJ0F3U
418
+ response = raw(
419
+ captcha_session.get_image(), content_type="image/jpeg"
420
+ ) # Captcha: LJ0F3U
328
421
  captcha_session.encode(response)
329
422
  return response
330
423
  ```
@@ -334,8 +427,12 @@ async def on_captcha_img_request(request):
334
427
  ```python
335
428
  @app.get("api/security/captcha/audio")
336
429
  async def on_captcha_audio_request(request):
337
- captcha_session = await CaptchaSession.decode(request)
338
- return captcha_session.get_audio() # Captcha: LJ0F3U
430
+ captcha_session = await request_captcha(request)
431
+ response = raw(
432
+ captcha_session.get_audio(), content_type="audio/mpeg"
433
+ ) # Captcha: LJ0F3U
434
+ captcha_session.encode(response)
435
+ return response
339
436
  ```
340
437
 
341
438
  * Attempt CAPTCHA
@@ -366,7 +463,7 @@ async def on_captcha(request):
366
463
 
367
464
  ## Two-step Verification
368
465
 
369
- Two-step verification should be integrated with other custom functionalities, such as account verification during registration.
466
+ Two-step verification should be integrated with other custom functionalities, such as forgot password recovery.
370
467
 
371
468
  * Request Two-step Verification
372
469
 
@@ -447,8 +544,10 @@ Wildcard permissions support the concept of multiple levels or parts. For exampl
447
544
  await assign_role(
448
545
  "Chat Room Moderator",
449
546
  account,
450
- "channels:view,delete, voice:*, account:suspend,mute",
451
547
  "Can read and delete messages in all chat rooms, suspend and mute accounts, and control voice chat.",
548
+ "channels:view,delete",
549
+ "voice:*",
550
+ "account:suspend,mute",
452
551
  )
453
552
  ```
454
553
 
@@ -467,7 +566,7 @@ async def on_check_perms(request):
467
566
 
468
567
  ```python
469
568
  @app.post("api/security/perms")
470
- @require_permissions("channels:view", "voice:*")
569
+ @requires_permission("channels:view", "voice:*")
471
570
  async def on_check_perms(request):
472
571
  return text("Account is authorized.")
473
572
  ```
@@ -485,7 +584,7 @@ async def on_check_roles(request):
485
584
 
486
585
  ```python
487
586
  @app.post("api/security/roles")
488
- @require_roles("Chat Room Moderator")
587
+ @requires_role("Chat Room Moderator")
489
588
  async def on_check_roles(request):
490
589
  return text("Account is authorized.")
491
590
  ```
@@ -582,16 +681,3 @@ Distributed under the MIT License. See `LICENSE` for more information.
582
681
  * PATCH version when you make backwards compatible bug fixes.
583
682
 
584
683
  [https://semver.org/](https://semver.org/)
585
-
586
- <!-- MARKDOWN LINKS & IMAGES -->
587
- <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
588
- [contributors-shield]: https://img.shields.io/github/contributors/sunset-developer/sanic-security.svg?style=flat-square
589
- [contributors-url]: https://github.com/sunset-developer/sanic-security/graphs/contributors
590
- [forks-shield]: https://img.shields.io/github/forks/sunset-developer/sanic-security.svg?style=flat-square
591
- [forks-url]: https://github.com/sunset-developer/sanic-security/network/members
592
- [stars-shield]: https://img.shields.io/github/stars/sunset-developer/sanic-security.svg?style=flat-square
593
- [stars-url]: https://github.com/sunset-developer/sanic-security/stargazers
594
- [issues-shield]: https://img.shields.io/github/issues/sunset-developer/sanic-security.svg?style=flat-square
595
- [issues-url]: https://github.com/sunset-developer/sanic-security/issues
596
- [license-shield]: https://img.shields.io/github/license/sunset-developer/sanic-security.svg?style=flat-square
597
- [license-url]: https://github.com/sunset-developer/sanic-security/blob/master/LICENSE
@@ -0,0 +1,17 @@
1
+ sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ sanic_security/authentication.py,sha256=dogkcRsZH81WqKMqvwnDXN44ANCOuZsuuTGeo3di0c4,12985
3
+ sanic_security/authorization.py,sha256=ssq58w4vLv4YsNt40ufxHVyCeNzVDby3UcOYOEeTnI4,8428
4
+ sanic_security/configuration.py,sha256=2kWC4CZXvWR1wtBaqkMl58IA0VzxhI2ZbBTqd7LS_fE,6305
5
+ sanic_security/exceptions.py,sha256=RCYrDUgczwH_Uz2A__z1zCc8iKKbt2YSBdNTQUaMykc,5381
6
+ sanic_security/models.py,sha256=Ote83cdLUTpNWOMaY1uM04yDmst5_DamPEMFcSSmdks,22161
7
+ sanic_security/oauth.py,sha256=Wnd-jqC3uIi-fi4cV15_gmhXTi2FyuY9NAwKG5FxLr8,8398
8
+ sanic_security/utils.py,sha256=WlPOEEQGcfZk-GbPNu6OiysNXAo9mw80TitDV7XxWMc,3762
9
+ sanic_security/verification.py,sha256=0pBoGBVGsyTFNLHI0lyz640Y1f8fnKjLjA8zHzXutqM,8660
10
+ sanic_security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ sanic_security/test/server.py,sha256=opZGmoLuNZgZR2WHzu5WnWecniRnUu-nheqQsrhau5I,13313
12
+ sanic_security/test/tests.py,sha256=h6v3N1YhvENNA0eC-RqJK1sqGe2gFeKAMPJu7hjceqc,22570
13
+ sanic_security-1.16.0.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
14
+ sanic_security-1.16.0.dist-info/METADATA,sha256=d9uGtSKHAiUtmZev-_kjjfTYWCcAKQ1s4RchCUPWPBc,25648
15
+ sanic_security-1.16.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
16
+ sanic_security-1.16.0.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
17
+ sanic_security-1.16.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- sanic_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sanic_security/authentication.py,sha256=3Pit1B4PN_MRvwAlhYPHl_6DGD9JVpdPjgjiyKQJanM,13145
3
- sanic_security/authorization.py,sha256=jAxfDT9cHN_zpMKcA3oYFZ5Eu2KItnMJZ7oPcqmMwrw,7537
4
- sanic_security/configuration.py,sha256=_E66ts5g9t_XHW9ZAnr48rWVcZmGNu_DWGDxm_AVVWE,5681
5
- sanic_security/exceptions.py,sha256=9zISLyAvP6qN8sNR8e5qxKP__FA4NLIXCun_fEKndOw,5297
6
- sanic_security/models.py,sha256=1gMoPnzA9cpJaZXJ1GtgAzsXxGO-rts-f3YyVgcd7lY,22475
7
- sanic_security/utils.py,sha256=Il5MjFzVe975yx_CV2HV_LVQYl2W3XYDRGtCG5CQA8Q,3531
8
- sanic_security/verification.py,sha256=9bi8-NZ8GE3rcuELZ63yh18zDg8RxvxGPkhAu5SzLn0,8692
9
- sanic_security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- sanic_security/test/server.py,sha256=RjL9Kfvkfqpm5TXWwFQKKa0J4hfTKgwI6U0s_TAKO8w,11984
11
- sanic_security/test/tests.py,sha256=bW5fHJfsCrg8eBmcSqVMLm0R5XRL1ou-XJJRgz09GOE,21993
12
- sanic_security-1.15.2.dist-info/LICENSE,sha256=sXlJs9_mG-dCkPfWsDnuzydJWagS82E2gYtkVH9enHA,1100
13
- sanic_security-1.15.2.dist-info/METADATA,sha256=PNjYIu36zcUqehxfO0Zg7X98CwHSzGbPc1FYXsXo7qs,23247
14
- sanic_security-1.15.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
15
- sanic_security-1.15.2.dist-info/top_level.txt,sha256=ZybkhHXSjfzhmv8XeqLvnNmLmv21Z0oPX6Ep4DJN8b0,15
16
- sanic_security-1.15.2.dist-info/RECORD,,