commonground-api-common 2.6.6__tar.gz → 2.6.7__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 (229) hide show
  1. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/CHANGELOG.rst +12 -0
  2. {commonground_api_common-2.6.6/commonground_api_common.egg-info → commonground_api_common-2.6.7}/PKG-INFO +5 -5
  3. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/README.rst +1 -1
  4. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7/commonground_api_common.egg-info}/PKG-INFO +5 -5
  5. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/commonground_api_common.egg-info/requires.txt +3 -3
  6. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/setup.cfg +4 -4
  7. commonground_api_common-2.6.7/tests/test_jwt_decoding.py +231 -0
  8. commonground_api_common-2.6.7/vng_api_common/__init__.py +1 -0
  9. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/middleware.py +51 -0
  10. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/conf/api.py +3 -0
  11. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/tests/auth.py +2 -0
  12. commonground_api_common-2.6.6/tests/test_jwt_decoding.py +0 -56
  13. commonground_api_common-2.6.6/vng_api_common/__init__.py +0 -1
  14. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/MANIFEST.in +0 -0
  15. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/bin/generate_schema +0 -0
  16. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/commonground_api_common.egg-info/SOURCES.txt +0 -0
  17. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/commonground_api_common.egg-info/dependency_links.txt +0 -0
  18. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/commonground_api_common.egg-info/not-zip-safe +0 -0
  19. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/commonground_api_common.egg-info/top_level.txt +0 -0
  20. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/pyproject.toml +0 -0
  21. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/setup.py +0 -0
  22. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_autorisatie_validation.py +0 -0
  23. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_cache_headers.py +0 -0
  24. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_cached_hyperlinkrelatedfields.py +0 -0
  25. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_check_query_params.py +0 -0
  26. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_checks.py +0 -0
  27. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_choices.py +0 -0
  28. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_configuration_steps_applicaties.py +0 -0
  29. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_configuration_steps_jwtsecrets.py +0 -0
  30. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_content_type_headers.py +0 -0
  31. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_field_extensions.py +0 -0
  32. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_filter_extension.py +0 -0
  33. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_filters.py +0 -0
  34. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_gegevensgroepen.py +0 -0
  35. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_get_resource.py +0 -0
  36. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_jwtsecrets.py +0 -0
  37. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_migrations.py +0 -0
  38. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_nested_serializer_validation.py +0 -0
  39. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_pagination.py +0 -0
  40. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_permissions.py +0 -0
  41. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_publish_validators.py +0 -0
  42. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_schema.py +0 -0
  43. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_serializer_extensions.py +0 -0
  44. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_serializer_fields.py +0 -0
  45. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_server_errors.py +0 -0
  46. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_utils.py +0 -0
  47. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_validators.py +0 -0
  48. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/tests/test_views.py +0 -0
  49. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/admin.py +0 -0
  50. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/api/__init__.py +0 -0
  51. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/api/permissions.py +0 -0
  52. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/api/serializers.py +0 -0
  53. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/api/urls.py +0 -0
  54. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/api/views.py +0 -0
  55. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/apps.py +0 -0
  56. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/__init__.py +0 -0
  57. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/admin.py +0 -0
  58. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/api/__init__.py +0 -0
  59. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/api/scopes.py +0 -0
  60. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/api/serializers.py +0 -0
  61. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/apps.py +0 -0
  62. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/audits.py +0 -0
  63. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0001_initial.py +0 -0
  64. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0002_auto_20190516_0830.py +0 -0
  65. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0003_auto_20190517_0844.py +0 -0
  66. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0004_auto_20190520_1238.py +0 -0
  67. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0005_auto_20190520_1450.py +0 -0
  68. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0006_audittrail_toelichting.py +0 -0
  69. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0007_auto_20190522_0916.py +0 -0
  70. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0008_audittrail_resource_weergave.py +0 -0
  71. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0009_auto_20190712_1643.py +0 -0
  72. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0010_audittrail_request_id.py +0 -0
  73. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0011_auto_20190918_1335.py +0 -0
  74. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0012_auto_20200619_0545.py +0 -0
  75. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0012_remove_audittrail_request_id.py +0 -0
  76. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0013_audittrail_logrecord_id.py +0 -0
  77. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0013_auto_20201207_0846.py +0 -0
  78. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0014_auto_20201221_0905.py +0 -0
  79. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0014_auto_20210323_1654.py +0 -0
  80. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0015_auto_20220318_1608.py +0 -0
  81. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0016_merge_20220607_0517.py +0 -0
  82. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0017_alter_audittrail_bron.py +0 -0
  83. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/0018_auto_20221212_0745.py +0 -0
  84. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/__init__.py +0 -0
  85. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/migrations/_operations.py +0 -0
  86. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/models.py +0 -0
  87. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/utils.py +0 -0
  88. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/audittrails/viewsets.py +0 -0
  89. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/__init__.py +0 -0
  90. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/admin.py +0 -0
  91. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0001_initial.py +0 -0
  92. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0002_authorizationsconfig.py +0 -0
  93. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0003_auto_20190502_0409.py +0 -0
  94. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0004_auto_20190503_0941.py +0 -0
  95. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0005_auto_20190506_0842.py +0 -0
  96. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0006_auto_20190506_0901.py +0 -0
  97. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0007_auto_20190506_1212.py +0 -0
  98. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0008_auto_20190712_1541.py +0 -0
  99. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0009_update_enums.py +0 -0
  100. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0010_auto_20190712_1643.py +0 -0
  101. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0011_auto_20191114_0728.py +0 -0
  102. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0012_auto_20200619_0545.py +0 -0
  103. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0013_auto_20201207_0846.py +0 -0
  104. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0014_auto_20201221_0905.py +0 -0
  105. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0015_auto_20220318_1608.py +0 -0
  106. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0016_remove_authorizationsconfig_api_root_and_more.py +0 -0
  107. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/0017_alter_applicatie_client_ids_and_more.py +0 -0
  108. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/migrations/__init__.py +0 -0
  109. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/models.py +0 -0
  110. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/serializers.py +0 -0
  111. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/utils.py +0 -0
  112. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/authorizations/validators.py +0 -0
  113. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/__init__.py +0 -0
  114. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/decorators.py +0 -0
  115. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/etags.py +0 -0
  116. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/introspection.py +0 -0
  117. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/models.py +0 -0
  118. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/registry.py +0 -0
  119. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/caching/signals.py +0 -0
  120. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/checks.py +0 -0
  121. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/choices.py +0 -0
  122. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/client.py +0 -0
  123. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/compat.py +0 -0
  124. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/conf/__init__.py +0 -0
  125. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/constants.py +0 -0
  126. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/contrib/__init__.py +0 -0
  127. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/contrib/setup_configuration/__init__.py +0 -0
  128. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/contrib/setup_configuration/models.py +0 -0
  129. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/contrib/setup_configuration/steps.py +0 -0
  130. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/db/__init__.py +0 -0
  131. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/db/operations.py +0 -0
  132. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/decorators.py +0 -0
  133. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/descriptors.py +0 -0
  134. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/doc.py +0 -0
  135. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/exception_handling.py +0 -0
  136. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/exceptions.py +0 -0
  137. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/__init__.py +0 -0
  138. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/file.py +0 -0
  139. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/gegevensgroep.py +0 -0
  140. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/geojson.py +0 -0
  141. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/hyperlink.py +0 -0
  142. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/polymorphic.py +0 -0
  143. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/extensions/query.py +0 -0
  144. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/fields.py +0 -0
  145. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/filters.py +0 -0
  146. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/filters_backend.py +0 -0
  147. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/filtersets.py +0 -0
  148. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/generators.py +0 -0
  149. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/geo.py +0 -0
  150. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/locale/nl/LC_MESSAGES/django.mo +0 -0
  151. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/locale/nl/LC_MESSAGES/django.po +0 -0
  152. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/middleware.py +0 -0
  153. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0001_initial.py +0 -0
  154. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0002_apicredential.py +0 -0
  155. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0003_auto_20190417_1145.py +0 -0
  156. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0004_auto_20190517_0903.py +0 -0
  157. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0005_auto_20190614_1346.py +0 -0
  158. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/0006_delete_apicredential.py +0 -0
  159. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/migrations/__init__.py +0 -0
  160. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/mocks.py +0 -0
  161. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/models.py +0 -0
  162. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/__init__.py +0 -0
  163. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/api/__init__.py +0 -0
  164. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/api/urls.py +0 -0
  165. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/api/views.py +0 -0
  166. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/apps.py +0 -0
  167. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/handlers.py +0 -0
  168. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0001_initial.py +0 -0
  169. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0002_subscription__subscription.py +0 -0
  170. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0003_auto_20190319_1048.py +0 -0
  171. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0004_auto_20190325_1313.py +0 -0
  172. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0005_fix_default_nrc.py +0 -0
  173. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0006_auto_20190417_1142.py +0 -0
  174. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0007_auto_20190429_1442.py +0 -0
  175. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0008_auto_20190502_0415.py +0 -0
  176. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0009_auto_20190729_0427.py +0 -0
  177. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0010_auto_20220704_1419.py +0 -0
  178. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/0011_remove_subscription_config_and_more.py +0 -0
  179. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/notifications/migrations/__init__.py +0 -0
  180. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/oas.py +0 -0
  181. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/pagination.py +0 -0
  182. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/permissions.py +0 -0
  183. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/polymorphism.py +0 -0
  184. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/routers.py +0 -0
  185. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/schema.py +0 -0
  186. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/scopes.py +0 -0
  187. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/search.py +0 -0
  188. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/serializers.py +0 -0
  189. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/css/admin/admin_overrides.css +0 -0
  190. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/css/screen.css +0 -0
  191. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/ico/favicon.png +0 -0
  192. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/img/vng.svg +0 -0
  193. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/LICENSE.txt +0 -0
  194. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/css/all.css +0 -0
  195. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/css/all.min.css +0 -0
  196. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-brands-400.eot +0 -0
  197. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-brands-400.svg +0 -0
  198. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  199. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-brands-400.woff +0 -0
  200. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  201. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-regular-400.eot +0 -0
  202. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-regular-400.svg +0 -0
  203. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  204. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-regular-400.woff +0 -0
  205. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  206. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-solid-900.eot +0 -0
  207. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-solid-900.svg +0 -0
  208. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  209. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-solid-900.woff +0 -0
  210. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/static/vng_api_common/libs/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  211. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/admin/base_site.html +0 -0
  212. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/includes/kanalen_card.html +0 -0
  213. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/index.html +0 -0
  214. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/master.html +0 -0
  215. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/ref/error_detail.html +0 -0
  216. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/ref/scopes.html +0 -0
  217. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templates/vng_api_common/view_config.html +0 -0
  218. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templatetags/__init__.py +0 -0
  219. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/templatetags/vng_api_common.py +0 -0
  220. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/tests/__init__.py +0 -0
  221. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/tests/caching.py +0 -0
  222. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/tests/schema.py +0 -0
  223. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/tests/urls.py +0 -0
  224. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/urls.py +0 -0
  225. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/utils.py +0 -0
  226. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/validators.py +0 -0
  227. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/version.py +0 -0
  228. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/views.py +0 -0
  229. {commonground_api_common-2.6.6 → commonground_api_common-2.6.7}/vng_api_common/viewsets.py +0 -0
