workos 5.38.0__tar.gz → 5.39.0__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 (171) hide show
  1. {workos-5.38.0 → workos-5.39.0}/PKG-INFO +14 -19
  2. {workos-5.38.0 → workos-5.39.0}/README.md +1 -1
  3. workos-5.39.0/pyproject.toml +68 -0
  4. {workos-5.38.0 → workos-5.39.0/src}/workos/_base_client.py +8 -0
  5. {workos-5.38.0 → workos-5.39.0/src}/workos/_client_configuration.py +2 -0
  6. {workos-5.38.0 → workos-5.39.0/src}/workos/async_client.py +4 -2
  7. {workos-5.38.0 → workos-5.39.0/src}/workos/client.py +4 -2
  8. {workos-5.38.0 → workos-5.39.0/src}/workos/directory_sync.py +8 -10
  9. {workos-5.38.0 → workos-5.39.0/src}/workos/portal.py +1 -2
  10. {workos-5.38.0 → workos-5.39.0/src}/workos/session.py +24 -1
  11. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/list_filters.py +4 -4
  12. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/warnings.py +3 -3
  13. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/authentication_factor.py +4 -5
  14. workos-5.39.0/src/workos/types/user_management/password_hash_type.py +5 -0
  15. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/session.py +1 -3
  16. {workos-5.38.0 → workos-5.39.0/src}/workos/types/workos_model.py +1 -1
  17. {workos-5.38.0 → workos-5.39.0/src}/workos/user_management.py +9 -7
  18. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/request_helper.py +0 -1
  19. {workos-5.38.0 → workos-5.39.0/src}/workos/vault.py +0 -1
  20. {workos-5.38.0 → workos-5.39.0/src}/workos/widgets.py +0 -1
  21. workos-5.38.0/LICENSE +0 -21
  22. workos-5.38.0/setup.cfg +0 -4
  23. workos-5.38.0/setup.py +0 -53
  24. workos-5.38.0/tests/test_api_keys.py +0 -50
  25. workos-5.38.0/tests/test_async_http_client.py +0 -328
  26. workos-5.38.0/tests/test_audit_logs.py +0 -290
  27. workos-5.38.0/tests/test_client.py +0 -128
  28. workos-5.38.0/tests/test_directory_sync.py +0 -373
  29. workos-5.38.0/tests/test_events.py +0 -42
  30. workos-5.38.0/tests/test_fga.py +0 -652
  31. workos-5.38.0/tests/test_mfa.py +0 -257
  32. workos-5.38.0/tests/test_organization_domains.py +0 -136
  33. workos-5.38.0/tests/test_organizations.py +0 -300
  34. workos-5.38.0/tests/test_passwordless.py +0 -56
  35. workos-5.38.0/tests/test_pipes.py +0 -167
  36. workos-5.38.0/tests/test_portal.py +0 -117
  37. workos-5.38.0/tests/test_session.py +0 -621
  38. workos-5.38.0/tests/test_sso.py +0 -402
  39. workos-5.38.0/tests/test_sync_http_client.py +0 -375
  40. workos-5.38.0/tests/test_user_management.py +0 -1286
  41. workos-5.38.0/tests/test_user_management_list_sessions.py +0 -73
  42. workos-5.38.0/tests/test_user_management_revoke_session.py +0 -26
  43. workos-5.38.0/tests/test_vault.py +0 -488
  44. workos-5.38.0/tests/test_webhooks.py +0 -156
  45. workos-5.38.0/tests/test_widgets.py +0 -25
  46. workos-5.38.0/workos/__about__.py +0 -23
  47. workos-5.38.0/workos/types/user_management/password_hash_type.py +0 -4
  48. workos-5.38.0/workos.egg-info/PKG-INFO +0 -93
  49. workos-5.38.0/workos.egg-info/SOURCES.txt +0 -167
  50. workos-5.38.0/workos.egg-info/dependency_links.txt +0 -1
  51. workos-5.38.0/workos.egg-info/not-zip-safe +0 -1
  52. workos-5.38.0/workos.egg-info/requires.txt +0 -20
  53. workos-5.38.0/workos.egg-info/top_level.txt +0 -1
  54. {workos-5.38.0 → workos-5.39.0/src}/workos/__init__.py +0 -0
  55. {workos-5.38.0 → workos-5.39.0/src}/workos/api_keys.py +0 -0
  56. {workos-5.38.0 → workos-5.39.0/src}/workos/audit_logs.py +0 -0
  57. {workos-5.38.0 → workos-5.39.0/src}/workos/events.py +0 -0
  58. {workos-5.38.0 → workos-5.39.0/src}/workos/exceptions.py +0 -0
  59. {workos-5.38.0 → workos-5.39.0/src}/workos/fga.py +0 -0
  60. {workos-5.38.0 → workos-5.39.0/src}/workos/mfa.py +0 -0
  61. {workos-5.38.0 → workos-5.39.0/src}/workos/organization_domains.py +0 -0
  62. {workos-5.38.0 → workos-5.39.0/src}/workos/organizations.py +0 -0
  63. {workos-5.38.0 → workos-5.39.0/src}/workos/passwordless.py +0 -0
  64. {workos-5.38.0 → workos-5.39.0/src}/workos/pipes.py +0 -0
  65. {workos-5.38.0 → workos-5.39.0/src}/workos/py.typed +0 -0
  66. {workos-5.38.0 → workos-5.39.0/src}/workos/sso.py +0 -0
  67. {workos-5.38.0 → workos-5.39.0/src}/workos/types/__init__.py +0 -0
  68. {workos-5.38.0 → workos-5.39.0/src}/workos/types/api_keys/__init__.py +0 -0
  69. {workos-5.38.0 → workos-5.39.0/src}/workos/types/api_keys/api_keys.py +0 -0
  70. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/__init__.py +0 -0
  71. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_event.py +0 -0
  72. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_event_actor.py +0 -0
  73. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_event_context.py +0 -0
  74. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_event_target.py +0 -0
  75. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_export.py +0 -0
  76. {workos-5.38.0 → workos-5.39.0/src}/workos/types/audit_logs/audit_log_metadata.py +0 -0
  77. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/__init__.py +0 -0
  78. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/directory.py +0 -0
  79. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/directory_group.py +0 -0
  80. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/directory_state.py +0 -0
  81. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/directory_type.py +0 -0
  82. {workos-5.38.0 → workos-5.39.0/src}/workos/types/directory_sync/directory_user.py +0 -0
  83. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/__init__.py +0 -0
  84. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/authentication_payload.py +0 -0
  85. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/connection_payload_with_legacy_fields.py +0 -0
  86. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/directory_group_membership_payload.py +0 -0
  87. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/directory_group_with_previous_attributes.py +0 -0
  88. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/directory_payload.py +0 -0
  89. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/directory_payload_with_legacy_fields.py +0 -0
  90. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/directory_user_with_previous_attributes.py +0 -0
  91. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/event.py +0 -0
  92. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/event_model.py +0 -0
  93. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/event_type.py +0 -0
  94. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/list_filters.py +0 -0
  95. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/organization_domain_verification_failed_payload.py +0 -0
  96. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/previous_attributes.py +0 -0
  97. {workos-5.38.0 → workos-5.39.0/src}/workos/types/events/session_payload.py +0 -0
  98. {workos-5.38.0 → workos-5.39.0/src}/workos/types/feature_flags/__init__.py +0 -0
  99. {workos-5.38.0 → workos-5.39.0/src}/workos/types/feature_flags/feature_flag.py +0 -0
  100. {workos-5.38.0 → workos-5.39.0/src}/workos/types/feature_flags/list_filters.py +0 -0
  101. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/__init__.py +0 -0
  102. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/authorization_resource_types.py +0 -0
  103. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/authorization_resources.py +0 -0
  104. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/check.py +0 -0
  105. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/list_filters.py +0 -0
  106. {workos-5.38.0 → workos-5.39.0/src}/workos/types/fga/warrant.py +0 -0
  107. {workos-5.38.0 → workos-5.39.0/src}/workos/types/list_resource.py +0 -0
  108. {workos-5.38.0 → workos-5.39.0/src}/workos/types/metadata.py +0 -0
  109. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/__init__.py +0 -0
  110. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/authentication_challenge.py +0 -0
  111. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/authentication_challenge_verification_response.py +0 -0
  112. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/authentication_factor_totp_and_challenge_response.py +0 -0
  113. {workos-5.38.0 → workos-5.39.0/src}/workos/types/mfa/enroll_authentication_factor_type.py +0 -0
  114. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organization_domains/__init__.py +0 -0
  115. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organization_domains/organization_domain.py +0 -0
  116. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organizations/__init__.py +0 -0
  117. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organizations/domain_data_input.py +0 -0
  118. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organizations/list_filters.py +0 -0
  119. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organizations/organization.py +0 -0
  120. {workos-5.38.0 → workos-5.39.0/src}/workos/types/organizations/organization_common.py +0 -0
  121. {workos-5.38.0 → workos-5.39.0/src}/workos/types/passwordless/__init__.py +0 -0
  122. {workos-5.38.0 → workos-5.39.0/src}/workos/types/passwordless/passwordless_session.py +0 -0
  123. {workos-5.38.0 → workos-5.39.0/src}/workos/types/passwordless/passwordless_session_type.py +0 -0
  124. {workos-5.38.0 → workos-5.39.0/src}/workos/types/pipes/__init__.py +0 -0
  125. {workos-5.38.0 → workos-5.39.0/src}/workos/types/pipes/pipes.py +0 -0
  126. {workos-5.38.0 → workos-5.39.0/src}/workos/types/portal/__init__.py +0 -0
  127. {workos-5.38.0 → workos-5.39.0/src}/workos/types/portal/portal_link.py +0 -0
  128. {workos-5.38.0 → workos-5.39.0/src}/workos/types/portal/portal_link_intent.py +0 -0
  129. {workos-5.38.0 → workos-5.39.0/src}/workos/types/portal/portal_link_intent_options.py +0 -0
  130. {workos-5.38.0 → workos-5.39.0/src}/workos/types/roles/__init__.py +0 -0
  131. {workos-5.38.0 → workos-5.39.0/src}/workos/types/roles/role.py +0 -0
  132. {workos-5.38.0 → workos-5.39.0/src}/workos/types/sso/__init__.py +0 -0
  133. {workos-5.38.0 → workos-5.39.0/src}/workos/types/sso/connection.py +0 -0
  134. {workos-5.38.0 → workos-5.39.0/src}/workos/types/sso/connection_domain.py +0 -0
  135. {workos-5.38.0 → workos-5.39.0/src}/workos/types/sso/profile.py +0 -0
  136. {workos-5.38.0 → workos-5.39.0/src}/workos/types/sso/sso_provider_type.py +0 -0
  137. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/__init__.py +2 -2
  138. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/authenticate_with_common.py +0 -0
  139. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/authentication_response.py +0 -0
  140. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/email_verification.py +0 -0
  141. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/impersonator.py +0 -0
  142. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/invitation.py +0 -0
  143. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/list_filters.py +0 -0
  144. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/magic_auth.py +0 -0
  145. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/oauth_tokens.py +0 -0
  146. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/organization_membership.py +0 -0
  147. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/password_reset.py +0 -0
  148. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/screen_hint.py +0 -0
  149. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/user.py +0 -0
  150. {workos-5.38.0 → workos-5.39.0/src}/workos/types/user_management/user_management_provider_type.py +0 -0
  151. {workos-5.38.0 → workos-5.39.0/src}/workos/types/vault/__init__.py +0 -0
  152. {workos-5.38.0 → workos-5.39.0/src}/workos/types/vault/key.py +0 -0
  153. {workos-5.38.0 → workos-5.39.0/src}/workos/types/vault/object.py +0 -0
  154. {workos-5.38.0 → workos-5.39.0/src}/workos/types/webhooks/__init__.py +0 -0
  155. {workos-5.38.0 → workos-5.39.0/src}/workos/types/webhooks/webhook.py +0 -0
  156. {workos-5.38.0 → workos-5.39.0/src}/workos/types/webhooks/webhook_model.py +0 -0
  157. {workos-5.38.0 → workos-5.39.0/src}/workos/types/webhooks/webhook_payload.py +0 -0
  158. {workos-5.38.0 → workos-5.39.0/src}/workos/types/widgets/__init__.py +0 -0
  159. {workos-5.38.0 → workos-5.39.0/src}/workos/types/widgets/widget_scope.py +0 -0
  160. {workos-5.38.0 → workos-5.39.0/src}/workos/types/widgets/widget_token_response.py +0 -0
  161. {workos-5.38.0 → workos-5.39.0/src}/workos/typing/__init__.py +0 -0
  162. {workos-5.38.0 → workos-5.39.0/src}/workos/typing/literals.py +0 -0
  163. {workos-5.38.0 → workos-5.39.0/src}/workos/typing/sync_or_async.py +0 -0
  164. {workos-5.38.0 → workos-5.39.0/src}/workos/typing/untyped_literal.py +0 -0
  165. {workos-5.38.0 → workos-5.39.0/src}/workos/typing/webhooks.py +0 -0
  166. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/__init__.py +0 -0
  167. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/_base_http_client.py +0 -0
  168. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/crypto_provider.py +0 -0
  169. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/http_client.py +0 -0
  170. {workos-5.38.0 → workos-5.39.0/src}/workos/utils/pagination_order.py +0 -0
  171. {workos-5.38.0 → workos-5.39.0/src}/workos/webhooks.py +0 -0
