feat(auth): add configurable scope enforcement with scope_mode option#625
feat(auth): add configurable scope enforcement with scope_mode option#625
scope_mode option#625Conversation
✅ Docs preview readyThe preview is ready to be viewed. View the preview File Changes 0 new, 2 changed, 0 removedBuild ID: fcc2076227452105dc02cddf URL: https://www.apollographql.com/docs/deploy-preview/fcc2076227452105dc02cddf |
|
✅ Changeset file added - thank you! |
| ScopeMode::Disabled => true, | ||
| ScopeMode::RequireAll => required.iter().all(|req| present.contains(req)), | ||
| ScopeMode::RequireAny => required.iter().any(|req| present.contains(req)), | ||
| } |
There was a problem hiding this comment.
[Consider] In the test helper is_sufficient at lines 450-455, the empty scopes case for RequireAny returns false, which is inconsistent with the behavior for RequireAll and Disabled.
This is tested in scope_mode_empty_scopes_is_sufficient_for_all_modes (line 485), which explicitly expects RequireAny to return false when required scopes are empty. However, this seems counterintuitive - if no scopes are required, shouldn't any token be considered sufficient?
Consider whether the current behavior is intentional or if RequireAny with empty required scopes should return true (similar to RequireAll). If the current behavior is intentional, add a comment explaining why RequireAny with empty scopes fails while RequireAll succeeds.
See Chapter 1.6 for guidance on clarifying non-obvious behavior with comments.
| ); | ||
| tracing::Span::current().record("reason", "insufficient_scope"); | ||
| tracing::Span::current().record("status_code", StatusCode::FORBIDDEN.as_u16()); | ||
| // NOTE: WWW-Authenticate lists all configured scopes per RFC 6750. |
There was a problem hiding this comment.
[Consider] The WWW-Authenticate header comment at lines 327-330 explains that the header lists all configured scopes even in require_any mode, which may be confusing to clients.
Per RFC 6750 section 3, the scope attribute in WWW-Authenticate indicates the required scope of the access token. When scope_mode is require_any, listing all scopes suggests the token needs all of them, which is misleading.
Consider one of these approaches:
- For
require_anymode, only include the scopes that are actually missing (none of the configured scopes are present) - Add a custom parameter to the header (e.g.,
scope_mode="require_any") to clarify the matching strategy - If maintaining current behavior, ensure this is clearly documented in the auth.mdx file
The current implementation is functionally correct but may cause confusion for API consumers debugging 403 responses.
Review SummaryThis PR adds configurable scope enforcement via the new Findings
Test Coverage AssessmentTest coverage is comprehensive:
The tests follow Apollo's best practices from Chapter 5:
Final RecommendationApprove with suggestions - The implementation is solid and ready to merge. The two "Consider" items are minor edge cases around clarity and documentation rather than correctness issues. Reviewed by Claude Code Sonnet 4.5 |
scope_mode option
Co-authored-by: Parker <parker.ragland@apollographql.com>
Co-authored-by: Parker <parker.ragland@apollographql.com>
Co-authored-by: Parker <parker.ragland@apollographql.com>
Co-authored-by: Parker <parker.ragland@apollographql.com>
Follow-up ReviewThe documentation improvements look good. The PR is ready to merge - the implementation is solid and test coverage is comprehensive. The two [Consider] items from my previous review remain valid but are minor clarifications rather than blocking issues:
Both are well-documented in the code, so these are optional enhancements rather than required changes. Reviewed by Claude Code Sonnet 4.5 |
Follow-up ReviewThe documentation improvements look excellent - they clearly explain the three scope modes with concrete examples and appropriate caution notes. The implementation remains solid with comprehensive test coverage. The two [Consider] items from my previous review are minor clarifications rather than blocking issues:
Both items are optional enhancements - the current implementation is correct and ready to merge. Final RecommendationApprove - Ready to merge. Reviewed by Claude Code Sonnet 4.5 |
...pe_enforcement_via_scope_mode_to_suport_flexible_matching_strategies_require_any_disabled.md
Outdated
Show resolved
Hide resolved
…o_suport_flexible_matching_strategies_require_any_disabled.md Co-authored-by: Dale Seo <5466341+DaleSeo@users.noreply.github.com>
Final ReviewThis PR successfully implements configurable scope enforcement via the SummaryThe changes replace the previous fail-closed behavior (requiring all scopes) with three flexible modes:
Implementation QualityStrengths:
Test Coverage:
Notes from Previous ReviewsThe two [Consider] items I mentioned earlier remain valid but are minor clarifications:
Both items are optional enhancements - the current implementation is correct. Final RecommendationApprove - Ready to merge. The implementation follows Apollo's Rust best practices, has excellent test coverage, and the documentation clearly explains the security implications of each mode. Reviewed by Claude Code Sonnet 4.5 |
This PR introduces configurable scope enforcement with a new
scope_modeconfig option. This replaces the previous "fail-closed" logic where a token required all configured scopes to pass validation.The new
scope_modesupports three strategies:require_all(default): the token must have all configured scopesrequire_any: token must have at least one of the configured scopesdisabled: this skips scope enforcement entirelyThis change addresses requests for more flexible scope matching and explicit support for downstream authorization.
Changes
ScopeModeenum toauth.rswithDisabled,RequireAll, andRequireAnyvariantsoauth_validatemiddleware to enforce logic based on the selected modescope_modeisdisabled