@@ -2,6 +2,18 @@
2
2
  Change history
3
3
  ==============
4
4
 
5
+ 2.6.7 (2025-06-30)
6
+ ------------------
7
+
8
+ **Bugfixes**
9
+
10
+ * [#103] Fix 500 error that occurred with ``iat`` in future, log a warning
11
+ * Add JWT expiry validation based on ``iat``
12
+
13
+ **Maintenance**
14
+
15
+ * Upgrade PyJWT to 2.10.1
16
+
5
17
  2.6.6 (2025-06-04)
6
18
  ------------------
7
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commonground-api-common
3
- Version: 2.6.6
3
+ Version: 2.6.7
4
4
  Summary: Commonground API tooling
5
5
  Home-page: https://github.com/maykinmedia/commonground-api-common
6
6
  Author: Maykin Media, VNG-Realisatie
@@ -32,7 +32,7 @@ Requires-Dist: iso639-lang
32
32
  Requires-Dist: notifications-api-common>=0.3.1
33
33
  Requires-Dist: zgw-consumers>=0.35.1
34
34
  Requires-Dist: oyaml
35
- Requires-Dist: PyJWT>=2.1.1
35
+ Requires-Dist: PyJWT>=2.10.1
36
36
  Requires-Dist: requests
37
37
  Requires-Dist: coreapi
38
38
  Requires-Dist: ape-pie
@@ -45,10 +45,10 @@ Provides-Extra: drf-extra-fields
45
45
  Requires-Dist: drf-extra-fields>=3.7.0; extra == "drf-extra-fields"
46
46
  Provides-Extra: tests
47
47
  Requires-Dist: psycopg2; extra == "tests"
48
- Requires-Dist: pytest==8.3.5; extra == "tests"
48
+ Requires-Dist: pytest; extra == "tests"
49
49
  Requires-Dist: pytest-django; extra == "tests"
50
50
  Requires-Dist: pytest-dotenv; extra == "tests"
51
- Requires-Dist: pytest-factoryboy; extra == "tests"
51
+ Requires-Dist: pytest-factoryboy>=2.8.0; extra == "tests"
52
52
  Requires-Dist: tox; extra == "tests"
53
53
  Requires-Dist: ruff; extra == "tests"
54
54
  Requires-Dist: requests-mock; extra == "tests"
@@ -76,7 +76,7 @@ Commonground-API-common - Tooling voor RESTful APIs
76
76
  ===================================================
77
77
 
78
78
 
79
- :Version: 2.6.6
79
+ :Version: 2.6.7
80
80
  :Source: https://github.com/maykinmedia/commonground-api-common
81
81
  :PythonVersion: 3.12
82
82
 
@@ -3,7 +3,7 @@ Commonground-API-common - Tooling voor RESTful APIs
3
3
  ===================================================
4
4
 
5
5
 
6
- :Version: 2.6.6
6
+ :Version: 2.6.7
7
7
  :Source: https://github.com/maykinmedia/commonground-api-common
8
8
  :PythonVersion: 3.12
9
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commonground-api-common
3
- Version: 2.6.6
3
+ Version: 2.6.7
4
4
  Summary: Commonground API tooling
5
5
  Home-page: https://github.com/maykinmedia/commonground-api-common
6
6
  Author: Maykin Media, VNG-Realisatie
@@ -32,7 +32,7 @@ Requires-Dist: iso639-lang
32
32
  Requires-Dist: notifications-api-common>=0.3.1
33
33
  Requires-Dist: zgw-consumers>=0.35.1
34
34
  Requires-Dist: oyaml
35
- Requires-Dist: PyJWT>=2.1.1
35
+ Requires-Dist: PyJWT>=2.10.1
36
36
  Requires-Dist: requests
37
37
  Requires-Dist: coreapi
38
38
  Requires-Dist: ape-pie
@@ -45,10 +45,10 @@ Provides-Extra: drf-extra-fields
45
45
  Requires-Dist: drf-extra-fields>=3.7.0; extra == "drf-extra-fields"
46
46
  Provides-Extra: tests
47
47
  Requires-Dist: psycopg2; extra == "tests"
48
- Requires-Dist: pytest==8.3.5; extra == "tests"
48
+ Requires-Dist: pytest; extra == "tests"
49
49
  Requires-Dist: pytest-django; extra == "tests"
50
50
  Requires-Dist: pytest-dotenv; extra == "tests"
51
- Requires-Dist: pytest-factoryboy; extra == "tests"
51
+ Requires-Dist: pytest-factoryboy>=2.8.0; extra == "tests"
52
52
  Requires-Dist: tox; extra == "tests"
53
53
  Requires-Dist: ruff; extra == "tests"
54
54
  Requires-Dist: requests-mock; extra == "tests"
@@ -76,7 +76,7 @@ Commonground-API-common - Tooling voor RESTful APIs
76
76
  ===================================================
77
77
 
78
78
 
79
- :Version: 2.6.6
79
+ :Version: 2.6.7
80
80
  :Source: https://github.com/maykinmedia/commonground-api-common
81
81
  :PythonVersion: 3.12
82
82
 
@@ -10,7 +10,7 @@ iso639-lang
10
10
  notifications-api-common>=0.3.1
11
11
  zgw-consumers>=0.35.1
12
12
  oyaml
13
- PyJWT>=2.1.1
13
+ PyJWT>=2.10.1
14
14
  requests
15
15
  coreapi
16
16
  ape-pie
@@ -44,10 +44,10 @@ django-setup-configuration>=0.7.0
44
44
 
45
45
  [tests]
46
46
  psycopg2
47
- pytest==8.3.5
47
+ pytest
48
48
  pytest-django
49
49
  pytest-dotenv
50
- pytest-factoryboy
50
+ pytest-factoryboy>=2.8.0
51
51
  tox
52
52
  ruff
53
53
  requests-mock
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = commonground-api-common
3
- version = 2.6.6
3
+ version = 2.6.7
4
4
  description = Commonground API tooling
5
5
  long_description = file: README.rst
6
6
  url = https://github.com/maykinmedia/commonground-api-common
@@ -42,7 +42,7 @@ install_requires =
42
42
  notifications-api-common>=0.3.1
43
43
  zgw-consumers>=0.35.1
44
44
  oyaml
45
- PyJWT>=2.1.1
45
+ PyJWT>=2.10.1
46
46
  requests
47
47
  coreapi
48
48
  ape-pie
@@ -71,10 +71,10 @@ drf_extra_fields =
71
71
  drf-extra-fields>=3.7.0
72
72
  tests =
73
73
  psycopg2
74
- pytest==8.3.5 # can be unpinned when pytest-factoryboy is updated
74
+ pytest
75
75
  pytest-django
76
76
  pytest-dotenv
77
- pytest-factoryboy
77
+ pytest-factoryboy>=2.8.0
78
78
  tox
79
79
  ruff
80
80
  requests-mock
@@ -0,0 +1,231 @@
1
+ from datetime import datetime
2
+
3
+ import jwt
4
+ import pytest
5
+ from freezegun import freeze_time
6
+ from rest_framework.exceptions import PermissionDenied
7
+
8
+ from vng_api_common.authorizations.middleware import JWTAuth
9
+ from vng_api_common.models import JWTSecret
10
+
11
+
12
+ @pytest.mark.django_db
13
+ def test_jwt_decode_ok():
14
+ secret = "secret"
15
+ JWTSecret.objects.create(identifier="client", secret=secret)
16
+ timestamp = int(datetime.now().timestamp())
17
+ token = jwt.encode(
18
+ {"client_id": "client", "iat": timestamp}, secret, algorithm="HS256"
19
+ )
20
+
21
+ auth = JWTAuth(token)
22
+
23
+ payload = auth.payload
24
+ assert auth.client_id == "client"
25
+ assert payload == {"client_id": "client", "iat": timestamp}
26
+
27
+
28
+ @pytest.mark.django_db
29
+ def test_jwt_decode_missing_iat():
30
+ secret = "secret"
31
+ JWTSecret.objects.create(identifier="client", secret=secret)
32
+ token = jwt.encode({"client_id": "client"}, secret, algorithm="HS256")
33
+
34
+ auth = JWTAuth(token)
35
+
36
+ with pytest.raises(PermissionDenied):
37
+ auth.payload
38
+
39
+
40
+ @pytest.mark.django_db
41
+ def test_jwt_decode_str_iat():
42
+ JWTSecret.objects.create(identifier="client", secret="secret")
43
+ payload = {
44
+ "client_id": "client",
45
+ "iat": "timestamp",
46
+ }
47
+ token = jwt.encode(payload, "secret", algorithm="HS256")
48
+
49
+ auth = JWTAuth(token)
50
+
51
+ with pytest.raises(PermissionDenied):
52
+ auth.payload
53
+
54
+
55
+ @pytest.mark.django_db
56
+ @freeze_time("2021-08-23T14:20:00")
57
+ def test_nbf_validated():
58
+ JWTSecret.objects.create(identifier="client", secret="secret")
59
+ timestamp = int(datetime.now().timestamp())
60
+ payload = {
61
+ "client_id": "client",
62
+ "iat": timestamp,
63
+ "nbf": timestamp + 1, # 1 second "later" than current time
64
+ }
65
+ token = jwt.encode(payload, "secret", algorithm="HS256")
66
+
67
+ auth = JWTAuth(token)
68
+
69
+ with pytest.raises(PermissionDenied):
70
+ auth.payload
71
+
72
+
73
+ @pytest.mark.django_db
74
+ @freeze_time("2021-08-23T14:20:00")
75
+ def test_nbf_validated_with_leeway(settings):
76
+ settings.TIME_LEEWAY = 3
77
+ JWTSecret.objects.create(identifier="client", secret="secret")
78
+ timestamp = int(datetime.now().timestamp())
79
+ payload = {
80
+ "client_id": "client",
81
+ "iat": timestamp,
82
+ "nbf": timestamp + 1, # 1 second "later" than current time
83
+ }
84
+ token = jwt.encode(payload, "secret", algorithm="HS256")
85
+
86
+ auth = JWTAuth(token)
87
+
88
+ assert auth.payload == payload
89
+
90
+
91
+ @pytest.mark.django_db
92
+ @freeze_time("2021-08-23T14:20:00")
93
+ def test_nbf_validated_with_leeway_not_enough(settings):
94
+ settings.TIME_LEEWAY = 3
95
+ JWTSecret.objects.create(identifier="client", secret="secret")
96
+ timestamp = int(datetime.now().timestamp())
97
+ payload = {
98
+ "client_id": "client",
99
+ "iat": timestamp,
100
+ "nbf": timestamp + 10, # 1 second "later" than current time
101
+ }
102
+ token = jwt.encode(payload, "secret", algorithm="HS256")
103
+
104
+ auth = JWTAuth(token)
105
+
106
+ with pytest.raises(PermissionDenied):
107
+ auth.payload
108
+
109
+
110
+ @pytest.mark.django_db
111
+ @freeze_time("2021-08-23T14:20:00")
112
+ def test_iat_validated():
113
+ """jwt iat in future only logs a warning"""
114
+ JWTSecret.objects.create(identifier="client", secret="secret")
115
+ timestamp = int(datetime.now().timestamp())
116
+ payload = {
117
+ "client_id": "client",
118
+ "iat": timestamp + 1, # 1 second "later" than current time
119
+ }
120
+ token = jwt.encode(payload, "secret", algorithm="HS256")
121
+
122
+ auth = JWTAuth(token)
123
+
124
+ assert auth.payload == payload
125
+
126
+
127
+ @pytest.mark.django_db
128
+ @freeze_time("2021-08-23T14:20:00")
129
+ def test_iat_validated_with_leeway(settings):
130
+ settings.TIME_LEEWAY = 3
131
+ JWTSecret.objects.create(identifier="client", secret="secret")
132
+ timestamp = int(datetime.now().timestamp())
133
+ payload = {
134
+ "client_id": "client",
135
+ "iat": timestamp + 1, # 1 second "later" than current time
136
+ }
137
+ token = jwt.encode(payload, "secret", algorithm="HS256")
138
+
139
+ auth = JWTAuth(token)
140
+
141
+ assert auth.payload == payload
142
+
143
+
144
+ @pytest.mark.django_db
145
+ @freeze_time("2021-08-23T14:20:00")
146
+ def test_iat_validated_with_leeway_not_enough(settings):
147
+ """jwt iat in future only logs a warning"""
148
+ settings.TIME_LEEWAY = 3
149
+ JWTSecret.objects.create(identifier="client", secret="secret")
150
+ timestamp = int(datetime.now().timestamp())
151
+ payload = {
152
+ "client_id": "client",
153
+ "iat": timestamp + 10, # 1 second "later" than current time
154
+ }
155
+ token = jwt.encode(payload, "secret", algorithm="HS256")
156
+
157
+ auth = JWTAuth(token)
158
+
159
+ assert auth.payload == payload
160
+
161
+
162
+ @pytest.mark.django_db
163
+ @freeze_time("2021-08-23T14:20:00")
164
+ def test_exp_ok():
165
+ JWTSecret.objects.create(identifier="client", secret="secret")
166
+ timestamp = int(datetime.now().timestamp())
167
+ payload = {"client_id": "client", "iat": timestamp}
168
+ token = jwt.encode(payload, "secret", algorithm="HS256")
169
+
170
+ auth = JWTAuth(token)
171
+
172
+ assert auth.payload == payload
173
+
174
+
175
+ @pytest.mark.django_db
176
+ @freeze_time("2021-08-23T14:20:00")
177
+ def test_exp_within_exp_setting():
178
+ JWTSecret.objects.create(identifier="client", secret="secret")
179
+ timestamp = int(datetime.now().timestamp())
180
+ payload = {"client_id": "client", "iat": timestamp - 1000}
181
+ token = jwt.encode(payload, "secret", algorithm="HS256")
182
+
183
+ auth = JWTAuth(token)
184
+
185
+ assert auth.payload == payload
186
+
187
+
188
+ @pytest.mark.django_db
189
+ @freeze_time("2021-08-23T14:20:00")
190
+ def test_exp_validated(settings):
191
+ settings.JWT_EXPIRY = 3600
192
+ JWTSecret.objects.create(identifier="client", secret="secret")
193
+ timestamp = int(datetime.now().timestamp())
194
+ payload = {"client_id": "client", "iat": timestamp - 3601}
195
+ token = jwt.encode(payload, "secret", algorithm="HS256")
196
+
197
+ auth = JWTAuth(token)
198
+
199
+ with pytest.raises(PermissionDenied):
200
+ auth.payload
201
+
202
+
203
+ @pytest.mark.django_db
204
+ @freeze_time("2021-08-23T14:20:00")
205
+ def test_exp_validated_with_leeway(settings):
206
+ settings.JWT_EXPIRY = 3600
207
+ settings.TIME_LEEWAY = 5
208
+ JWTSecret.objects.create(identifier="client", secret="secret")
209
+ timestamp = int(datetime.now().timestamp())
210
+ payload = {"client_id": "client", "iat": timestamp - 3603}
211
+ token = jwt.encode(payload, "secret", algorithm="HS256")
212
+
213
+ auth = JWTAuth(token)
214
+
215
+ assert auth.payload == payload
216
+
217
+
218
+ @pytest.mark.django_db
219
+ @freeze_time("2021-08-23T14:20:00")
220
+ def test_exp_validated_with_leeway_not_enough(settings):
221
+ settings.JWT_EXPIRY = 3600
222
+ settings.TIME_LEEWAY = 5
223
+ JWTSecret.objects.create(identifier="client", secret="secret")
224
+ timestamp = int(datetime.now().timestamp())
225
+ payload = {"client_id": "client", "iat": timestamp - 3610}
226
+ token = jwt.encode(payload, "secret", algorithm="HS256")
227
+
228
+ auth = JWTAuth(token)
229
+
230
+ with pytest.raises(PermissionDenied):
231
+ auth.payload
@@ -0,0 +1 @@
1
+ __version__ = "2.6.7"
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import time
2
3
  from typing import Any, Dict, Iterable, List, Optional
3
4
 
4
5
  from django.conf import settings
@@ -147,12 +148,31 @@ class JWTAuth:
147
148
  key,
148
149
  algorithms=["HS256"],
149
150
  leeway=settings.TIME_LEEWAY,
151
+ options={
152
+ "require": ["iat"],
153
+ "verify_iat": False,
154
+ }, # iat is validated in _check_jwt_expiry
150
155
  )