@@ -1,25 +1,20 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: workos
3
- Version: 5.38.0
3
+ Version: 5.39.0
4
4
  Summary: WorkOS Python Client
5
- Home-page: https://github.com/workos-inc/workos-python
6
5
  Author: WorkOS
7
- Author-email: team@workos.com
8
- License: MIT
9
- Classifier: Development Status :: 5 - Production/Stable
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.8
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
6
+ Author-email: WorkOS <team@workos.com>
7
+ License-Expression: MIT
8
+ Requires-Dist: cryptography>=44.0.2
9
+ Requires-Dist: httpx~=0.28.1
10
+ Requires-Dist: pydantic>=2.10.4
11
+ Requires-Dist: pyjwt>=2.10.0 ; python_full_version >= '3.9'
12
+ Requires-Dist: pyjwt>=2.9.0,<2.10 ; python_full_version == '3.8.*'
13
+ Requires-Python: >=3.8
14
+ Project-URL: Changelog, https://workos.com/docs/sdks/python
15
+ Project-URL: Documentation, https://workos.com/docs/reference
16
+ Project-URL: Homepage, https://workos.com/docs/sdks/python
20
17
  Description-Content-Type: text/markdown
21
- Provides-Extra: dev
22
- License-File: LICENSE
23
18
 
