This quick-start shows what you need to know to create your own stores and validation for SCIM requests.
Using a Custom Store
To use your store for resources, you need to create a store that implements IScimStore<T>
where T
is a type derived from Resource
. To find more information about Resource
and its derived models please see the introduction. The interface IScimStore<T>
looks as follows:
Task<T> Add(T resource);
Task<ScimPageResults<TResource>> GetAll(IResourceQuery query);
Task<T> GetById(string id, ResourceAttributeSet attributes) ;
Task<ScimPageResults<T>> GetAll(IResourceQuery query);
Task<T> Update(T resource);
Task PartialUpdate(string resourceId, IEnumerable<PatchCommand> updates);
Task Delete(string id);
To register your store with the SCIM library, you must register it alongside a resource in the ConfigureServices
method.
public void ConfigureServices(IServiceCollection services)
{
services.AddScimServiceProvider("/SCIM", new ScimLicensingOptions("Demo", "eyJTb2xkRm9yIjowLjAsI .... "))
.AddResource<User, CustomUserStore>("urn:ietf:params:scim:schemas:core:2.0:User", "Users");
}
In this example, we provide a custom store implementation for the default User
model. This example will also utilize the built-in ScimValidator
, as described in the installation quick-start.
Filtering
To provide a full implementation of the GetAll
method requires compiling a SCIM filter expression to an expression that the store can execute against the underlying data store. The SCIM component ships with a type that compiles SCIM filter expressions to an IQueryable<T>
to assist in executing a SCIM filter. Use the extension method AddFilterPropertyExpressionCompiler
on the DI container to make the service available to the stores via IScimQueryBuilderFactory
.
Configure the factory using the extension methods described in mapping attributes. The extension method maps from SCIM attribute paths to the storage type's properties.
The store uses the factory to create a query builder for the store's storage type (the T in the IQueryable). The builder provides methods to define the filter along with paging and sorting.
public async Task<ScimPageResults<User>> GetAll(IResourceQuery query)
{
IQueryable<AppUser> databaseQuery =
queryBuilderFactory.CreateQueryBuilder<AppUser>(ctx.Users)
.Filter(query.Filter)
.Build();
IQueryable<AppUser> pageQuery = queryBuilderFactory.CreateQueryBuilder<AppUser>(databaseQuery)
.Page(query.StartIndex, query.Count)
.Sort(query.Sort.By, query.Sort.Direction)
.Build();
. . .
}
The store then uses the compiled expression against any data store that can compile an IQueryable
int totalCount = await databaseQuery.CountAsync();
var matchingUsers = await pageQuery
.AsAsyncEnumerable()
.Select(MapAppUserToScimUser)
.ToListAsync();
return new ScimPageResults<User>(matchingUsers, totalCount);
The alternative is to walk the filter abstract syntax tree to determine the underlying query. All items in the tree are a kind of a ScimExpression
.
Using a Custom Validator
To use your validator, as opposed to the default validation described in the installation quick-start, you need to implement IScimValidator<T>
(where T
is derived from Resource
) and also have a custom store implemented as defined above. You can provide a custom validator for your resources or the default resources. The interface IScimValidator<T>
defines two methods. The ValidateUpdate
method will be called when validating Update
(PUT
) request, and the ValidateAdd
method will be called when validating Create
(POST
) requests. This is to enable different validation based on the context of the request.
Task<IScimResult<T>> ValidateUpdate(string resourceAsString, string schema);
Task<IScimResult<T>> ValidateAdd(string resourceAsString, string schema);
To register your store with the SCIM library, you must register it alongside a resource and store in the ConfigureServices
method.
public void ConfigureServices(IServiceCollection services)
{
services.AddScimServiceProvider("/SCIM", new ScimLicensingOptions("Demo", "eyJTb2xkRm9yIjowLjAsI .... "))
.AddResource<ScimUser, ScimStore, ScimValidator>("urn:ietf:params:scim:schemas:core:2.0:User", "Users");
}