151
156
  except jwt.InvalidSignatureError:
152
157
  logger.exception("Invalid signature - possible payload tampering?")
153
158
  raise PermissionDenied(
154
159
  "Client credentials zijn niet geldig", code="invalid-jwt-signature"
155
160
  )
161
+ except jwt.MissingRequiredClaimError as exc:
162
+ msg = "Missing required {} claim".format(exc.claim)
163
+ logger.exception(msg)
164
+ raise PermissionDenied(
165
+ _(msg),
166
+ code="jwt-missing-{}-claim".format(exc.claim),
167
+ )
168
+ except jwt.PyJWTError as exc:
169
+ logger.exception("Invalid JWT encountered")
170
+ raise PermissionDenied(
171
+ _("JWT did not validate"),
172
+ code="jwt-{}".format(type(exc).__name__.lower()),
173
+ )
174
+
175
+ self._check_jwt_expiry(payload)
156
176
 
157
177
  self._payload = payload
158
178
 
@@ -164,6 +184,37 @@ class JWTAuth:
164
184
  return None
165
185
  return self.payload["client_id"]
166
186
 
187
+ def _check_jwt_expiry(self, payload: Dict[str, Any]) -> None:
188
+ """
189
+ Verify that the token was issued recently enough.
190
+
191
+ The Django settings define how long a JWT is considered to be valid. Adding
192
+ that duration to the issued-at claim determines the upper limit for token
193
+ validity.
194
+ """
195
+ iat = payload.get("iat")
196
+
197
+ try:
198
+ iat = int(iat)
199
+ except ValueError:
200
+ raise PermissionDenied(_("The iat claim must be an integer."))
201
+
202
+ current_timestamp = time.time()
203
+ difference = current_timestamp - iat
204
+
205
+ if difference < -settings.TIME_LEEWAY:
206
+ logger.warning(
207
+ "The JWT used for this request is not valid yet, the `iat` claim is "
208
+ "newer than the current time stamp. You may want to check the clock drift "
209
+ "on the Open Zaak server and/or tweak the `TIME_LEEWAY` setting.",
210
+ extra={"payload": payload},
211
+ )
212
+
213
+ if difference >= (settings.JWT_EXPIRY + settings.TIME_LEEWAY):
214
+ raise PermissionDenied(
215
+ _("The JWT used for this request is expired"), code="jwt-expired"
216
+ )
217
+
167
218
  def filter_vertrouwelijkheidaanduiding(self, base: QuerySet, value) -> QuerySet:
168
219
  if value is None:
169
220
  return base
@@ -9,6 +9,7 @@ __all__ = [
9
9
  "GEMMA_URL_INFORMATIEMODEL",
10
10
  "GEMMA_URL_TEMPLATE",
11
11
  "TIME_LEEWAY",
12
+ "JWT_EXPIRY",
12
13
  "JWT_SPECTACULAR_SETTINGS",
13
14
  "LINK_FETCHER",
14
15
  "NOTIFICATIONS_DISABLED",
@@ -97,4 +98,6 @@ COMMON_SPEC = f"https://raw.githubusercontent.com/{vng_repo}/feature/{vng_branch
97
98
 
98
99
  TIME_LEEWAY = 0 # default in PyJWT
99
100
 
101
+ JWT_EXPIRY = 3600
102
+
100
103
  COMMONGROUND_API_COMMON_GET_DOMAIN = "vng_api_common.utils.get_site_domain"
@@ -26,6 +26,8 @@ class AuthCheckMixin:
26
26
  request_kwargs = request_kwargs or {}
27
27
 
28
28
  with self.subTest(case="JWT missing"):
29
+ self.client.credentials() # explicity clear credentials
30
+
29
31
  response = do_request(url, **request_kwargs)
30
32
 
31
33
  self.assertEqual(
@@ -1,56 +0,0 @@
1
- from datetime import datetime
2
-
3
- import jwt
4
- import pytest
5
- from freezegun import freeze_time
6
- from jwt import ImmatureSignatureError
7
-
8
- from vng_api_common.authorizations.middleware import JWTAuth
9
- from vng_api_common.models import JWTSecret
10
-
11
-
12
- @pytest.mark.django_db
13
- def test_jwt_decode_ok():
14
- secret = "secret"
15
- JWTSecret.objects.create(identifier="client", secret=secret)
16
- token = jwt.encode({"client_id": "client"}, secret, algorithm="HS256")
17
-
18
- auth = JWTAuth(token)
19
-
20
- payload = auth.payload
21
- assert auth.client_id == "client"
22
- assert payload == {"client_id": "client"}
23
-
24
-
25
- @pytest.mark.django_db
26
- @freeze_time("2021-08-23T14:20:00")
27
- def test_nbf_validated():
28
- JWTSecret.objects.create(identifier="client", secret="secret")
29
- payload = {
30
- "client_id": "client",
31
- "nbf": int(datetime.now().timestamp())
32
- + 1, # 1 second "later" than current time
33
- }
34
- token = jwt.encode(payload, "secret", algorithm="HS256")
35
-
36
- auth = JWTAuth(token)
37
-
38
- with pytest.raises(ImmatureSignatureError):
39
- auth.payload
40
-
41
-
42
- @pytest.mark.django_db
43
- @freeze_time("2021-08-23T14:20:00")
44
- def test_nbf_validated_with_leeway(settings):
45
- settings.TIME_LEEWAY = 3
46
- JWTSecret.objects.create(identifier="client", secret="secret")
47
- payload = {
48
- "client_id": "client",
49
- "nbf": int(datetime.now().timestamp())
50
- + 1, # 1 second "later" than current time
51
- }
52
- token = jwt.encode(payload, "secret", algorithm="HS256")
53
-
54
- auth = JWTAuth(token)
55
-
56
- assert auth.payload == payload
@@ -1 +0,0 @@
1
- __version__ = "2.6.6"