24
19
  # WorkOS Python Library
25
20
 
@@ -43,7 +38,7 @@ pip install workos
43
38
  To install from source, clone the repo and run the following:
44
39
 
45
40
  ```
46
- python setup.py install
41
+ python -m pip install .
47
42
  ```
48
43
 
49
44
  ## Configuration
@@ -20,7 +20,7 @@ pip install workos
20
20
  To install from source, clone the repo and run the following:
21
21
 
22
22
  ```
23
- python setup.py install
23
+ python -m pip install .
24
24
  ```
25
25
 
26
26
  ## Configuration
@@ -0,0 +1,68 @@
1
+ [project]
2
+ name = "workos"
3
+ version = "5.39.0"
4
+ description = "WorkOS Python Client"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [{ name = "WorkOS", email = "team@workos.com" }]
8
+ requires-python = ">=3.8"
9
+
10
+ dependencies = [
11
+ "cryptography>=44.0.2",
12
+ "httpx~=0.28.1",
13
+ "pydantic>=2.10.4",
14
+ "pyjwt>=2.10.0 ; python_full_version >= '3.9'",
15
+ "pyjwt>=2.9.0,<2.10 ; python_full_version == '3.8.*'",
16
+ ]
17
+
18
+ [project.urls]
19
+ Homepage = "https://workos.com/docs/sdks/python"
20
+ Documentation = "https://workos.com/docs/reference"
21
+ Changelog = "https://workos.com/docs/sdks/python"
22
+
23
+ [dependency-groups]
24
+ dev = [
25
+ { include-group = "test" },
26
+ { include-group = "lint" },
27
+ { include-group = "type_check" },
28
+ { include-group = "nox" },
29
+ ]
30
+ test = [
31
+ "pytest==8.3.4",
32
+ "pytest-asyncio==0.23.8",
33
+ "pytest-cov==5.0.0",
34
+ "six==1.17.0",
35
+ ]
36
+ lint = ["ruff==0.14.5"]
37
+ type_check = ["mypy==1.14.1"]
38
+ nox = [
39
+ "nox>=2024.10.9 ; python_version >= '3.9'",
40
+ "nox-uv>=0.7.0 ; python_version >= '3.9'",
41
+ ]
42
+
43
+
44
+ [tool.mypy]
45
+ packages = "workos"
46
+ warn_return_any = true
47
+ warn_unused_configs = true
48
+ warn_unreachable = true
49
+ warn_redundant_casts = true
50
+ warn_no_return = true
51
+ warn_unused_ignores = true
52
+ implicit_reexport = true
53
+ strict_equality = true
54
+ strict = true
55
+
56
+ [tool.ruff.lint.per-file-ignores]
57
+ "*/__init__.py" = ["F401", "F403"]
58
+
59
+ [tool.ruff.lint.mccabe]
60
+ max-complexity = 10
61
+
62
+ [tool.uv.build-backend]
63
+ source-include = ["py.typed"]
64
+ source-exclude = ["tests*"]
65
+
66
+ [build-system]
67
+ requires = ["uv_build>=0.8.15,<0.9.0"]
68
+ build-backend = "uv_build"
@@ -27,6 +27,7 @@ class BaseClient(ClientConfiguration):
27
27
  _base_url: str
