| Internet-Draft | SCIM Attribute Pagination | August 2026 |
| Kushwaha | Expires 3 March 2027 | [Page] |
[RFC7643] defines Group.members with the returned: default characteristic, so a conformant service provider is required to return the attribute in response to GET /Groups/{id}. [RFC7644] defines no bound on the number of values that attribute may contain. A service provider holding a group with millions of members therefore has no conformant and interoperable way to answer a request that a client is entitled to make. In practice providers diverge: they truncate silently, reject the request, omit the attribute, or fail. A client cannot discover in advance which behavior it will encounter.¶
This document defines that missing behavior. It specifies discovery so a client can learn how a service provider treats a high-cardinality attribute, a bounded response with a defined continuation contract, and rules preventing a partial representation from being mistaken for complete resource state.¶
The mechanism has two forms. A request for one resource returns a bounded page of one protected multi-valued attribute with an opaque cursor when more values exist. A collection search returns parent resources without loading protected attributes, each carrying an authoritative link for retrieving that attribute. The attribute remains part of its parent resource; this document does not create a top-level resource for each attribute value, and it is not a substitute for doing so where independent relationship lifecycle or cross-collection query is required (Section 16.4).¶
Although the mechanism is defined generally and applies to any complex multi-valued attribute a service provider designates as protected, the attributes that reach problematic sizes in deployed SCIM services are predominantly Group.members and User.groups among those defined in [RFC7643], together with implementation-specific assignment attributes (Section 3).¶
This document updates [RFC7643] and [RFC7644]. It adds attributes to existing structures defined by those documents and defines attribute-return behavior that replaces the requirements of Section 3.9 of [RFC7644] within a negotiated scope. It does not change the behavior of deployments that do not implement it: the modified attribute-selection behavior described in Section 4 applies only between a service provider that has advertised this capability and a client for which deferred retrieval has been established through the negotiation mechanisms defined in this document. It defines discovery metadata, the attributeCount and attributeCursor query parameters, response metadata, processing and compatibility rules, mutation safety, error handling, cursor security, and operational limits.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 3 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
[RFC7644] supports pagination of resources in a SCIM ListResponse. [RFC9865] adds cursor-based pagination for those resource collections. Neither mechanism bounds the values contained inside one resource.¶
[RFC7643] defines Group.members with returned: default. A client may therefore issue:¶
and a conformant service provider is required to return the members attribute. [RFC7644] places no bound on how many values that attribute contains, and defines no mechanism by which a service provider may return fewer than all of them while remaining conformant.¶
For a group with two million members this leaves a service provider with no correct option. Every available behavior is either non-conformant or operationally unsafe:¶
| Behavior | Problem |
|---|---|
| Return all values | Unbounded database work, heap consumption, serialization cost, and request duration (Section 1.2) |
| Truncate silently | Non-conformant, and indistinguishable to the client from complete state |
| Return an empty array | Non-conformant, and destructive if the client subsequently issues PUT |
| Omit the attribute | Non-conformant under Section 3.9 of [RFC7644] |
| Reject the request | Conformant client receives an error for a valid request, with no defined remedy |
Deployed service providers do all of these. A client has no way to determine which it will encounter, and no defined recovery when it encounters one. This is an interoperability defect in the protocol rather than a deficiency in any implementation.¶
Approaches that expose memberships through a separate address — an inverse filter over the counterpart resource (Section 16.8), a relationship resource type, or a per-attribute sub-resource endpoint (Section 16.4) — give clients good ways to enumerate memberships. None of them closes this gap, because Group.members remains defined with returned: default regardless of what other retrieval paths a provider offers, and clients continue to request it.¶
The same problem occurs for implementation-specific complex multi-valued attributes, particularly assignment attributes such as application grants and accounts, which represent access relationships rather than descriptive properties and grow with the size of the deployment rather than with the size of an individual record.¶
The problem has two distinct forms:¶
A collection search can return many parent resources, each of which can trigger an unbounded child or reference-derived query.¶
A resource-by-identifier request can return one attribute containing an unbounded number of values.¶
Applying a page size only after discovering or hydrating all values does not protect the system. The page boundary has to be applied to the first query that discovers the attribute values.¶
This document therefore defines two complementary behaviors:¶
Deferred collection retrieval: a collection search returns parent resources without loading protected multi-valued attributes. Each affected resource contains metadata with a link to retrieve the attribute from that parent.¶
Cursor-paged resource retrieval: a request for one parent and one protected multi-valued attribute returns a bounded first page and an opaque cursor when more values exist.¶
This model keeps the multi-valued attribute on its parent resource. It avoids introducing a new top-level resource type and avoids maintaining two independently mutable representations of the same relationship.¶
Attribute pagination does not imply snapshot isolation. Unless a service provider advertises stronger consistency, clients MUST tolerate values being added, removed, or reordered while a traversal is in progress.¶
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14 when, and only when, they appear in all capitals.¶
Attribute page¶
A bounded subset of the values of one multi-valued attribute on one SCIM resource.¶
Attribute cursor¶
An opaque continuation value issued by the service provider for retrieving another page of the same attribute.¶
Protected attribute¶
A complex or primitive multi-valued attribute for which the service provider advertises attribute pagination and may enforce deferred or bounded retrieval.¶
Deferred attribute¶
A selected protected attribute whose values were intentionally not loaded into the current representation. Its attributePagination entry has state deferred and contains a firstPage URI-reference.¶
Hydrated attribute¶
A protected attribute for which a bounded page of values is present in the current representation. Its attributePagination entry has state page.¶
Effective page size¶
The maximum number of values that the service provider will attempt to return after applying the requested attributeCount, provider defaults, maximums, authorization policy, response-byte budgets, and other safety limits.¶
Reference-derived attribute¶
A multi-valued attribute whose values are computed from, or hydrated using, another persisted resource or relationship rather than stored directly on the parent resource.¶
Compatibility profile¶
A client, tenant, endpoint, or deployment policy establishing whether automatic deferred retrieval can be used for requests that do not explicitly contain attributeCount or attributeCursor.¶
This specification has the following goals:¶
Bound database, memory, serialization, and response-size work before hydration.¶
Support both directly persisted and reference-derived multi-valued attributes.¶
Keep each attribute value within the existing parent-resource contract.¶
Permit more than one protected attribute to be advertised in a collection result without loading any of them.¶
Hydrate at most one protected attribute in a single response.¶
Use opaque, context-bound cursor continuation rather than increasing offsets.¶
Preserve a controlled migration path for existing SCIM clients.¶
This version does not define:¶
Previous-page traversal.¶
Client-defined filtering or sorting within a multi-valued attribute.¶
A top-level resource type for an attribute value or relationship.¶
Snapshot isolation across pages.¶
Mutation of a partial attribute page.¶
Attribute cursors spanning more than one parent resource or more than one attribute.¶
Root-resource pagination and attribute pagination are independent. A resource collection MAY use startIndex pagination from [RFC7644] or cursor pagination from [RFC9865] while protected attributes inside each returned resource remain deferred.¶
Section 3.9 of [RFC7644] requires a resource to contain attributes explicitly selected by the attributes query parameter. [RFC7643] also defines Group.members as returned: default. Omitting such values is therefore a protocol behavior change, not a transparent implementation optimization.¶
This document therefore updates [RFC7643] and [RFC7644]. It updates [RFC7643] by adding attributes to existing structures, and it updates [RFC7644] by defining attribute-return rules that replace those of Section 3.9 for parties that have established this capability. This mirrors [RFC9865], which likewise updates [RFC7643] and [RFC7644] while remaining an opt-in capability discovered through ServiceProviderConfig.¶
Updating those documents does not make this behavior mandatory or unconditional. A service provider and client that have not established this capability retain unmodified [RFC7644] semantics, and a client that never negotiates deferred retrieval cannot observe any change. The negotiation mechanisms that establish the capability are defined in Sections 4.1 and 4.2.¶
Between parties for which deferred mode has been established, the following rules replace the attribute-return requirements of [RFC7644] Section 3.9:¶
A selected protected attribute MAY be omitted from a returned resource when an attributePagination entry for that exact attribute is included with state deferred.¶
The omission MUST NOT be represented as an empty array or null, because either value can be mistaken for complete attribute state.¶
The firstPage URI-reference in the metadata is the authoritative way to retrieve the omitted values.¶
An attribute with schema characteristic returned: always MUST NOT be deferred.¶
An attribute excluded by excludedAttributes MUST be omitted normally and MUST NOT produce an attributePagination entry.¶
A service provider MAY support either or both of these modes:¶
Explicit mode¶
Attribute pagination is used only when the request contains attributeCount or attributeCursor. Other requests retain [RFC7644] behavior, subject to existing provider limits.¶
Automatic deferred mode¶
The service provider can defer protected attributes from collection results and apply a default page size to a resource-by-identifier request even when attributeCount is absent. This is analogous to [RFC9865] permitting a service provider to choose cursor pagination and a default page size when a resource-collection request omits cursor and count.¶
A new service provider MAY advertise automatic deferred mode as its default. An existing service provider adding this extension SHOULD preserve its legacy behavior until a compatibility profile has been established for affected clients or tenants.¶
ServiceProviderConfig advertisement alone does not prove that every existing client understands a partial attribute representation. Existing deployments SHOULD use a staged tenant or client profile, the in-band preference below, an out-of-band capability agreement, or another deployment-specific negotiation mechanism before enabling automatic deferred mode.¶
An extension-aware client MAY explicitly opt in by sending this [RFC7240] preference:¶
A provider that applies the preference SHOULD return:¶
The absence of this preference does not request unsafe or unbounded behavior. A provider MAY still apply deferred mode through its advertised default and compatibility profile. An existing provider that has not established such a profile SHOULD retain legacy behavior or fail closed as described below.¶
If a provider cannot safely return an unbounded attribute and automatic deferred behavior has not been established for the client, it SHOULD fail closed with attributePaginationRequired rather than return a silently truncated representation or attempt unsafe unbounded retrieval.¶
This specification does not claim that automatic deferred mode is wire-compatible with clients that require a complete default attribute. For example, some deployed provisioning clients require a bare GET /Groups/{id} to return all members, or construct a subsequent PUT from a retrieved representation. Such clients require explicit migration, a legacy compatibility profile, or targeted PATCH behavior before automatic deferred mode is enabled.¶
A service provider supporting this specification SHOULD include the following extension in /ServiceProviderConfig:¶
urn:ietf:params:scim:schemas:extension:attributePagination:2.0:ServiceProviderConfig¶
Example:¶
{
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:ServiceProviderConfig": {
"supported": true,
"cursor": true,
"defaultMode": "deferred",
"defaultPageSize": 100,
"maxPageSize": 1000,
"maxHydratedAttributesPerResponse": 1,
"cursorTimeout": 3600,
"totalResults": "optional",
"resourceTypes": [
{
"resourceType": "Group",
"attributes": ["members"]
},
{
"resourceType": "App",
"attributes": ["grants", "accounts"]
}
]
}
}¶
The fields have the following meaning:¶
| Field | Requirement | Description |
|---|---|---|
supported
|
REQUIRED | Indicates support for this specification. |
cursor
|
REQUIRED | Indicates support for attribute cursor continuation. |
defaultMode
|
OPTIONAL |
explicit or deferred. Absence does not imply that no provider policy exists. |
defaultPageSize
|
OPTIONAL | Provider-selected page size when attributeCount is absent. |
maxPageSize
|
OPTIONAL | Maximum permitted effective page size. |
maxHydratedAttributesPerResponse
|
OPTIONAL | Maximum protected attributes whose values can be loaded in one representation. This version defines a maximum of one. |
cursorTimeout
|
OPTIONAL | Minimum advertised cursor lifetime in seconds. |
totalResults
|
OPTIONAL |
unsupported, optional, or supported. |
resourceTypes
|
RECOMMENDED | Identifies protected attribute paths by resource type. |
A provider MAY withhold numeric defaults or limits when they vary by resource type, authorization context, response-byte budget, or other policy. A client MUST NOT interpret an omitted value as unlimited.¶
Protected attributes SHOULD also be identifiable through provider schema or resource-type metadata. Attribute paths MUST use canonical SCIM attribute notation. Multiple requested sub-attributes of the same top-level multi-valued attribute count as one protected attribute.¶
attributeCount
attributeCount specifies the client's preferred maximum number of values from the selected protected attribute.¶
The value MUST be a non-negative integer.¶
The parameter is OPTIONAL for the first page.¶
If omitted, the provider selects an effective page size.¶
A provider MUST NOT return more values than the effective page size.¶
A provider MAY return fewer values because of authorization, response-byte, query-time, or other safety limits.¶
A value greater than the provider maximum MUST either be reduced to the maximum or rejected with invalidAttributeCount; the behavior SHOULD be advertised consistently.¶
A value of zero requests no values. The provider MAY return an inexpensive totalResults, but a zero-size response does not create a traversable cursor.¶
When a client supplies attributeCount on a continuation request, it MUST match the effective page size bound into the cursor. A continuation request MAY omit attributeCount because the cursor already identifies that size.¶
attributeCursor
attributeCursor contains an opaque continuation value returned in the previous response.¶
It MUST be omitted for the first page.¶
It MUST NOT be interpreted or constructed by the client.¶
It MUST contain URL-safe characters or be percent encoded.¶
It MUST be scoped to the original request context.¶
It SHOULD expire after a service-defined interval.¶
It MUST NOT be accepted on a resource-collection endpoint.¶
The protected attribute is selected through the existing SCIM attributes parameter or through the default attribute-selection rules in [RFC7644].¶
Example with an explicit client preference:¶
Example using the provider's default page size:¶
attributeCursor applies to exactly one canonical protected attribute on exactly one parent resource. If a continuation request selects a different attribute, parent, projection, or other bound context, the provider MUST reject it.¶
Pagination metadata is carried in this provisional resource extension:¶
urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource¶
The extension contains a multi-valued complex attribute named attributePagination. An array is used because a collection response can defer more than one protected attribute independently.¶
Each entry has the following fields:¶
| Field | Requirement | Description |
|---|---|---|
attribute
|
REQUIRED | Canonical path of the protected attribute. |
state
|
REQUIRED |
deferred or page. |
firstPage
|
REQUIRED for deferred
|
Authoritative absolute or relative URI-reference for retrieving the first page from this parent. |
itemsPerPage
|
REQUIRED for page
|
Number of values actually returned in this response. |
nextCursor
|
CONDITIONAL for page
|
Opaque cursor; present only when another page is known to exist. |
totalResults
|
OPTIONAL for page
|
Total authorized values; normally limited to the first page and omitted when expensive. |
attributeVersion
|
OPTIONAL | Opaque version of the logical attribute collection when the provider offers stronger change detection. |
The presence of nextCursor is authoritative. This specification does not define a separate hasMore field because it would duplicate nextCursor and could become inconsistent with it.¶
firstPage is a URI-reference as defined by [RFC3986], not a cursor. It indicates that no page of that attribute was consumed in the current response. Clients SHOULD follow it as supplied rather than reconstruct it. A provider MUST generate it from trusted routing configuration and MUST NOT copy an unvalidated Host or forwarding header into the response.¶
The service provider first applies [RFC7644] attributes, excludedAttributes, schema returned characteristics, and authorization rules. It then applies attribute pagination only to selected and authorized protected attributes.¶
If a protected attribute is excluded, no values and no pagination entry are returned.¶
If the client is not authorized to discover the attribute, no pagination entry is returned.¶
A provider MUST NOT use pagination metadata to reveal the existence, size, source mapping, or values of an unauthorized attribute.¶
An attribute with returned: always MUST be returned and is not eligible for deferred mode.¶
For a collection search returning multiple parent resources, a provider using automatic deferred mode:¶
Retrieves the parent-resource page without invoking the loader, relationship query, exact count, or hydration path for any protected attribute.¶
Omits the selected protected attribute values from each resource.¶
Adds one attributePagination entry with state deferred for each selected protected attribute that can be retrieved for that parent.¶
Supplies a parent-specific firstPage URI-reference in every entry.¶
More than one protected attribute MAY be deferred on the same resource because deferral does not load any values. Root count, cursor, page, or startIndex parameters continue to control the number of parent resources and MUST NOT be interpreted as an attribute page size.¶
attributeCount and attributeCursor MUST NOT cause per-parent protected-attribute hydration on a collection endpoint. A provider MUST reject either attribute-level parameter on a collection endpoint with attributePaginationNotSupported. Root count and root cursor parameters remain valid and independent.¶
The provider SHOULD NOT issue an exact count query merely to decide whether a deferred descriptor is needed. Consequently, following firstPage can legitimately return an empty attribute page.¶
When a request addresses one parent resource and selects exactly one protected attribute for hydration, the provider:¶
Validates the parent and canonical attribute path.¶
Evaluates authorization for the parent, attribute, and visible values.¶
Chooses the effective page size from attributeCount or provider policy.¶
Determines a deterministic total order.¶
Retrieves no more than effectivePageSize + 1 candidate rows from the first query that discovers the values.¶
Removes the look-ahead row before child, CMVA, reference, or display-value hydration.¶
Returns no more than the effective page size.¶
Returns nextCursor only when the look-ahead row proves another page exists.¶
MAY calculate totalResults when it can do so within configured cost limits.¶
If more than one protected attribute is selected on a resource-by-identifier request, the provider MUST NOT hydrate all of them. It SHOULD return each as deferred with an independent firstPage URI-reference. A provider MAY instead reject an explicitly ambiguous request with multipleAttributePaginationNotSupported when that behavior is advertised. This rule permits a bare resource-by-identifier request to remain bounded even when several default-returned protected attributes exist.¶
When attributeCursor is present, the provider:¶
Validates cursor syntax, integrity, expiry, and context.¶
Re-evaluates authorization for the parent, attribute, and values.¶
Applies the stored keyset boundary and ordering.¶
Retrieves no more than effectivePageSize + 1 candidate rows.¶
Removes the look-ahead row before hydration.¶
Returns a replacement nextCursor only when another page is known to exist.¶
SHOULD omit totalResults.¶
An invalid cursor MUST NOT fall back to a first page, an unbounded query, or index-based attribute pagination.¶
For a reference-derived attribute, pagination MUST be applied at the relationship or source-resource query before referenced objects are hydrated. The provider MUST NOT first collect every referenced identifier and then paginate the hydrated result.¶
The source query SHOULD return only the identifiers and ordering values needed for the bounded page. Hydration queries SHOULD use joins, array binding, temporary tables, or bounded chunks appropriate to the database. Implementations MUST account for database expression limits; a page of 1000 plus one look-ahead row MUST NOT become a single 1001-expression IN predicate. The look-ahead row MUST be removed before hydration because it is not part of the response page.¶
Page size is not the only resource limit. A provider MAY stop a page before reaching the effective page size when a response-byte, serialization, query-time, or hydration budget is reached. If more authorized values remain, it MUST return a nextCursor whose boundary is the last value actually returned.¶
A provider MUST NOT return a cursor that advances past values omitted only because a safety budget was reached.¶
The values and page sizes in these examples are illustrative. The App resource type and its grants and accounts attributes are illustrative implementation-specific extensions identified by a URN in the example namespace defined by [RFC6963]; they are not proposed for registration.¶
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 2,
"itemsPerPage": 2,
"startIndex": 1,
"Resources": [
{
"schemas": [
"urn:example:scim:schemas:2.0:App",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource"
],
"id": "app-123",
"displayName": "Payroll",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource": {
"attributePagination": [
{
"attribute": "grants",
"state": "deferred",
"firstPage": "/Apps/app-123?attributes=id%2Cgrants"
}
]
}
},
{
"schemas": [
"urn:example:scim:schemas:2.0:App",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource"
],
"id": "app-456",
"displayName": "Travel",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource": {
"attributePagination": [
{
"attribute": "grants",
"state": "deferred",
"firstPage": "/Apps/app-456?attributes=id%2Cgrants"
}
]
}
}
]
}¶
The grants arrays are absent, not empty. No grant query, count, identifier list, or hydration is performed while building this parent collection.¶
attributeCount
The client follows the first link:¶
Assume the provider chooses an effective page size of two for this abbreviated example.¶
{
"schemas": [
"urn:example:scim:schemas:2.0:App",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource"
],
"id": "app-123",
"grants": [
{
"value": "grant-001",
"$ref": "../Grants/grant-001",
"granteeId": "user-001"
},
{
"value": "grant-002",
"$ref": "../Grants/grant-002",
"granteeId": "user-002"
}
],
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource": {
"attributePagination": [
{
"attribute": "grants",
"state": "page",
"itemsPerPage": 2,
"nextCursor": "opaque-attribute-cursor"
}
]
}
}¶
itemsPerPage describes the number of values actually present in the response page.¶
The continuation request does not need attributeCount; the cursor binds the effective page size. The response contains another nextCursor only if another page exists and normally omits totalResults.¶
The provider returns at most 250 authorized member values, subject to a smaller provider or response-byte limit.¶
The provider returns neither array and advertises both independently:¶
{
"schemas": [
"urn:example:scim:schemas:2.0:App",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource"
],
"id": "app-123",
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource": {
"attributePagination": [
{
"attribute": "grants",
"state": "deferred",
"firstPage": "/Apps/app-123?attributes=id%2Cgrants"
},
{
"attribute": "accounts",
"state": "deferred",
"firstPage": "/Apps/app-123?attributes=id%2Caccounts"
}
]
}
}¶
The client follows the links independently, so a single cursor never has to encode multiple positions.¶
An attribute cursor MUST be bound to at least:¶
Service provider and tenant.¶
Parent resource type and identifier.¶
Canonical protected attribute path.¶
Requested sub-attribute projection.¶
Effective page size.¶
Service-defined ordering and null-order policy.¶
Last stable keyset boundary.¶
Source relationship or reference mapping when the attribute is derived.¶
Authorization-relevant client or subject context when required by provider policy.¶
Changing a bound value MUST cause the provider to reject the cursor. Binding to an exact access-token string is NOT REQUIRED; authorization is re-evaluated on every page.¶
The provider MUST use a deterministic total order. When the logical ordering value is not unique, a stable unique identifier MUST be appended as a tie-breaker. For example:¶
(attributeSortValue, attributeValueId)¶
When no logical order is defined, ordering by an immutable relationship or value identifier is RECOMMENDED. The boundary used to create the next cursor MUST correspond to the last value actually returned, not the look-ahead row.¶
A cursor MUST be either:¶
an unpredictable server-side handle mapped to protected state; or¶
an integrity-protected token whose fields cannot be modified without detection.¶
Encoding cursor state with Base64 alone does not provide integrity. Encryption is not required when the token reveals no confidential information, but integrity or server-side validation is required.¶
Keyset pagination provides stable forward progress over the provider's ordering but does not by itself create a snapshot.¶
During traversal:¶
Values inserted before the current boundary might not be observed.¶
Values inserted after the boundary might be observed.¶
Deleted values might disappear.¶
A value whose ordering key changes can be skipped or repeated.¶
Clients MUST tolerate these outcomes unless stronger consistency is advertised. Providers SHOULD use immutable ordering keys where possible.¶
A provider MAY offer stronger change detection by returning attributeVersion and binding it into the cursor. The version represents the logical attribute collection and need not equal the parent resource's meta.version, especially for a reference-derived attribute. If strict continuation cannot be satisfied after the collection changes, the provider MAY reject the cursor and require traversal to restart.¶
An attribute page or deferred representation is not a complete statement of the protected attribute's values. A client MUST NOT use it as the source for a full-resource PUT or a PATCH operation that replaces the complete protected attribute.¶
This is important because [RFC7644] permits a provider to clear or default omitted read-write attributes during PUT, and deployed clients sometimes use GET-modify-PUT flows.¶
Extension-aware clients SHOULD modify protected attributes with value-targeted PATCH operations, such as adding a value or removing a value selected by a value filter. A provider MAY define a compatibility profile that allows complete replacement when the client independently possesses the complete desired set.¶
When a request contains the pagination extension metadata or is otherwise known to have been derived from a partial representation, a provider SHOULD reject an unsafe full replacement with partialAttributeReplacement. A provider cannot always infer how a client constructed a request after the client removes the metadata; therefore deployment negotiation and client-profile controls remain necessary.¶
This specification does not change the authorization, mutability, uniqueness, or referential-integrity rules for modifying the underlying attribute.¶
Errors use the SCIM error response defined by [RFC7644].¶
scimType
|
Suggested status | Meaning |
|---|---|---|
invalidAttributeCursor
|
400 | Cursor is malformed, modified, unknown, or does not match its request context. |
expiredAttributeCursor
|
400 | Cursor has expired. |
invalidAttributeCount
|
400 | Count is invalid or violates provider policy. |
attributePaginationNotSupported
|
400 | The resource, attribute, endpoint, or request form does not support attribute pagination. |
multipleAttributePaginationNotSupported
|
400 | The request attempts to hydrate or continue more than one protected attribute. |
attributePaginationRequired
|
400 | The provider cannot safely perform unbounded retrieval and deferred behavior has not been established for the client. |
partialAttributeReplacement
|
400 | The request attempts unsafe replacement using a partial or deferred attribute representation. |
Example:¶
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "400",
"scimType": "invalidAttributeCursor",
"detail": "Attribute cursor invalid for this request.\n Request the first page again."
}¶
Providers SHOULD avoid details that disclose whether a parent, protected attribute, hidden value, tenant, or cursor boundary exists.¶
A service provider MUST be able to bound the work performed on behalf of a single client. Deferred collection retrieval converts one large response into a series of optional follow-up requests, so a client can still fan out across many parents and attributes; the mechanism relocates the work rather than eliminating it.¶
A service provider therefore MUST enforce a maximum attribute page size (Section 5) and SHOULD enforce limits on response size, query and hydration time, request rate, concurrency for expensive protected attributes, cursor issuance and lifetime, and the number of deferred descriptors returned in one response. When a limit is reached the provider MUST terminate the page early and return a cursor rather than exceeding the limit or returning an incomplete page without one (Section 8).¶
For complete extraction of very large datasets, providers SHOULD offer an asynchronous export or bulk mechanism rather than encouraging millions of synchronous cursor requests.¶
Appendix C gives non-normative implementation guidance on query construction, budget selection, and observability.¶
Exact totals can be as expensive as retrieving the values and are not required for forward traversal. Providers SHOULD omit totalResults when it requires a costly count. Deferred collection responses SHOULD NOT count protected values merely to populate metadata.¶
An advertised firstPage can return zero values and no nextCursor. This is not an error.¶
Authorization MUST be evaluated for every page. Possession of an attribute cursor or firstPage link does not grant access to the parent, attribute, or referenced values.¶
Providers MUST prevent a cursor from being used across tenants, parent resources, protected attributes, projections, or incompatible authorization contexts. Replaying the same cursor for the same authorized context MAY return the same logical page; cross-context replay MUST fail.¶
Cursors are untrusted input. A provider MUST validate syntax, length, integrity, expiry, and context before using cursor fields in a query. Cursor fields MUST be passed to databases as bound parameters and MUST NOT be concatenated into SQL.¶
Cursors can appear in URLs, browser history, proxy logs, and telemetry. They SHOULD contain no plaintext personal data, credentials, tenant names, or sensitive internal identifiers. Providers SHOULD redact query parameters from logs and use short, risk-appropriate cursor lifetimes. Cursor responses SHOULD be treated as private authenticated content by caches.¶
The provider MUST re-evaluate value-level authorization on each page. itemsPerPage and totalResults, when returned, MUST describe values visible to the requester unless the provider explicitly defines a different non-leaking policy.¶
The deferred descriptor itself can reveal that an attribute exists for a resource. It MUST be omitted when the requester is not authorized to discover the attribute.¶
Page-size limits alone do not eliminate denial-of-service risk. Providers SHOULD apply the work budgets in Section 14.3 and MAY return HTTP 429 or 503 when rate or capacity limits are reached.¶
[RFC9865] pages collections of SCIM resources. This document reuses its main design properties—opaque forward cursors, provider-selected defaults, maximum page sizes, cursor expiry, per-page authorization, and no fallback after an invalid cursor—but scopes the cursor to values of one attribute on one parent.¶
[I-D.hunt-scim-mv-paging] (Hunt and Wilson) and its replacement [I-D.hunt-scim-mv-filtering] (Hunt) previously proposed value qualifiers containing index pagination and filters inside the attributes parameter, including paging values across multiple returned parents. Support was discovered through a boolean mvpaging attribute in ServiceProviderConfig. The SCIM working group charter names this work as input for the multi-value query filtering and paging work item.¶
A call for adoption of [I-D.hunt-scim-mv-filtering] was issued to the working group in May 2022. The draft was not adopted, for lack of sufficient responses; the substantive response received did not support adoption, on the grounds summarized in Section 16.8. This document does not assume that history is irrelevant to it. Sections 16.8 and 1.1 set out what this document claims that the 2022 proposal did not, and Section 16.9 records the design question that remains open.¶
This document uses that work as input and differs in three respects. First, it separates parent collection traversal from attribute traversal, which bounds work and avoids encoding multiple parent-specific continuation positions in one request. Second, it uses an opaque keyset cursor rather than index qualifiers, for the reasons given in Section 16.2.1. Third, it uses a structured discovery extension rather than a single boolean, because a service provider needs to advertise which attributes are protected, what page-size limits apply, and which modes are supported, none of which a boolean can express.¶
Two properties claimed for the qualifier approach warrant direct comment, because this document deliberately trades both away.¶
Backward compatibility. Qualifier-based paging is backward compatible in the sense that a client that sends no qualifier receives unmodified behavior. That property is preserved here by the explicit mode of Section 4.1. It is not preserved by automatic deferred mode, and this document does not claim otherwise. The reason is that explicit mode alone does not solve the operational problem: an unmodified client issuing a bare GET /Groups/{id} against a group with millions of members still causes the unbounded work described in Section 2, because the client has no way to know it should ask for less. A mechanism that only protects the service provider when the client cooperates does not protect the service provider. Automatic mode exists to close that gap, and the negotiation surface in Sections 4.1 and 4.2 exists to make the resulting behavior change safe and observable rather than silent.¶
Statelessness. Index qualifiers are stateless in that the server retains nothing between requests. This document accepts server-side or cursor-encoded continuation state because statelessness and correctness are in conflict here: an index position is only a valid continuation point if the underlying value sequence has not changed, and Section 16.2.1 documents what happens in deployment when it has. The cursors defined in this document are self-describing and integrity-protected rather than stored server-side (Section 11), which recovers most of the operational benefit of statelessness without inheriting the correctness defect.¶
Index-qualified retrieval of multi-valued attribute values has been deployed at scale for more than two decades and its limitations are documented. The expired [I-D.kashi-incremental] proposed incremental retrieval of multi-valued properties, and Active Directory implements this mechanism as range retrieval: a client attaches a range=low-high option to an attribute name in a search request, and the server returns that subset, with the maximum values returned in one response governed by a server policy.¶
The relevant operational finding is the ordering guarantee. Value ordering in a range retrieval request is arbitrary, and consistent across successive requests only while the attribute is not modified between them. Implementers have reported the consequence directly: when another client adds or removes values between a client's successive range requests, the retrieved sequence can contain overlapping, duplicated, or skipped values.¶
This is the same class of defect that index-based collection pagination exhibits, occurring inside a single resource, and it is the primary reason this document specifies keyset cursors bound to a deterministic total ordering (Section 7) rather than index ranges. It is also why this document specifies concurrent-modification semantics and optional attribute versioning explicitly rather than leaving them to implementations.¶
A related contemporaneous proposal, draft-haripriya-partial-entry, addressed partial entry retrieval from a different direction and is noted here for completeness.¶
OData 4.01 [OData-JSON] permits a partial collection-valued property or expanded navigation collection to carry a property-specific nextLink, annotated as {property}@odata.nextLink. A response to an expanded parent collection can therefore return a bounded set of child values per parent together with a per-parent continuation link. The firstPage and nextCursor concepts in this document follow the same architectural principle: continuation metadata belongs to the partial nested collection, while the values remain associated with their parent.¶
OASIS also considered the scoping question this document faces. Issue ODATA-519 records that client-driven paging with $top and $skip was permitted for all collection-valued resources while server-driven paging via next links was restricted to collections of entities or entity references, and notes that there is no semantic reason for that restriction. This document does not adopt the restriction: the deferred and paged behavior defined here applies to any complex multi-valued attribute a service provider designates as protected, whether or not its values are references.¶
Two related proposals represent a multi-valued attribute's values as resources rather than as attribute values: a top-level relationship resource such as /GroupMembers, defined in [I-D.zollner-scim-groupmember], and a per-attribute sub-resource endpoint such as /Groups/{id}/members or a generalized /{ResourceType}/{id}/{attributeUrn}. Both enable standard collection pagination, filtering, and in the relationship-resource case per-relationship create and delete operations.¶
This document is not an alternative to either. Its relationship to each differs.¶
A top-level relationship resource addresses relationship management: individually addressable memberships, cross-collection queries such as retrieving all memberships created within a time window, atomic per-relationship lifecycle operations, and change detection over the relationship set. Those capabilities require relationships to be first-class resources and cannot be provided by attribute pagination. This document does not attempt to provide them.¶
This document addresses bounded retrieval: how a service provider returns a resource that carries a high-cardinality attribute, without unbounded hydration, for any complex multi-valued attribute. The two concerns are orthogonal, and a provider that implements one still needs the other. A provider exposing /GroupMembers still returns Group resources containing a members attribute, because Group.members remains defined by [RFC7643] with returned: default, and that provider still requires defined behavior for the attribute when the group is large. This document supplies it. Support for one does not imply support for the other, and neither obsoletes the other.¶
The sub-resource model and the mechanism defined here converge, and the difference between them is narrower than it first appears.¶
The firstPage URI-reference defined in Section 6 is a per-attribute endpoint address. A collection search returns each parent resource without its protected attribute values together with an authoritative address at which those values may be traversed. This is the same retrieval shape as a sub-resource endpoint, and it produces the same client flow: obtain the parent representation without the high-cardinality attribute, then traverse that attribute separately at its own address.¶
This document specifies that address as provider-generated and discovered rather than client-constructed from a URI template. That choice is deliberate and is the substantive difference between the two models:¶
A provider-generated link can bind ordering, projection, filter, and authorization context into the address itself (Section 10), so a continuation is valid only in the context that produced it. A client-constructed template cannot carry that context and must reconstruct it from query parameters that the client may combine inconsistently.¶
Discovery (Section 5) tells a client which attributes behave this way before it issues a request, rather than requiring the client to know or guess which sub-resource endpoints a given provider exposes for a given resource type.¶
The mechanism applies uniformly to attributes for which no sub-resource endpoint has been defined, including implementation-specific and dynamically derived attributes, without requiring a new endpoint and a new registration for each one.¶
The parent resource's representation remains the response envelope, so the client receives the attribute in the schema context it belongs to, and meta.version, schema URIs, and returned characteristics remain meaningful for the values returned.¶
A service provider that exposes per-attribute sub-resource endpoints MAY use those endpoint addresses as the firstPage value, in which case the two models coincide exactly and this document supplies the discovery, ordering, continuation, and mutation-safety contract that a bare endpoint definition otherwise leaves to implementations.¶
An alternative raised in working group mailing list discussion is to paginate the JSON object representing a SCIM resource, treating the serialized resource rather than one attribute's value list as the unit of division. This has the attraction of addressing a resource with several large multi-valued attributes, and of addressing large single-valued attributes, in one mechanism.¶
This document does not adopt that model, for four reasons.¶
A division of the serialized object has no attribute semantics. It cannot express that an attribute with returned: always must never be withheld, and it cannot distinguish a withheld attribute from an empty one, which Section 4 identifies as a correctness requirement for mutation safety.¶
A continuation point over serialized output cannot be bound to a deterministic ordering of the underlying value set, so it reintroduces the concurrent-modification defect described in Section 16.2.1 at the document level rather than the attribute level.¶
Authorization is applied per value (Section 15). A serialization-level boundary can split a value set at a point that does not correspond to any authorization decision, so the provider must still evaluate the whole set before deciding what to emit. Response size is bounded; the underlying work is not.¶
The generated boundary is not addressable. A client cannot request the second page of one specific attribute without traversing what precedes it, which defeats the selective-retrieval use case in Section 3.¶
A provider needing to bound several protected attributes on one resource achieves this with the mechanism defined here by deferring each independently and hydrating one per response, as specified in Section 8.¶
Chunked transfer encoding has been raised in SCIM working group mailing list discussion as an existing mechanism that could address large resource representations without a SCIM-level extension.¶
Chunked transfer encoding bounds neither the work described in Section 2 nor the memory required to produce the response. It permits a response to be transmitted without a known content length, which allows the service provider to begin transmitting before serialization completes. It does not reduce the number of values the provider must retrieve, hydrate, authorize, or serialize, and it does not bound the intermediate identifier lists, expression-limit exposure, or fan-out during collection searches. A provider that streams a group of several million members has converted a large allocation into a long-running one; the request is still unbounded, and the client still receives a representation it cannot process incrementally without a value-level continuation contract.¶
Chunked transfer encoding is complementary to this document, not an alternative to it, and a provider MAY use it for the bounded pages defined here.¶
Deployed identity clients demonstrate both sides of the compatibility problem. Microsoft Entra provisioning requests Groups with excludedAttributes=members and uses targeted membership operations, which naturally avoids unbounded reads. Okta documents that a bare GET /Groups/{id} must return members and that some custom integrations use PUT with full membership state. PingOne management APIs use provider-defined page limits and opaque cursor links for large collections. Providers therefore need client-specific migration evidence before changing automatic behavior for an established integration.¶
Implementers have independently converged on the retrieval pattern this document standardizes. One reported deployment handling groups exceeding one hundred thousand members retrieves the group with its members excluded and then paginates the membership through a separate endpoint, having added that endpoint as an implementation-specific extension. That two-step flow — parent representation without the high-cardinality attribute, followed by a bounded traversal of the attribute at its own address — is the flow specified in Sections 6 and 8 of this document. The contribution here is not the pattern but its standardization: an authoritative provider-generated firstPage link rather than a client-constructed URI template, a deterministic ordering and continuation contract, and discovery that tells a client which attributes behave this way before it issues the first request.¶
Working group feedback on the earlier multi-value filtering proposal observed that the common group-membership use cases can be satisfied with existing SCIM filtering and ordinary resource pagination, without any protocol extension. Where a counterpart resource exists and the inverse relationship is filterable, membership can be enumerated as a resource collection:¶
The results are resources rather than attribute values, so they page under Section 3.4.2.4 of [RFC7644] with no new mechanism. Membership tests reduce to compound filters in the same way.¶
This document accepts that analysis. For enumerating the members of a group, or the groups containing a user, inverse filtering is an effective technique that requires nothing new, and clients that can use it should. The observation that the base SCIM schemas contain few attributes large enough to warrant server-side value pagination — principally Group.members and User.groups — is also accepted; see Section 3.¶
Three limits define what remains.¶
First, and most importantly, inverse filtering answers a different question. It provides a way for a client to enumerate memberships; it does not define what a service provider returns when a client requests the parent resource, which [RFC7643] entitles it to do and which returns members by default. Section 1.1 sets out that gap. A provider cannot decline to answer GET /Groups/{id} on the grounds that a better query exists.¶
Second, it requires a filterable inverse. User.groups is defined with mutability: readOnly, and support for filtering on it is uneven across deployed service providers. Where the counterpart attribute is not filterable, or is not indexed for that access path, the technique is unavailable and the client has no way to discover this in advance.¶
Third, it requires a counterpart resource. Implementation-specific assignment attributes are frequently derived rather than persisted, and frequently have no resource on the other side of the relationship to filter over. For these attributes the inverse query does not exist to be issued.¶
Inverse filtering and this document are therefore complementary. A service provider SHOULD support inverse filtering where the relationship permits it, and clients SHOULD prefer it for enumeration. This document defines what happens on the paths inverse filtering does not cover.¶
[[ RFC Editor / Working Group note: this section states an open design question that this revision does not resolve. It is included because the question is material to the value of the mechanism. To be resolved before working group last call. ]]¶
As specified in this revision, traversing a protected attribute requires a request per parent resource. A collection search returns each parent with a firstPage link, and the client follows one link per parent. For a client enumerating memberships across many groups, this is a request per group.¶
This is a substantive limitation of the mechanism as specified, not merely an inefficiency, for two reasons. First, the request count scales with the number of parent resources rather than with the number of values retrieved. Second, and more consequentially, it forecloses a root-level form such as:¶
in which a single traversal spans parents. That form is a prerequisite for change-tracking and delta-query mechanisms over relationship sets, which are anticipated future work for this protocol. A design that cannot express it constrains that work.¶
The cursor mechanism defined in Section 10 appears capable of carrying this form. A keyset cursor is defined over a deterministic total ordering; extending that ordering from (value identifier) within one parent to the composite (parent identifier, value identifier) across a collection yields a single continuation sequence over the whole relationship set. The per-parent traversal specified in Section 8 then becomes the case in which the ordering is constrained to one parent, rather than the only available mode. A delta traversal would order over a change sequence instead.¶
Several questions remain unresolved, and this document does not treat the design as settled:¶
What the response envelope should be. A root-level traversal returns values belonging to many parents; whether these are returned as partial parent resources, as a flat sequence of (parent, value) pairs, or in some other form determines whether the result remains interpretable in the schema context of its parent.¶
Whether the composite ordering can be evaluated efficiently by service providers whose relationship storage is partitioned by parent, which is a common arrangement and the reason the per-parent form was specified first.¶
How the result relates to a relationship resource collection (Section 16.4.1). A flat (parent, value) sequence and a paged relationship resource collection may be close enough that specifying both is not warranted.¶
Whether authorization can be evaluated per value at acceptable cost when a page spans parents with differing access-control outcomes.¶
Working group input is invited on all four, and specifically on whether this work belongs in this document or in the relationship-resource work described in Section 16.4.1.¶
This document requests registration of the following URIs in the IANA "System for Cross-domain Identity Management (SCIM) Schema URIs" registries.¶
This document requests registration of the following preference in the IANA "HTTP Preferences" registry defined by [RFC7240]:¶
Preference: scim-attribute-pagination¶
Value: deferred¶
Optional Parameters: None¶
Description: Indicates that the client understands deferred and cursor-paged SCIM multi-valued attribute representations defined by this document.¶
Reference: This document¶
The SCIM detail error keywords in Section 13 extend Table 9 of [RFC7644]. No separate IANA registry for SCIM detail error keywords exists at the time of writing.¶
The author thanks the following contributors, whose input shaped this revision: Phillip Hunt, for the earlier multi-value paging and filtering work that this document takes as input and for the history of that effort; Daniel Cormier, for reporting deployed implementation experience with large group memberships; Danny Zollner, for identifying the resource-oriented alternatives evaluated in Section 16 and for detailed review comments on the -00 revision; and Matt Peterson, whose 2022 analysis of membership use cases is recorded in Section 16.8.¶
Acknowledgement does not imply endorsement. Several of the contributors named above have expressed reservations about the approach taken in this document, and Section 16 records those positions.¶
The definitions in this appendix are provisional review representations. They are to be converted to the final RFCXML artwork and checked with the designated SCIM schema expert before publication.¶
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
"id": "urn:ietf:params:scim:schemas:extension:attributePagination:2.0:Resource",
"name": "AttributePaginationResourceExtension",
"description": "Describes deferred or cursor-paged multi-valued attributes on a SCIM resource.",
"attributes": [
{
"name": "attributePagination",
"type": "complex",
"multiValued": true,
"required": false,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Independent retrieval state for protected multi-valued attributes.",
"subAttributes": [
{
"name": "attribute",
"type": "string",
"multiValued": false,
"required": true,
"caseExact": false,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Canonical SCIM path of the protected attribute."
},
{
"name": "state",
"type": "string",
"multiValued": false,
"required": true,
"caseExact": true,
"canonicalValues": ["deferred", "page"],
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Indicates whether values are deferred or a page is present."
},
{
"name": "firstPage",
"type": "reference",
"referenceTypes": ["uri"],
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Authoritative URI-reference used to retrieve the first page."
},
{
"name": "itemsPerPage",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Values returned in this page."
},
{
"name": "nextCursor",
"type": "string",
"multiValued": false,
"required": false,
"caseExact": true,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Opaque cursor for the next page."
},
{
"name": "totalResults",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Optional total authorized values."
},
{
"name": "attributeVersion",
"type": "string",
"multiValued": false,
"required": false,
"caseExact": true,
"mutability": "readOnly",
"returned": "default",
"uniqueness": "none",
"description": "Optional collection version token."
}
]
}
]
}¶
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
"id":
"urn:ietf:params:scim:schemas:extension:attributePagination:2.0:ServiceProviderConfig",
"name": "AttributePaginationServiceProviderConfigExtension",
"description": "Support and policy for attribute pagination.",
"attributes": [
{
"name": "supported",
"type": "boolean",
"multiValued": false,
"required": true,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "cursor",
"type": "boolean",
"multiValued": false,
"required": true,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "defaultMode",
"type": "string",
"multiValued": false,
"required": false,
"caseExact": true,
"canonicalValues": ["explicit", "deferred"],
"mutability": "readOnly",
"returned": "default"
},
{
"name": "defaultPageSize",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "maxPageSize",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "maxHydratedAttributesPerResponse",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "cursorTimeout",
"type": "integer",
"multiValued": false,
"required": false,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "totalResults",
"type": "string",
"multiValued": false,
"required": false,
"caseExact": true,
"canonicalValues": ["unsupported", "optional", "supported"],
"mutability": "readOnly",
"returned": "default"
},
{
"name": "resourceTypes",
"type": "complex",
"multiValued": true,
"required": false,
"mutability": "readOnly",
"returned": "default",
"subAttributes": [
{
"name": "resourceType",
"type": "string",
"multiValued": false,
"required": true,
"caseExact": true,
"mutability": "readOnly",
"returned": "default"
},
{
"name": "attributes",
"type": "string",
"multiValued": true,
"required": true,
"caseExact": false,
"mutability": "readOnly",
"returned": "default"
}
]
}
]
}¶
[[ RFC Editor: please remove this section before publication. ]]¶
Changed intended status from Informational to Standards Track because automatic deferral replaces [RFC7644] Section 3.9 response semantics for negotiating parties and adds attributes to existing [RFC7643] structures.¶
Expanded the problem from explicitly requested single-resource pagination to both deferred collection retrieval and bounded resource-by-identifier retrieval.¶
Made attributeCount optional and defined a provider-selected default page size.¶
Added advertised explicit and automatic deferred modes plus staged compatibility-profile guidance.¶
Added an [RFC7240] in-band preference for client opt-in without making its absence an unsafe-behavior request.¶
Replaced the single metadata object with an attributePagination array supporting independent deferred descriptors.¶
Added state and firstPage fields and removed the redundant hasMore field.¶
Allowed multiple protected attributes to be deferred while retaining at most one hydrated attribute per response.¶
Defined selection behavior for attributes, excludedAttributes, returned: always, default-returned attributes, authorization, and empty attributes.¶
Added Updates: 7643, 7644, following [RFC9865], together with replacement rules for [RFC7644] Section 3.9 attribute-return behavior scoped to negotiated parties, and documented that automatic deferral is not wire-compatible with every existing client.¶
Added GET-modify-PUT and full-replacement safety requirements.¶
Added adaptive byte/time budgets, fan-out controls, and asynchronous export guidance.¶
Added database expression-limit guidance and required removal of the look-ahead row before hydration.¶
Strengthened cursor context, total ordering, integrity, logging, reauthorization, and privacy requirements.¶
Added concurrent-modification semantics and optional attributeVersion change detection.¶
Added implementation-neutral handling for persisted and reference-derived attributes.¶
Added observability guidance using bounded dimensions.¶
Reframed the abstract and introduction around the [RFC7643] returned: default conformance gap rather than around generalization across attribute types, and added Section 1.1 enumerating the non-conformant or unsafe options currently available to a service provider.¶
Added Section 16.8 accepting inverse filtering over the counterpart resource as effective for membership enumeration, and stating the three limits that leave the conformance gap open.¶
Added Section 16.9 recording root-level attribute traversal as an open design question, including the composite (parent, value) ordering that may express it and four unresolved questions put to the working group.¶
Recorded the May 2022 call for adoption of [I-D.hunt-scim-mv-filtering] and its outcome (Section 16.2).¶
Moved query construction, budget selection, and observability guidance from Section 14 into non-normative Appendix C, leaving normative operational limits in the body.¶
Added prior-art comparisons with [RFC9865], the Hunt multi-value paging and filtering drafts, LDAP/Active Directory range retrieval and its documented ordering failure mode, OData nested collection continuation, top-level relationship resources, and per-attribute sub-resource endpoints.¶
Addressed feedback received on the SCIM mailing list in January and February 2026: documented the backward-compatibility and statelessness trade-offs relative to qualifier-based paging (Section 16.2), added rebuttals of whole-resource pagination (Section 16.5) and HTTP chunked transfer encoding (Section 16.6), and recorded reported implementation experience with the deferred retrieval pattern (Section 16.7).¶
Reframed the relationship to resource-based models: the firstPage link is described as a provider-generated per-attribute endpoint address, and Section 16.4.2 states the conditions under which the sub-resource model and this mechanism coincide.¶
Added deployment interoperability considerations based on Microsoft Entra and Okta client behavior.¶
Added provisional IANA registration requests for the resource and ServiceProviderConfig extension schema URIs and the HTTP preference token.¶
This appendix contains implementation guidance. It defines no protocol behavior and conformance does not depend on it.¶
A directly persisted attribute can use a parent-scoped keyset query:¶
SELECT ... FROM RESOURCE_SUBOBJECT WHERE TENANT_ID = ? AND PARENT_ID = ? AND MAPPING_PATH = ? AND ID > ? ORDER BY ID FETCH FIRST ? ROWS ONLY¶
The final bind is the effective page size plus one.¶
A reference-derived attribute can page the relationship at its source:¶
SELECT ... FROM GRANT_RESOURCE WHERE TENANT_ID = ? AND APP_ID = ? AND ID > ? ORDER BY ID FETCH FIRST ? ROWS ONLY¶
Only the returned page is hydrated into the parent attribute. Implementations SHOULD avoid N+1 display-value queries and unbounded identifier lists.¶
Deferred collection retrieval changes one large response into optional follow-up calls. A malicious or poorly designed client can still fan out across many parents and attributes. Providers SHOULD enforce:¶
Maximum attribute page size.¶
Maximum response bytes and serialized values.¶
Query-time and hydration-time budgets.¶
Per-client and per-tenant request-rate limits.¶
Concurrency limits for expensive protected attributes.¶
Cursor issuance and lifetime limits.¶
Maximum root-resource page size.¶
Maximum deferred descriptors per response.¶
For complete extraction of very large datasets, providers SHOULD offer an asynchronous export or bulk mechanism rather than encouraging millions of synchronous cursor requests.¶
Providers SHOULD distinguish at least:¶
deferred collection responses;¶
first attribute pages;¶
continuation pages;¶
terminal pages;¶
invalid or expired cursors;¶
effective page size and returned value count;¶
time spent discovering values versus hydrating them;¶
response bytes and budget-driven early page termination.¶
Metrics MUST NOT use tenant identifiers, parent identifiers, cursor contents, attribute values, or other unbounded/high-cardinality dimensions.¶