OAuth2 goodies for the Djangonauts!
This report presents the forensic synthetic code analysis of django-oauth/django-oauth-toolkit, a Python project with 3,330 GitHub stars. SynthScan v2.0 examined 83,172 lines of code across 247 source files, recording 956 pattern matches distributed across 17 syntactic categories. The overall adjusted score of 14.0 places this repository in the Low AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 956 distinct pattern matches across 17 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_www_authenticate.py | 24 | def test_bare_bearer_when_nothing_to_advertise(self): | CODE |
| LOW | tests/test_www_authenticate.py | 28 | def test_includes_error_and_resource_metadata(self): | CODE |
| LOW⚡ | tests/test_www_authenticate.py | 42 | def test_explicit_resource_metadata_url_overrides_default(self): | CODE |
| LOW⚡ | tests/test_www_authenticate.py | 50 | def test_explicit_none_omits_resource_metadata(self): | CODE |
| LOW⚡ | tests/test_www_authenticate.py | 55 | def test_quoted_string_values_are_escaped(self): | CODE |
| LOW | tests/test_oauth2_provider_middleware.py | 32 | def test_malformed_bearer_header_no_token(self): | CODE |
| LOW | tests/test_oauth2_provider_middleware.py | 42 | def test_malformed_bearer_header_empty_token(self): | CODE |
| LOW⚡ | tests/test_oauth2_provider_middleware.py | 74 | def test_invalid_bearer_token(self): | CODE |
| LOW⚡ | tests/test_oauth2_provider_middleware.py | 84 | def test_no_authorization_header(self): | CODE |
| LOW⚡ | tests/test_oauth2_provider_middleware.py | 93 | def test_non_bearer_authorization_header(self): | CODE |
| LOW | tests/test_oauth2_provider_middleware.py | 113 | def test_case_insensitive_bearer_scheme(self): | CODE |
| LOW | tests/test_oauth2_provider_middleware.py | 126 | def test_scheme_starting_with_bearer_is_rejected(self): | CODE |
| LOW | tests/test_oauth2_provider_middleware.py | 136 | def test_whitespace_variations(self): | CODE |
| LOW | tests/test_admin.py | 37 | def test_mask_credential_hides_the_secret(): | CODE |
| LOW | tests/test_admin.py | 56 | def _assert_hidden_on_change_form(admin_class, model, field, masked_field): | CODE |
| LOW | tests/test_admin.py | 70 | def test_credential_admins_disable_add(): | CODE |
| LOW | tests/test_admin.py | 83 | def test_admin_overrides_preserve_subclass_config(): | CODE |
| LOW⚡ | tests/test_admin.py | 104 | def _assert_searchable_by_app_and_user(admin_class): | CODE |
| LOW⚡ | tests/test_admin.py | 112 | def test_access_token_admin_does_not_expose_token(): | CODE |
| LOW⚡ | tests/test_admin.py | 119 | def test_refresh_token_admin_does_not_expose_token(): | CODE |
| LOW⚡ | tests/test_admin.py | 126 | def test_grant_admin_does_not_expose_code(): | CODE |
| LOW⚡ | tests/test_admin.py | 133 | def test_id_token_admin_searchable_by_app_and_user(): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 136 | def test_authenticate_basic_auth_hashed_secret(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 141 | def test_authenticate_basic_auth_unhashed_secret(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 150 | def test_authenticate_basic_auth_default_encoding(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 155 | def test_authenticate_basic_auth_wrong_client_id(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 160 | def test_authenticate_basic_auth_wrong_client_secret(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 165 | def test_authenticate_basic_auth_wrong_client_secret_not_logged(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 173 | def test_authenticate_request_body_wrong_client_secret_not_logged(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 181 | def test_authenticate_basic_auth_undecodable_credentials_not_logged(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 223 | def test_authenticate_basic_auth_public_app_with_device_code(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 229 | def test_authenticate_check_secret(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 236 | def test_authenticate_client_id(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 239 | def test_authenticate_client_id_fail(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 245 | def test_client_authentication_required(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 259 | def test_load_application_loads_client_id_when_request_has_no_client(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 264 | def test_load_application_uses_cached_when_request_has_valid_client_matching_client_id(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 270 | def test_load_application_succeeds_when_request_has_invalid_client_valid_client_id(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 276 | def test_load_application_overwrites_client_on_client_id_mismatch(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 291 | def test_load_application_returns_none_when_client_not_usable_cached(self, mock_is_usable): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 299 | def test_load_application_returns_none_when_client_not_usable_db_lookup(self, mock_is_usable): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 306 | def test_rotate_refresh_token__is_true(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 309 | def test_validate_refresh_token_with_long_token(self): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 734 | def test_validate_id_token_expired_jwt(oauth2_settings, mocker, oidc_tokens): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 742 | def test_validate_id_token_no_token(oauth2_settings, mocker): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 750 | def test_validate_id_token_app_removed(oauth2_settings, mocker, oidc_tokens): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 759 | def test_validate_id_token_bad_token_no_aud(oauth2_settings, mocker, oidc_key): | CODE |
| LOW⚡ | tests/test_oauth2_validators.py | 768 | def test_get_id_token_dictionary_auth_time_naive_last_login_is_utc(oauth2_settings, rf): | CODE |
| LOW | tests/test_oauth2_validators.py | 90 | def test_authenticate_request_body(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 112 | def test_authenticate_request_body_unhashed_secret(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 329 | def test_validate_refresh_token_with_unknown_token(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 333 | def test_revoke_token_with_long_refresh_token(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 346 | def test_validate_refresh_token_prefers_unrevoked_row_over_revoked_duplicate(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 366 | def test_revoke_token_with_duplicate_refresh_token_checksums(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 385 | def test_save_bearer_token__without_user__raises_fatal_client(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 391 | def test_save_bearer_token__with_existing_tokens__does_not_create_new_tokens(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 420 | def test_save_bearer_token__checks_to_rotate_tokens(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 444 | def test_save_bearer_token__with_new_token__creates_new_tokens(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 459 | def test_save_bearer_token__with_new_token_equal_to_existing_token__revokes_old_tokens(self): | CODE |
| LOW | tests/test_oauth2_validators.py | 486 | def test_save_bearer_token__with_no_refresh_token__creates_new_access_token_only(self): | CODE |
| 673 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_device.py | 256 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_device.py | 258 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_device.py | 268 | # ------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_device.py | 270 | # ------------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 139 | # ----------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 142 | # ----------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 197 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 200 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 242 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_device.py | 245 | # -------------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 344 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 346 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 443 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 445 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 777 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_dcr_views.py | 779 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 22 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 24 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 48 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 50 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 369 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 372 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 872 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 874 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 898 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 900 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/e2e/conftest.py | 101 | # -------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/e2e/conftest.py | 103 | # -------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL⚡ | tests/test_dcr_views.py | 337 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL⚡ | tests/test_resource_validators.py | 436 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL⚡ | tests/test_resource_validators.py | 442 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | oauth2_provider/models.py | 244 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | oauth2_provider/validators.py | 4 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | …uth2_provider/management/commands/createapplication.py | 1 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | oauth2_provider/views/device.py | 5 | from django.core.exceptions import ValidationError | CODE |
| CRITICAL | oauth2_provider/views/dynamic_client_registration.py | 13 | from django.core.exceptions import ValidationError | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/test_implicit.py | 0 | test for default redirect uri if omitted from query string with response_type: code | STRING |
| HIGH | tests/test_authorization_code.py | 0 | test for default redirect uri if omitted from query string with response_type: code | STRING |
| HIGH | tests/test_hybrid.py | 0 | test for default redirect uri if omitted from query string with response_type: code | STRING |
| HIGH | tests/test_implicit.py | 0 | test error when passing a forbidden redirect_uri in query string with response_type: code | STRING |
| HIGH | tests/test_authorization_code.py | 0 | test error when passing a forbidden redirect_uri in query string with response_type: code | STRING |
| HIGH | tests/test_hybrid.py | 0 | test error when passing a forbidden redirect_uri in query string with response_type: code | STRING |
| HIGH | tests/test_implicit.py | 0 | test authorization code is given for an allowed request with response_type: code | STRING |
| HIGH | tests/test_authorization_code.py | 0 | test authorization code is given for an allowed request with response_type: code | STRING |
| HIGH | tests/test_hybrid.py | 0 | test authorization code is given for an allowed request with response_type: code | STRING |
| HIGH | tests/test_implicit.py | 0 | if application.skip_authorization = true, should skip the authorization page. | STRING |
| HIGH | tests/test_authorization_code.py | 0 | if application.skip_authorization = true, should skip the authorization page. | STRING |
| HIGH | tests/test_hybrid.py | 0 | if application.skip_authorization = true, should skip the authorization page. | STRING |
| HIGH | tests/test_implicit.py | 0 | tests that a redirection uri with query string is allowed and query string is retained on redirection. see https://rfc-e | STRING |
| HIGH | tests/test_authorization_code.py | 0 | tests that a redirection uri with query string is allowed and query string is retained on redirection. see https://rfc-e | STRING |
| HIGH | tests/test_hybrid.py | 0 | tests that a redirection uri with query string is allowed and query string is retained on redirection. see https://rfc-e | STRING |
| HIGH | tests/test_implicit.py | 0 | tests that a redirection uri is matched using scheme + netloc + path | STRING |
| HIGH | tests/test_authorization_code.py | 0 | tests that a redirection uri is matched using scheme + netloc + path | STRING |
| HIGH | tests/test_hybrid.py | 0 | tests that a redirection uri is matched using scheme + netloc + path | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/mysql_settings.py | 5 | CODE | |
| LOW | tests/settings_swapped.py | 1 | CODE | |
| LOW | tests/multi_db_settings.py | 3 | CODE | |
| LOW | tests/mysql_pr_settings.py | 5 | CODE | |
| LOW | tests/postgres_mig_settings.py | 3 | CODE | |
| LOW | tests/multi_db_settings_invalid_token_configuration.py | 1 | CODE | |
| LOW | tests/mysql_pr_mig_settings.py | 5 | CODE | |
| LOW | tests/postgres_pr_settings.py | 3 | CODE | |
| LOW | tests/postgres_settings.py | 3 | CODE | |
| LOW | tests/mysql_mig_settings.py | 5 | CODE | |
| LOW | tests/postgres_pr_mig_settings.py | 3 | CODE | |
| LOW | oauth2_provider/compat.py | 8 | CODE | |
| LOW | oauth2_provider/apps.py | 10 | CODE | |
| LOW | oauth2_provider/contrib/ninja/__init__.py | 1 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 2 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 2 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 2 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 2 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 2 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 3 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 10 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 21 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 22 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 22 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 23 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 23 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 23 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 23 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 24 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 24 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 25 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 25 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 25 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 25 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 26 | CODE | |
| LOW | oauth2_provider/views/__init__.py | 26 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_rfc8707_integration.py | 96 | # Step 3: Verify access token has resource binding (JSON array format) | COMMENT |
| LOW⚡ | tests/test_rfc8707_integration.py | 101 | # Step 4: Verify audience validation | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 45 | # Step 1: Authorization request with resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 78 | # Step 2: Token request with resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 396 | # Step 1: Authorization request with limited resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 411 | # Step 2: Token request trying to escalate to unauthorized resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 462 | # Step 1: Authorization with multiple resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 479 | # Step 2: Token request WITHOUT resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 534 | # Step 1: Authorization with three resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 553 | # Step 2: Token request repeating the resource parameter to narrow to two | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 606 | # Step 1: Authorization with a single resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 620 | # Step 2: Token request repeating resource params, one outside the grant | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 670 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 685 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 712 | # Step 3: Use refresh token to get new access token | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 726 | # Step 4: Verify new access token preserves resource from refresh token | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 762 | # Step 1: Authorization with specific resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 782 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 805 | # Step 3: Attempt refresh with unauthorized resource - should fail | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 822 | # Step 4: Get fresh token to test narrowing (previous refresh may have consumed token) | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 840 | # Step 5: Refresh with subset (resource1 only) - should succeed | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 888 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 903 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 924 | # Step 3: Use refresh token (should rotate and create new refresh token) | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 977 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 991 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 1008 | # Step 3: Refresh (non-rotating — same refresh token reused, access token updated in place) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_rfc8707_integration.py | 96 | # Step 3: Verify access token has resource binding (JSON array format) | COMMENT |
| LOW⚡ | tests/test_rfc8707_integration.py | 101 | # Step 4: Verify audience validation | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 45 | # Step 1: Authorization request with resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 78 | # Step 2: Token request with resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 396 | # Step 1: Authorization request with limited resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 411 | # Step 2: Token request trying to escalate to unauthorized resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 462 | # Step 1: Authorization with multiple resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 479 | # Step 2: Token request WITHOUT resource parameter | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 534 | # Step 1: Authorization with three resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 553 | # Step 2: Token request repeating the resource parameter to narrow to two | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 606 | # Step 1: Authorization with a single resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 620 | # Step 2: Token request repeating resource params, one outside the grant | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 670 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 685 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 712 | # Step 3: Use refresh token to get new access token | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 726 | # Step 4: Verify new access token preserves resource from refresh token | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 762 | # Step 1: Authorization with specific resources | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 782 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 805 | # Step 3: Attempt refresh with unauthorized resource - should fail | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 822 | # Step 4: Get fresh token to test narrowing (previous refresh may have consumed token) | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 840 | # Step 5: Refresh with subset (resource1 only) - should succeed | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 888 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 903 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 924 | # Step 3: Use refresh token (should rotate and create new refresh token) | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 977 | # Step 1: Authorization with resource | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 991 | # Step 2: Exchange code for tokens | COMMENT |
| LOW | tests/test_rfc8707_integration.py | 1008 | # Step 3: Refresh (non-rotating — same refresh token reused, access token updated in place) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_application_views.py | 434 | cls.admin_user = UserModel.objects.create_superuser("admin_user", "admin@example.com", "123456") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 187 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 207 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 236 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 259 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 272 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW⚡ | tests/test_rest_framework.py | 463 | auth = self._create_authorization_header("fake-token") | CODE |
| LOW | tests/test_settings.py | 233 | admin_user = UserModel.objects.create_superuser("admin", "admin@example.com", "password") | CODE |
| LOW | rfcs/openid-connect-core-1_0.txt | 3371 | "name": "Jane Doe", | CODE |
| LOW | rfcs/openid-connect-core-1_0.txt | 3796 | "name": "Jane Doe", | CODE |
| LOW | rfcs/openid-connect-core-1_0.txt | 3936 | "name": "Jane Doe", | CODE |
| LOW | rfcs/openid-connect-core-1_0.txt | 3998 | "name": "Jane Doe", | CODE |
| LOW | rfcs/openid-connect-core-1_0.txt | 7742 | "name": "Jane Doe", | CODE |
| LOW | rfcs/openid-connect-discovery-1_0.txt | 650 | Such an example is "acct:joe%40example.com@example.org". End-Users | CODE |
| LOW | rfcs/openid-connect-discovery-1_0.txt | 651 | MAY input values like "joe@example.com@example.org" to initiate | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pyproject.toml | 101 | COMMENT | |
| LOW | tox.ini | 1 | [tox] | COMMENT |
| LOW | docker-compose.yml | 21 | condition: service_completed_successfully | COMMENT |
| LOW | docs/conf.py | 1 | # Django OAuth Toolkit documentation build configuration file, created by | COMMENT |
| LOW | docs/conf.py | 81 | # There are two options for replacing |today|: either, you set today to some | COMMENT |
| LOW | docs/conf.py | 121 | COMMENT | |
| LOW | docs/conf.py | 141 | # A shorter title for the navigation bar. Default is the same as html_title. | COMMENT |
| LOW | docs/conf.py | 161 | COMMENT | |
| LOW | docs/conf.py | 181 | COMMENT | |
| LOW | docs/conf.py | 221 | # the title page. | COMMENT |
| LOW | oauth2_provider/models.py | 1061 | continue | COMMENT |
| LOW | …provider/static/oauth2_provider/js/application_form.js | 1 | // Live client-secret UX for the Application form. | COMMENT |
| LOW | oauth2_provider/views/base.py | 421 | the login flow with the prompt consumed, so the user is not sent to | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_oauth2_provider_middleware.py | 54 | # Create a valid access token | COMMENT |
| MEDIUM | tests/test_application_views.py | 35 | # Create a registration view and tests that the model form is bound | COMMENT |
| MEDIUM | tests/test_dcr_views.py | 615 | # Create a second application with its own token | COMMENT |
| MEDIUM | docs/conf.py | 4 | # This file is execfile()d with the current directory set to its containing dir. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/e2e/conftest.py | 70 | CODE | |
| LOW | tests/e2e/compliance.py | 110 | CODE | |
| LOW | oauth2_provider/oauth2_validators.py | 239 | CODE | |
| LOW | oauth2_provider/oauth2_validators.py | 322 | CODE | |
| LOW | oauth2_provider/oauth2_validators.py | 671 | CODE | |
| LOW | oauth2_provider/oauth2_validators.py | 771 | CODE | |
| LOW | oauth2_provider/oauth2_validators.py | 855 | CODE | |
| LOW | oauth2_provider/settings.py | 273 | CODE | |
| LOW | oauth2_provider/contrib/rest_framework/permissions.py | 146 | CODE | |
| LOW | oauth2_provider/views/base.py | 179 | CODE | |
| LOW | oauth2_provider/views/base.py | 513 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/multi_db_settings.py | 15 | # Keep ``default`` concrete so Django's test harness can use standard multi-db | COMMENT |
| LOW | tests/test_device.py | 1040 | # values take effect without wiping the overrides we just set above. | COMMENT |
| MEDIUM | tests/app/idp/idp/settings.py | 269 | # log oauth2_provider issues to facilitate troubleshooting | COMMENT |
| LOW | tests/app/idp/idp/oauth.py | 9 | # the way we're using it, so we just use a lambda that returns None | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | oauth2_provider/settings.py | 277 | # Check if present in user settings | COMMENT |
| LOW | oauth2_provider/decorators.py | 121 | # Check if provided scopes are acceptable | COMMENT |
| LOW | oauth2_provider/decorators.py | 131 | # Check if method is safe. Build a fresh list per request so the read/write | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/e2e/browser_rp/conftest.py | 59 | except Exception as exc: # pragma: no cover - environment guard | CODE |
| LOW | tests/e2e/browser_rp/conftest.py | 81 | except Exception as exc: # pragma: no cover - environment guard | CODE |
| LOW | tests/e2e/browser_rp/conftest.py | 94 | except Exception as exc: # pragma: no cover - environment guard | CODE |
| LOW | tests/e2e/helpers/browser.py | 27 | except Exception as exc: # Playwright TimeoutError (or the check's own AssertionError) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | oauth2_provider/compat.py | 15 | __all__ = ["login_not_required"] | CODE |
| LOW | oauth2_provider/models.py | 31 | logger = logging.getLogger(__name__) | CODE |
| LOW | oauth2_provider/utils.py | 107 | def set_oauthlib_user_to_device_request_user(request: Request) -> None: | CODE |
| LOW | oauth2_provider/contrib/ninja/__init__.py | 4 | __all__ = ["HttpOAuth2"] | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | tests/test_oidc_views.py | 170 | """Required OIDC endpoints must fail fast, not emit null, when unreversible.""" | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/e2e/helpers/oauth_client.py | 147 | CODE | |
| LOW | tests/e2e/helpers/idp_process.py | 53 | CODE | |
| LOW | oauth2_provider/middleware.py | 65 | CODE |