28
28
  _client_id: str
29
29
  _request_timeout: int
30
+ _jwt_leeway: float
30
31
 
31
32
  def __init__(
32
33
  self,
@@ -35,6 +36,7 @@ class BaseClient(ClientConfiguration):
35
36
  client_id: Optional[str],
36
37
  base_url: Optional[str] = None,
37
38
  request_timeout: Optional[int] = None,
39
+ jwt_leeway: float = 0,
38
40
  ) -> None:
39
41
  api_key = api_key or os.getenv("WORKOS_API_KEY")
40
42
  if api_key is None:
@@ -66,6 +68,8 @@ class BaseClient(ClientConfiguration):
66
68
  else int(os.getenv("WORKOS_REQUEST_TIMEOUT", DEFAULT_REQUEST_TIMEOUT))
67
69
  )
68
70
 
71
+ self._jwt_leeway = jwt_leeway
72
+
69
73
  @property
70
74
  @abstractmethod
71
75
  def api_keys(self) -> ApiKeysModule: ...
@@ -136,3 +140,7 @@ class BaseClient(ClientConfiguration):
136
140
  @property
137
141
  def request_timeout(self) -> int:
138
142
  return self._request_timeout
143
+
144
+ @property
145
+ def jwt_leeway(self) -> float:
146
+ return self._jwt_leeway
@@ -8,3 +8,5 @@ class ClientConfiguration(Protocol):
8
8
  def client_id(self) -> str: ...
