fix: clamp SCIM pagination args instead of rejecting them (#21577)

RFC 7644 §3.4.2.4 specifies that out-of-range pagination values MUST be
clamped, not rejected. The previous implementation used FastAPI Query
constraints (ge=1, le=100) which caused a 422 response for values like
startIndex=0 or count=9999 — violating the spec.

For both /Users and /Groups:
- startIndex < 1 is now treated as 1 (spec: "SHALL be interpreted as 1")
- count < 0 is now treated as 0 (spec: "SHALL be interpreted as 0")
- count > 100 is clamped to the server maximum of 100

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Monteith
2026-02-19 15:08:42 -06:00
committed by GitHub
co-authored by Claude Sonnet 4.6
parent 2f1344d619
commit 27c76c677a
+13 -4
View File
@@ -523,13 +523,17 @@ async def get_schemas():
@router.get("/Users", response_model=SCIMListResponse)
async def get_users(
request: Request,
startIndex: int = Query(1, ge=1),
count: int = Query(20, ge=1, le=100),
startIndex: int = Query(1),
count: int = Query(20),
filter: Optional[str] = None,
_: bool = Depends(get_scim_auth),
db: Session = Depends(get_session),
):
"""List SCIM Users"""
# Clamp per SCIM 2.0 spec (RFC 7644 §3.4.2.4):
# startIndex < 1 SHALL be treated as 1; count < 0 SHALL be treated as 0.
startIndex = max(1, startIndex)
count = max(0, min(100, count))
skip = startIndex - 1
limit = count
@@ -794,13 +798,18 @@ async def delete_user(
@router.get("/Groups", response_model=SCIMListResponse)
async def get_groups(
request: Request,
startIndex: int = Query(1, ge=1),
count: int = Query(20, ge=1, le=100),
startIndex: int = Query(1),
count: int = Query(20),
filter: Optional[str] = None,
_: bool = Depends(get_scim_auth),
db: Session = Depends(get_session),
):
"""List SCIM Groups"""
# Clamp per SCIM 2.0 spec (RFC 7644 §3.4.2.4):
# startIndex < 1 SHALL be treated as 1; count < 0 SHALL be treated as 0.
startIndex = max(1, startIndex)
count = max(0, min(100, count))
# Get all groups
groups_list = Groups.get_all_groups(db=db)