-
Notifications
You must be signed in to change notification settings - Fork 29
04. Adding & Modifying Resource Types
All core SCIM resource types are added by default. Each resource has an associated ScimTypeDefinition
which defines the qualities associated with each attribute. *Even if you introduce a custom resource type or resource type extension, Owin.Scim will automatically create a type definition for all attributes on your type. There are many valid use cases to modify the core Owin.Scim resource type definitions: e.g.
- service provider may
require
certain fields - service provider has specific canonicalization rules
- service provider has specific canonical values
- service provider has specific validation logic
- etc ...
The majority of SCIM's resource type attributes and sub-attributes have qualities which default to:
- caseExact: false
- mutability: readWrite (readOnly, writeOnly, immutable)
- required: false
- returned: default (always, never)
- uniqueness: none (server, global)
By default, Owin.Scim assigns all attribute qualities as per https://tools.ietf.org/html/rfc7643#section-7. Depending on your requirements as a SCIM service provider, you may need to modify these qualities as you see fit. It is up to you to ensure any modifications remain in compliance of the SCIM standard.
Owin.Scim uses these rules for processing and enforcing mutability rules during deserialization for POST/PUT/PATCH request operations. It is also used to enforce SCIM Returned values upon outbound serialization. More on this in a later chapter.
In order to process rules concerning mutability and attribute serialization, Owin.Scim requires all types to define their metadata schema. If you do not create your own type definition, Owin.Scim will create it for you - interpreting each attribute with the default SCIM attribute behaviors: (Mutability.ReadWrite, Returned.Default, etc.)
A type definition must implement Owin.Scim.Model.IScimTypeDefinition
and furthermore, inherit from either ScimResourceTypeDefinitionBuilder<T>
or ScimTypeDefinitionBuilder<T>
. Inherit from the former when you are defining resource types and the latter when defining any other object.
public class User : Resource
{
// ...
}
public class UserDefinition : ScimResourceTypeDefinitionBuilder<User>
{
public UserDefinition()
: base(
ScimConstants.ResourceTypes.User,
ScimConstants.Schemas.User,
ScimConstants.Endpoints.Users,
typeof(UserValidator),
schemaIdentifiers => schemaIdentifiers.Contains(ScimConstants.Schemas.User))
{
AddSchemaExtension<EnterpriseUserExtension, EnterpriseUserExtensionValidator>(ScimConstants.Schemas.UserEnterprise, false); // add optional or required schema extensions
For(u => u.Schemas)
.SetReturned(Returned.Always);
For(u => u.Id)
.SetMutability(Mutability.ReadOnly)
.SetReturned(Returned.Always)
.SetUniqueness(Uniqueness.Server)
.SetCaseExact(true);
For(u => u.UserName)
.SetRequired(true)
.SetUniqueness(Uniqueness.Server);
// ...
}
}
For all POST, PUT, and PATCH operations Owin.Scim must interpret the request content and decide which concrete type to instantiate and deserialize to. In the above resource type definition constructor, if the predicate schemaIdentifiers => schemaIdentifiers.Contains(ScimConstants.Schemas.User)
is satisfied by the schemas collection obtained from the request's json schemas
collection, Owin.Scim will instantiate (deserialize) an instance of the associated type argument User
.
Owin.Scim defines all canonical values as per SCIM specification. The SCIM specification frequently references "canonical values" for multi-valued attribute's type
attribute. Values like: work
, home
, other
, etc. Owin.Scim does not currently provide any automated validation around these type definition canonical values. In this light, canonicalization should be viewed strictly in terms of normalization of data. There is a GitHub issue that exists for automating validation rules based upon type definitions which may be built in the future.
You have complete control over schema definitions for built-in core SCIM resource types and their attributes. (e.g. User, Group). To customize these schema definitions you may do one of the following:
- Create a class which inherits from a built-in schema definition (e.g.
UserDefinition
)
Use this when you want to keep the majority of Owin.Scim's default attribute definitions for the resource. - Create a class which inherits from
ScimResourceTypeDefinitionBuilder<T>
(where T is the Resource)
Use this when you want to define all attribute definitions yourself. (Owin.Scim will still initialize all attribute definitions to the default SCIM qualities, but will not use any customizations found in built-in definitions.) - Specify a
ModifyResourceType<T>(Action<ScimResourceTypeDefinitionBuilder<T>> builder)
configuration action
Use this when you only need to minimally customize the resource. (e.g. changing the validator) You cannot modify complex attribute's schema definitions from this function.
public class CustomUserDefinition : UserDefinition
{
public CustomUserDefinition(ScimServerConfiguration serverConfiguration) : base(serverConfiguration)
{
For(u => u.Name)
.SetRequired(true);
}
}
app.UseScimServer(
configuration => {
configuration.ModifyResourceType<User>(ModifyUserResourceType));
});
// ...
private void ModifyUserResourceType(ScimResourceTypeDefinitionBuilder<User> builder)
{
builder
.SetValidator<UserValidator>(); // allows you to change the validator for the resource
}
To add new resource types, all you have to do is:
- Create a new class which inherits from
Resource
- Create a custom validator for this resource which inherits from
ResourceValidatorBase<TResource>
- Create a new
ApiController
for this resource endpoint which inherits fromScimControllerBase
- Create an associated resource type definition which inherits from
ScimResourceTypeDefinitionBuilder<TResource>
An example of this process can be seen at: CustomResourceTypes