9
9
  @property
10
10
  def request_timeout(self) -> int: ...
11
+ @property
12
+ def jwt_leeway(self) -> float: ...
@@ -1,5 +1,5 @@
1
1
  from typing import Optional
2
- from workos.__about__ import __version__
2
+ from importlib.metadata import version
3
3
  from workos._base_client import BaseClient
4
4
  from workos.api_keys import AsyncApiKeys
5
5
  from workos.audit_logs import AuditLogsModule
@@ -32,18 +32,20 @@ class AsyncClient(BaseClient):
32
32
  client_id: Optional[str] = None,
33
33
  base_url: Optional[str] = None,
34
34
  request_timeout: Optional[int] = None,
35
+ jwt_leeway: float = 0,
35
36
  ):
36
37
  super().__init__(
37
38
  api_key=api_key,
38
39
  client_id=client_id,
39
40
  base_url=base_url,
40
41
  request_timeout=request_timeout,
42
+ jwt_leeway=jwt_leeway,
41
43
  )
42
44
  self._http_client = AsyncHTTPClient(
43
45
  api_key=self._api_key,
44
46
  base_url=self.base_url,
45
47
  client_id=self._client_id,
46
- version=__version__,
48
+ version=version("workos"),
47
49
  timeout=self.request_timeout,
48
50
  )
49
51
 
@@ -1,5 +1,5 @@
1
+ from importlib.metadata import version
1
2
  from typing import Optional
2
- from workos.__about__ import __version__
3
3
  from workos._base_client import BaseClient
4
4
  from workos.api_keys import ApiKeys
5
5
  from workos.audit_logs import AuditLogs
@@ -32,18 +32,20 @@ class SyncClient(BaseClient):
32
32
  client_id: Optional[str] = None,
33
33
  base_url: Optional[str] = None,
34
34
  request_timeout: Optional[int] = None,
35
+ jwt_leeway: float = 0,
35
36
  ):
36
37
  super().__init__(
37
38
  api_key=api_key,
38
39
  client_id=client_id,
39
40
  base_url=base_url,
40
41
  request_timeout=request_timeout,
42
+ jwt_leeway=jwt_leeway,
41
43
  )
42
44
  self._http_client = SyncHTTPClient(
43
45
  api_key=self._api_key,
44
46
  base_url=self.base_url,
45
47
  client_id=self._client_id,
46
- version=__version__,
48
+ version=version("workos"),
47
49
  timeout=self.request_timeout,
48
50
  )
49
51
 
@@ -176,7 +176,6 @@ class DirectorySync(DirectorySyncModule):
176
176
  after: Optional[str] = None,
177
177
  order: PaginationOrder = "desc",
178
178
  ) -> DirectoryUsersListResource:
179
-
180
179
  list_params: DirectoryUserListFilters = {
181
180
  "limit": limit,
182
181
  "before": before,
@@ -185,9 +184,9 @@ class DirectorySync(DirectorySyncModule):
185
184
  }
186
185
 
187
186
  if group_id is not None:
188
- list_params["group"] = group_id
187
+ list_params["group_id"] = group_id
189
188
  if directory_id is not None:
190
- list_params["directory"] = directory_id
189
+ list_params["directory_id"] = directory_id
191
190
 
192
191
  response = self._http_client.request(
193
192
  "directory_users",
@@ -219,9 +218,9 @@ class DirectorySync(DirectorySyncModule):
219
218
  }
220
219
 
221
220
  if user_id is not None:
222
- list_params["user"] = user_id
221
+ list_params["user_id"] = user_id
223
222
  if directory_id is not None:
224
- list_params["directory"] = directory_id
223
+ list_params["directory_id"] = directory_id
225
224
 
226
225
  response = self._http_client.request(
227
226
  "directory_groups",
@@ -315,7 +314,6 @@ class AsyncDirectorySync(DirectorySyncModule):
315
314
  after: Optional[str] = None,
316
315
  order: PaginationOrder = "desc",
317
316
  ) -> DirectoryUsersListResource:
318
-
319
317
  list_params: DirectoryUserListFilters = {
320
318
  "limit": limit,
321
319
  "before": before,
@@ -324,9 +322,9 @@ class AsyncDirectorySync(DirectorySyncModule):
324
322
  }
325
323
 
326
324
  if group_id is not None:
327
- list_params["group"] = group_id
325
+ list_params["group_id"] = group_id
328
326
  if directory_id is not None:
329
- list_params["directory"] = directory_id
327
+ list_params["directory_id"] = directory_id
330
328
 
331
329
  response = await self._http_client.request(
332
330
  "directory_users",
@@ -357,9 +355,9 @@ class AsyncDirectorySync(DirectorySyncModule):
357
355
  "order": order,
358
356
  }
359
357
  if user_id is not None:
360
- list_params["user"] = user_id
358
+ list_params["user_id"] = user_id
361
359
  if directory_id is not None:
