This quick start will cover how you can configure different types of pagination, and what you need to do to implement cursor-based paging.
Configuring support for Cursor-based pagination
The default configuration is to enable index-based pagination. This is the pagination approach defined in the SCIM Protocol spec RFC 7644, with a separate specification RFC draft-ietf-scim-cursor-pagination defining cursor-based pagination. This specification also introduces pagination options for defining how a SCIM client should interact with the SCIM service provider and what capabilites the service provider has.
To configure the pagination capabilities of your service provider, when calling AddScimServiceProvider
, set the PaginationOptions
on the ScimServiceProviderConfigOptions
object. The PaginationOptions
class has the following structure.
{
// A Boolean value specifying support of cursor-based pagination
public bool Cursor { get; }
// A Boolean value specifying support of index-based pagination
public bool Index { get; }
// A value specifying the type of pagination that the service provider defaults to when the client has not specified which method it wishes to use
public PaginationMethod DefaultPaginationMethod { get; }
// Positive integer value specifying the default number of results returned in a page when a count is not specified in the query
public int? DefaultPageSize { get; }
// Positive integer specifying the maximum number of results returned in a page regardless of what is specified for the count in a query
public int? MaxPageSize { get; }
// Positive integer specifying the maximum number seconds that a cursor is guaranteed to be valid between page requests
public int? CursorTimeout { get; }
}
The pagination options, like other options, are exposed to a SCIM Client through a call to /ServiceProviderConfig
"pagination": {
"cursor": true,
"index": true,
"defaultPaginationMethod": "cursor",
"defaultPageSize": 100,
"maxPageSize": 250,
"cursorTimeout": 3600
}
Supporting Cursor-Based Paging
To add support for cursors:
- The SCIM Store must implement the
GetAll(ICursorResourceQuery)
method on theIScimStore<TResource>
interface - As part of the service wire-up, the
Pagination
options object propertyCursor
must be set totrue
The SCIM Client may be capable of supporting both index and cursor paging. To configure which method the SCIM component should use if both the cursor
and startIndex
query parameters are included, set the DefaultPaginationMathod
to your desired method.
You will need to return a ScimCursorPageResults<TResource>
from your GetAll(ICursorResourceQuery)
. This object looks like the following:
{
// Page resource rows
public IEnumerable<T> Rows { get; }
// Total number of matched rows the overall query
public int TotalRows { get; }
// A string representation of the previous cursor
public string PreviousCursor { get; set; }
// A string representation of the next cursor
public string NextCursor { get; set; }
}
The NextCursor
contains a cursor value string that can be used in subsequent requests to obtain the next page of results. When constructing a ScimCursorPageResults<TResource>
, if there is a next possible cursor, then this must be included. If there is no next cursor due to being on the last page of results, it can be omitted. The PreviousCursor
contains a cursor value string that can be used in a subsequent request to obtain the previous page of results, but is optional.
Default Implementation
There is only a small breaking change in the SCIM Store to add cursor support:
GetAll(IIndexResourceQuery)
replacesGetAll(IResourceQuery)
GetAll(ICursorResourceQuery)
contains a default implementation that throws aNotImplmenetedException
If a store needs to support cursors due to integration with a specific SCIM client, but it still wants to use index-based paging and not duplicate GetAll(IIndexResourceQuery)
implementation, during service wire-up call AdaptCursorPagingToIndexPaging
. This method adds a decorator to your IScimStore
that will map the incoming cursor-based request and parameters into index-based paging parameters.
Validation
Your store is responsible for validating the cursor, based on lifetime and its existence. This validation should match the configuration of the store, e.g. CursorTimeout
.
Cursor Timeouts
If the GetAll
implementation, receives a cursor value that has timed out, the GetAll
method must throw a ScimStoreCursorTimeoutException
. The SCIM middleware will translate the exception into an HTTP 400 status code (Bad Request).
Unexpected Cursors
If the GetAll
implementation receives an unrecognised cursor value, the GetAll
method must throw a ScimStoreUnrecognizedCursorException
. The SCIM middleware will translate the exception into an HTTP 400 status code (Bad Request).