362
- list_params["directory"] = directory_id
360
+ list_params["directory_id"] = directory_id
363
361
 
364
362
  response = await self._http_client.request(
365
363
  "directory_groups",
@@ -1,4 +1,4 @@
1
- from typing import Optional, Protocol, Dict, Literal, Union
1
+ from typing import Optional, Protocol
2
2
  from workos.types.portal.portal_link import PortalLink
3
3
  from workos.types.portal.portal_link_intent import PortalLinkIntent
4
4
  from workos.types.portal.portal_link_intent_options import IntentOptions
@@ -36,7 +36,6 @@ class PortalModule(Protocol):
36
36
 
37
37
 
38
38
  class Portal(PortalModule):
39
-
40
39
  _http_client: SyncHTTPClient
41
40
 
42
41
  def __init__(self, http_client: SyncHTTPClient):
@@ -35,6 +35,7 @@ class SessionModule(Protocol):
35
35
  cookie_password: str
36
36
  jwks: PyJWKClient
37
37
  jwk_algorithms: List[str]
38
+ jwt_leeway: float
38
39
 
39
40
  def __init__(
40
41
  self,
@@ -43,6 +44,7 @@ class SessionModule(Protocol):
43
44
  client_id: str,
44
45
  session_data: str,
45
46
  cookie_password: str,
47
+ jwt_leeway: float = 0,
46
48
  ) -> None:
47
49
  # If the cookie password is not provided, throw an error
48
50
  if cookie_password is None or cookie_password == "":
@@ -52,6 +54,7 @@ class SessionModule(Protocol):
52
54
  self.client_id = client_id
53
55
  self.session_data = session_data
54
56
  self.cookie_password = cookie_password
57
+ self.jwt_leeway = jwt_leeway
55
58
 
56
59
  self.jwks = _get_jwks_client(self.user_management.get_jwks_url())
57
60
 
@@ -91,13 +94,13 @@ class SessionModule(Protocol):
91
94
  signing_key.key,
92
95
  algorithms=self.jwk_algorithms,
93
96
  options={"verify_aud": False},
97
+ leeway=self.jwt_leeway,
94
98
  )
95
99
  except jwt.exceptions.InvalidTokenError:
96
100
  return AuthenticateWithSessionCookieErrorResponse(
97
101
  authenticated=False,
98
102
  reason=AuthenticateWithSessionCookieFailureReason.INVALID_JWT,
99
103
  )
100
-
101
104
  return AuthenticateWithSessionCookieSuccessResponse(
102
105
  authenticated=True,
103
106
  session_id=decoded["sid"],
@@ -137,6 +140,20 @@ class SessionModule(Protocol):
137
140
  )
138
141
  return str(result)
139
142
 
143
+ def _is_valid_jwt(self, token: str) -> bool:
144
+ try:
145
+ signing_key = self.jwks.get_signing_key_from_jwt(token)
146
+ jwt.decode(
147
+ token,
148
+ signing_key.key,
149
+ algorithms=self.jwk_algorithms,
150
+ options={"verify_aud": False},
151
+ leeway=self.jwt_leeway,
152
+ )
153
+ return True
154
+ except jwt.exceptions.InvalidTokenError:
155
+ return False
156
+
140
157
  @staticmethod
141
158
  def seal_data(data: Dict[str, Any], key: str) -> str:
142
159
  fernet = Fernet(key)
@@ -163,6 +180,7 @@ class Session(SessionModule):
163
180
  client_id: str,
164
181
  session_data: str,
165
182
  cookie_password: str,
183
+ jwt_leeway: float = 0,
166
184
  ) -> None:
167
185
  # If the cookie password is not provided, throw an error
168
186
  if cookie_password is None or cookie_password == "":
@@ -172,6 +190,7 @@ class Session(SessionModule):
172
190
  self.client_id = client_id
173
191
  self.session_data = session_data
174
192
  self.cookie_password = cookie_password
193
+ self.jwt_leeway = jwt_leeway
175
194
 
176
195
  self.jwks = _get_jwks_client(self.user_management.get_jwks_url())
177
196
 
@@ -224,6 +243,7 @@ class Session(SessionModule):
224
243
  signing_key.key,
225
244
  algorithms=self.jwk_algorithms,
226
245
  options={"verify_aud": False},
246
+ leeway=self.jwt_leeway,
227
247
  )
228
248
 
229
249
  return RefreshWithSessionCookieSuccessResponse(
@@ -255,6 +275,7 @@ class AsyncSession(SessionModule):
255
275
  client_id: str,
256
276
  session_data: str,
257
277
  cookie_password: str,
278
+ jwt_leeway: float = 0,
258
279
  ) -> None:
259
280
  # If the cookie password is not provided, throw an error
260
281
  if cookie_password is None or cookie_password == "":
@@ -264,6 +285,7 @@ class AsyncSession(SessionModule):
264
285
  self.client_id = client_id
265
286
  self.session_data = session_data
266
287
  self.cookie_password = cookie_password
288
+ self.jwt_leeway = jwt_leeway
267
289
 
268
290
  self.jwks = _get_jwks_client(self.user_management.get_jwks_url())
269
291
 
@@ -316,6 +338,7 @@ class AsyncSession(SessionModule):
316
338
  signing_key.key,
317
339
  algorithms=self.jwk_algorithms,
318
340
  options={"verify_aud": False},
341
+ leeway=self.jwt_leeway,
319
342
  )
320
343
 
321
344
  return RefreshWithSessionCookieSuccessResponse(
@@ -12,10 +12,10 @@ class DirectoryUserListFilters(
12
12
  ListArgs,
13
13
  total=False,
14
14
  ):
15
- group: Optional[str]
16
- directory: Optional[str]
15
+ group_id: Optional[str]
16
+ directory_id: Optional[str]
17
17
 
18
18
 
19
19
  class DirectoryGroupListFilters(ListArgs, total=False):
20
- user: Optional[str]
21
- directory: Optional[str]
20
+ user_id: Optional[str]
21
+ directory_id: Optional[str]
@@ -1,8 +1,8 @@
1
- from typing import Sequence, Union, Any, Dict, Literal
2
- from typing_extensions import Annotated
1
+ from typing import Any, Dict, Literal, Sequence, Union
3
2
 
4
3
  from pydantic import BeforeValidator
5
4
  from pydantic_core.core_schema import ValidationInfo
5
+ from typing_extensions import Annotated
6
6
 
7
7
  from workos.types.workos_model import WorkOSModel
8
8
 
@@ -12,7 +12,7 @@ class FGABaseWarning(WorkOSModel):
12
12
  message: str
13
13
 
14
14
 
15
- class MissingContextKeysWarning(FGABaseWarning):
15
+ class MissingContextKeysWarning(FGABaseWarning): # type: ignore[override, unused-ignore]
16
16
  code: Literal["missing_context_keys"]
17
17
  keys: Sequence[str]
18
18
 
@@ -1,13 +1,12 @@
1
1
  from typing import Literal, Optional, Union
2
2
 
3
- from workos.types.workos_model import WorkOSModel
4
3
  from workos.types.mfa.enroll_authentication_factor_type import (
5
4
  SmsAuthenticationFactorType,
6
5
  TotpAuthenticationFactorType,
7
6
  )
7
+ from workos.types.workos_model import WorkOSModel
8
8
  from workos.typing.literals import LiteralOrUntyped
9
9
 
10
-
11
10
  AuthenticationFactorType = Literal[
12
11
  "generic_otp", SmsAuthenticationFactorType, TotpAuthenticationFactorType
13
12
  ]
@@ -43,21 +42,21 @@ class AuthenticationFactorBase(WorkOSModel):
43
42
  user_id: Optional[str] = None
44
43
 
45
44
 
46
- class AuthenticationFactorTotp(AuthenticationFactorBase):
45
+ class AuthenticationFactorTotp(AuthenticationFactorBase): # type: ignore[override, unused-ignore]
47
46
  """Representation of a MFA Authentication Factor Response as returned by WorkOS through the MFA feature."""
48
47
 
49
48
  type: TotpAuthenticationFactorType
50
49
  totp: TotpFactor
51
50
 
52
51
 
53
- class AuthenticationFactorTotpExtended(AuthenticationFactorBase):
52
+ class AuthenticationFactorTotpExtended(AuthenticationFactorBase): # type: ignore[override, unused-ignore]
54
53
  """Representation of a MFA Authentication Factor Response when enrolling an authentication factor."""
55
54
 
56
55
  type: TotpAuthenticationFactorType
57
56
  totp: ExtendedTotpFactor
58
57
 
59
58
 
60
- class AuthenticationFactorSms(AuthenticationFactorBase):
59
+ class AuthenticationFactorSms(AuthenticationFactorBase): # type: ignore[override, unused-ignore]
61
60
  """Representation of a SMS Authentication Factor Response as returned by WorkOS through the MFA feature."""
62
61
 
63
62
  type: SmsAuthenticationFactorType
@@ -0,0 +1,5 @@
1
+ from typing import Literal
2
+
3
+ PasswordHashType = Literal[
4
+ "bcrypt", "firebase-scrypt", "pbkdf2", "scrypt", "ssha", "argon2"
5
+ ]
@@ -1,7 +1,5 @@
1
1
  from enum import Enum
2
- from typing import Optional, Sequence, TypedDict, Union
3
-
4
- from typing_extensions import Literal
2
+ from typing import Literal, Optional, Sequence, TypedDict, Union
5
3
 
6
4
  from workos.types.user_management.impersonator import Impersonator
7
5
  from workos.types.user_management.user import User
@@ -14,7 +14,7 @@ class WorkOSModel(BaseModel):
14
14
  by_alias: bool = False,
15
15
  exclude_unset: bool = False,
16
16
  exclude_defaults: bool = False,
17
- exclude_none: bool = False
17
+ exclude_none: bool = False,
18
18
  ) -> Dict[str, Any]:
19
19
  return self.model_dump(
20
20
  include=include,
@@ -1,5 +1,6 @@
1
1
  from typing import Awaitable, Optional, Protocol, Sequence, Type, Union, cast
2
2
  from urllib.parse import urlencode
3
+
3
4
  from workos._client_configuration import ClientConfiguration
4
5
  from workos.session import AsyncSession, Session
5
6
  from workos.types.feature_flags import FeatureFlag
@@ -38,19 +39,20 @@ from workos.types.user_management.authenticate_with_common import (
38
39
  AuthenticateWithTotpParameters,
39
40
  )
40
41
  from workos.types.user_management.authentication_response import (
41
- AuthKitAuthenticationResponse,
42
42
  AuthenticationResponseType,
43
+ AuthKitAuthenticationResponse,
43
44
  )
44
45
  from workos.types.user_management.list_filters import (
45
46
  AuthenticationFactorsListFilters,
46
47
  InvitationsListFilters,
47
48
  OrganizationMembershipsListFilters,
49
+ SessionsListFilters,
48
50
  UsersListFilters,
49
51
  )
50
52
  from workos.types.user_management.password_hash_type import PasswordHashType
51
53
  from workos.types.user_management.screen_hint import ScreenHintType
52
- from workos.types.user_management.session import SessionConfig
53
54
  from workos.types.user_management.session import Session as UserManagementSession
55
+ from workos.types.user_management.session import SessionConfig
54
56
  from workos.types.user_management.user_management_provider_type import (
55
57
  UserManagementProviderType,
56
58
  )
@@ -59,11 +61,11 @@ from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
59
61
  from workos.utils.pagination_order import PaginationOrder
60
62
  from workos.utils.request_helper import (
61
63
  DEFAULT_LIST_RESPONSE_LIMIT,
62
- RESPONSE_TYPE_CODE,
63
- REQUEST_METHOD_POST,
64
- REQUEST_METHOD_GET,
65
64
  REQUEST_METHOD_DELETE,
65
+ REQUEST_METHOD_GET,
66
+ REQUEST_METHOD_POST,
66
67
  REQUEST_METHOD_PUT,
68
+ RESPONSE_TYPE_CODE,
67
69
  QueryParameters,
68
70
  RequestHelper,
69
71
  )
@@ -120,8 +122,6 @@ FeatureFlagsListResource = WorkOSListResource[
120
122
  FeatureFlag, FeatureFlagListFilters, ListMetadata
121
123
  ]
122
124
 
123
- from workos.types.user_management.list_filters import SessionsListFilters
124
-
125
125
  SessionsListResource = WorkOSListResource[
126
126
  UserManagementSession, SessionsListFilters, ListMetadata
127
127
  ]
@@ -956,6 +956,7 @@ class UserManagement(UserManagementModule):
956
956
  client_id=self._http_client.client_id,
957
957
  session_data=sealed_session,
958
958
  cookie_password=cookie_password,
959
+ jwt_leeway=self._client_configuration.jwt_leeway,
959
960
  )
960
961
 
961
962
  def get_user(self, user_id: str) -> User:
@@ -1679,6 +1680,7 @@ class AsyncUserManagement(UserManagementModule):
1679
1680
  client_id=self._http_client.client_id,
1680
1681
  session_data=sealed_session,
1681
1682
  cookie_password=cookie_password,
1683
+ jwt_leeway=self._client_configuration.jwt_leeway,
1682
1684
  )
1683
1685
 
1684
1686
  async def get_user(self, user_id: str) -> User:
@@ -14,7 +14,6 @@ QueryParameters = Dict[str, QueryParameterValue]
14
14
 
15
15
 
16
16
  class RequestHelper:
17
-
18
17
  @classmethod
19
18
  def build_parameterized_url(cls, url: str, **params: QueryParameterValue) -> str:
20
19
  escaped_params = {k: urllib.parse.quote(str(v)) for k, v in params.items()}
@@ -9,7 +9,6 @@ from workos.types.list_resource import (
9
9
  WorkOSListResource,
10
10
  )
11
11
  from workos.utils.http_client import SyncHTTPClient
12
- from workos.utils.pagination_order import PaginationOrder
13
12
  from workos.utils.request_helper import (
14
13
  DEFAULT_LIST_RESPONSE_LIMIT,
15
14
  REQUEST_METHOD_DELETE,
@@ -30,7 +30,6 @@ class WidgetsModule(Protocol):
30
30
 
31
31
 
32
32
  class Widgets(WidgetsModule):
33
-
34
33
  _http_client: SyncHTTPClient
35
34
 
36
35
  def __init__(self, http_client: SyncHTTPClient):
workos-5.38.0/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 WorkOS
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
workos-5.38.0/setup.cfg DELETED
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-