public static SCIMSchema Extract(string filePath, string resourceType) { var content = File.ReadAllText(filePath); var jObj = JsonConvert.DeserializeObject <JObject>(content); var builder = SCIMSchemaBuilder.Create(jObj[SCIMConstants.StandardSCIMRepresentationAttributes.Id].ToString(), jObj[SCIMConstants.StandardSCIMRepresentationAttributes.Name].ToString(), resourceType, jObj[SCIMConstants.StandardSCIMRepresentationAttributes.Description].ToString(), true); var attributes = jObj[SCIMConstants.StandardSCIMRepresentationAttributes.Attributes] as JArray; foreach (JObject attribute in attributes) { JArray subAttributes = null; if (attribute.ContainsKey(SCIMConstants.StandardSCIMRepresentationAttributes.SubAttributes)) { subAttributes = attribute[SCIMConstants.StandardSCIMRepresentationAttributes.SubAttributes] as JArray; } builder.AddAttribute( ExtractString(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Name), ExtractEnum <SCIMSchemaAttributeTypes>(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Type), multiValued: ExtractBoolean(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.MultiValued), required: ExtractBoolean(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Required), caseExact: ExtractBoolean(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.CaseExact), mutability: ExtractEnum <SCIMSchemaAttributeMutabilities>(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Mutability), returned: ExtractEnum <SCIMSchemaAttributeReturned>(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Returned), uniqueness: ExtractEnum <SCIMSchemaAttributeUniqueness>(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Uniqueness), description: ExtractString(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.Description), canonicalValues: ExtractList(attribute, SCIMConstants.StandardSCIMRepresentationAttributes.CanonicalValues), callback: (c) => { if (subAttributes == null) { return; } foreach (JObject subAttr in subAttributes) { c.AddAttribute( ExtractString(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Name), ExtractEnum <SCIMSchemaAttributeTypes>(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Type), multiValued: ExtractBoolean(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.MultiValued), required: ExtractBoolean(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Required), caseExact: ExtractBoolean(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.CaseExact), mutability: ExtractEnum <SCIMSchemaAttributeMutabilities>(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Mutability), returned: ExtractEnum <SCIMSchemaAttributeReturned>(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Returned), uniqueness: ExtractEnum <SCIMSchemaAttributeUniqueness>(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Uniqueness), description: ExtractString(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.Description), canonicalValues: ExtractList(subAttr, SCIMConstants.StandardSCIMRepresentationAttributes.CanonicalValues) ); } } ); } return(builder.Build()); }
public void ConfigureServices(IServiceCollection services) { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", SCIMConstants.SCIMEndpoints.User, "User Account", true) .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("name", c => { c.AddStringAttribute("formatted", description: "The full name"); c.AddStringAttribute("familyName", description: "The family name"); c.AddStringAttribute("givenName", description: "The given name"); }, description: "The components of the user's real name.") .AddStringAttribute("roles", multiValued: true) .AddStringAttribute("immutable", mutability: SCIMSchemaAttributeMutabilities.IMMUTABLE) .AddComplexAttribute("groups", opt => { opt.AddStringAttribute("value", mutability: SCIMSchemaAttributeMutabilities.READONLY); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READONLY) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddComplexAttribute("scores", opt => { opt.AddComplexAttribute("math", sopt => { sopt.AddIntAttribute("score"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE); }, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddStringAttribute("type", canonicalValues: new List <string> { "manager", "employee" }) .AddStringAttribute("org", defaultValue: new List <string> { "ENTREPRISE" }, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddSCIMSchemaExtension("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", true) .Build(); var enterpriseUser = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", "EnterpriseUser", "Enterprise user") .AddStringAttribute("employeeNumber", required: true) .Build(); var schemas = new List <SCIMSchema> { userSchema, enterpriseUser, SCIMConstants.StandardSchemas.GroupSchema }; services.AddMvc(); services.AddAuthorization(opts => opts.AddDefaultSCIMAuthorizationPolicy()); services.AddAuthentication(SCIMConstants.AuthenticationScheme).AddCustomAuthentication(c => { }); services.AddSIDScim(o => { o.MaxOperations = 3; o.IgnoreUnsupportedCanonicalValues = false; }).AddSchemas(schemas); }
public void ConfigureServices(IServiceCollection services) { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", "User Account") .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("name", c => { c.AddStringAttribute("formatted", description: "The full name"); c.AddStringAttribute("familyName", description: "The family name"); c.AddStringAttribute("givenName", description: "The given name"); }, description: "The components of the user's real name.") .AddStringAttribute("immutable", mutability: SCIMSchemaAttributeMutabilities.IMMUTABLE) .AddComplexAttribute("groups", opt => { opt.AddStringAttribute("value", mutability: SCIMSchemaAttributeMutabilities.READONLY); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READONLY) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddStringAttribute("org", defaultValue: new List <string> { "ENTREPRISE" }, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .Build(); var schemas = new List <SCIMSchema> { userSchema, SCIMConstants.StandardSchemas.GroupSchema, SCIMConstants.StandardSchemas.CommonSchema }; services.AddMvc(); services.AddAuthorization(opts => opts.AddDefaultSCIMAuthorizationPolicy()); services.AddAuthentication(SCIMConstants.AuthenticationScheme).AddCustomAuthentication(c => { }); services.AddSIDScim(o => { o.UserSchemas = new List <SCIMSchema> { userSchema, SCIMConstants.StandardSchemas.CommonSchema }; o.GroupSchemas = new List <SCIMSchema> { SCIMConstants.StandardSchemas.GroupSchema, SCIMConstants.StandardSchemas.CommonSchema }; o.MaxOperations = 3; }).AddSchemas(schemas); }
public void When_Apply_Patch_To_SCIM_Representation() { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", "User Account") .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .Build(); var userRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { userSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "john" }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "01" }); b.AddStringAttribute("type", new List <string> { "mobile" }); }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "02" }); b.AddStringAttribute("type", new List <string> { "home" }); }) .Build(); userRepresentation.ApplyPatches(new List <SCIMPatchOperationRequest> { new SCIMPatchOperationRequest(SCIMPatchOperations.REPLACE, "userName", "cassandra"), new SCIMPatchOperationRequest(SCIMPatchOperations.ADD, "phones", JArray.Parse("[{ phoneNumber : '03', type: 'type1' }, { phoneNumber : '05', type: 'type2' }]")), new SCIMPatchOperationRequest(SCIMPatchOperations.REMOVE, "phones[phoneNumber eq 01]") }, false); Assert.Equal("cassandra", userRepresentation.Attributes.First(a => a.SchemaAttribute.Name == "userName").ValuesString.First()); Assert.True(userRepresentation.Attributes.Any(a => a.SchemaAttribute.Name == "phones" && a.Values.Any(b => b.SchemaAttribute.Name == "phoneNumber" && b.ValuesString.Contains("03"))) == true); Assert.True(userRepresentation.Attributes.Any(a => a.SchemaAttribute.Name == "phones" && a.Values.Any(b => b.SchemaAttribute.Name == "phoneNumber" && b.ValuesString.Contains("05"))) == true); Assert.True(userRepresentation.Attributes.Any(a => a.SchemaAttribute.Name == "phones" && a.Values.Any(b => b.SchemaAttribute.Name == "phoneNumber" && b.ValuesString.Contains("01"))) == false); }
public void When_Extract_Attributes() { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", "User Account") .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .Build(); var userRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { userSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "john" }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "01" }); b.AddStringAttribute("type", new List <string> { "mobile" }); }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "02" }); b.AddStringAttribute("type", new List <string> { "home" }); }) .Build(); var firstFilter = SCIMFilterParser.Parse("phones.phoneNumber", new List <SCIMSchema> { userSchema }); var secondFilter = SCIMFilterParser.Parse("phones[phoneNumber eq 02]", new List <SCIMSchema> { userSchema }); var thirdFilter = SCIMFilterParser.Parse("userName", new List <SCIMSchema> { userSchema }); var fourthFilter = SCIMFilterParser.Parse("phones.phoneNumber", new List <SCIMSchema> { userSchema }); var fifthFilter = SCIMFilterParser.Parse("phones[phoneNumber eq 02]", new List <SCIMSchema> { userSchema }); var sixFilter = SCIMFilterParser.Parse("meta.lastModified", new List <SCIMSchema> { userSchema }); var sevenFilter = SCIMFilterParser.Parse("meta.lastModified", new List <SCIMSchema> { userSchema }); var eightFilter = SCIMFilterParser.Parse("id", new List <SCIMSchema> { userSchema }); var nineFilter = SCIMFilterParser.Parse("id", new List <SCIMSchema> { userSchema }); var firstJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { firstFilter }); var secondJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { secondFilter }); var thirdJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { thirdFilter }, "http://localhost"); var fourthJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { fourthFilter }, "http://localhost"); var fifthJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { fifthFilter }, "http://localhost"); var sixJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { sixFilter }); var sevenJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { sevenFilter }, "http://localhost"); var eightJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { eightFilter }, "http://localhost"); var nineJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { nineFilter }); Assert.Equal("01", firstJSON.SelectToken("phones[0].phoneNumber").ToString()); Assert.Equal("02", secondJSON.SelectToken("phones[0].phoneNumber").ToString()); Assert.Equal("home", secondJSON.SelectToken("phones[0].type").ToString()); Assert.Null(thirdJSON.SelectToken("userName")); Assert.Null(fourthJSON.SelectToken("phones[0].phoneNumber")); Assert.True((fifthJSON.SelectToken("phones") as JArray).Count == 1); Assert.NotNull(sixJSON.SelectToken("meta.lastModified")); Assert.Null(sevenJSON.SelectToken("meta.lastModified")); Assert.NotNull(eightJSON.SelectToken("id")); Assert.NotNull(nineJSON.SelectToken("id")); }
public void When_Parse_And_Execute_Filter() { var customSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:CustomProperties", "User", SCIMEndpoints.User, "Custom properties", false) .AddDecimalAttribute("age") .AddBinaryAttribute("eidCertificate") .AddStringAttribute("filePath") .Build(); var schema = StandardSchemas.UserSchema; var representation = new SCIMRepresentation { Id = Guid.NewGuid().ToString(), LastModified = DateTime.Parse("2010-05-13T04:42:34Z") }; var secondRepresentation = new SCIMRepresentation { Id = Guid.NewGuid().ToString(), LastModified = DateTime.Parse("2012-05-13T04:42:34Z"), Version = 2 }; var thirdRepresentation = new SCIMRepresentation { Id = Guid.NewGuid().ToString() }; representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("title"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "title" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), customSchema.GetAttribute("age"), customSchema.Id) { Id = Guid.NewGuid().ToString(), ValueDecimal = 20 }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), customSchema.GetAttribute("eidCertificate"), customSchema.Id) { Id = Guid.NewGuid().ToString(), ValueBinary = "aGVsbG8=" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), customSchema.GetAttribute("filePath"), customSchema.Id) { Id = Guid.NewGuid().ToString(), ValueString = @"C:\Program Files (x86)\Internet Explorer" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("userType"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "Employee" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("emails"), schema.Id)); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("emails.value"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "example.org" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("emails.type"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "work" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("phoneNumbers"), schema.Id)); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("phoneNumbers.primary"), schema.Id) { ValueBoolean = true }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("userName"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "bjensen" }); representation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("name.familyName"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "O'Malley" }); secondRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("userName"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "Justine" }); secondRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("userType"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "Intern" }); thirdRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("userName"), schema.Id) { Id = Guid.NewGuid().ToString(), ValueString = "Jule" }); thirdRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("ims"), schema.Id)); thirdRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("ims.type"), schema.Id) { ValueString = "xmpp" }); thirdRepresentation.AddAttribute(new SCIMRepresentationAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), schema.GetAttribute("ims.value"), schema.Id) { ValueString = "foo.com" }); var representations = new List <SCIMRepresentation> { representation, secondRepresentation, thirdRepresentation }; var firstResult = ParseAndExecuteFilter(representations.AsQueryable(), "userName eq \"bjensen\"", customSchema); var secondResult = ParseAndExecuteFilter(representations.AsQueryable(), "name.familyName co \"O'Malley\"", customSchema); var thirdResult = ParseAndExecuteFilter(representations.AsQueryable(), "userName sw \"J\"", customSchema); var fourthResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr", customSchema); var fifthResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified gt \"2011-05-13T04:42:34Z\"", customSchema); var sixResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified ge \"2011-05-13T04:42:34Z\"", customSchema); var sevenResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified lt \"2011-05-13T04:42:34Z\"", customSchema); var eightResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified le \"2011-05-13T04:42:34Z\"", customSchema); var nineResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr and userType eq \"Employee\"", customSchema); var tenResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr or userType eq \"Intern\"", customSchema); var elevenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and (emails.value co \"example.org\" or emails.value co \"example.org\")", customSchema); var twelveResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType ne \"Employee\" and not (emails co \"example.com\" or emails.value co \"example.org\")", customSchema); var thirteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and (emails.type eq \"work\")", customSchema); var fourteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and emails[type eq \"work\" and value co \"example.org\"]", customSchema); var fifteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "emails[type eq \"work\" and value co \"example.org\"] or ims[type eq \"xmpp\" and value co \"foo.com\"]", customSchema); var sixteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified gt \"2011-05-13T04:42:34Z\" and meta.version eq \"2\"", customSchema); var seventeenResult = ParseAndExecuteFilter(representations.AsQueryable(), "phoneNumbers[primary eq \"true\"]", customSchema); var eighteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "age gt 15", customSchema); var nineteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "eidCertificate eq \"aGVsbG8=\"", customSchema); var twentyResult = ParseAndExecuteFilter(representations.AsQueryable(), "filePath eq \"C:\\Program Files (x86)\\Internet Explorer\"", customSchema); var twentyOneResult = ParseAndExecuteFilter(representations.AsQueryable(), "urn:ietf:params:scim:schemas:core:2.0:User:userName eq \"bjensen\"", customSchema); var thirtyResult = ParseAndExecuteFilter(representations.AsQueryable(), "urn:ietf:params:scim:schemas:core:2.0:User:name.familyName co \"O'Malley\"", customSchema); Assert.Equal(1, firstResult.Count()); Assert.Equal(1, secondResult.Count()); Assert.Equal(2, thirdResult.Count()); Assert.Equal(1, fourthResult.Count()); Assert.Equal(1, fifthResult.Count()); Assert.Equal(1, sixResult.Count()); Assert.Equal(2, sevenResult.Count()); Assert.Equal(2, eightResult.Count()); Assert.Equal(1, nineResult.Count()); Assert.Equal(2, tenResult.Count()); Assert.Equal(1, elevenResult.Count()); Assert.Equal(1, twelveResult.Count()); Assert.Equal(1, thirteenResult.Count()); Assert.Equal(1, fourteenResult.Count()); Assert.Equal(2, fifteenResult.Count()); Assert.Equal(1, sixteenResult.Count()); Assert.Equal(1, seventeenResult.Count()); Assert.Equal(1, eighteenResult.Count()); Assert.Equal(1, nineteenResult.Count()); Assert.Equal(1, twentyResult.Count()); Assert.Equal(1, twentyOneResult.Count()); Assert.Equal(1, thirtyResult.Count()); }
public void When_Parse_And_Execute_Filter() { var customSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:CustomProperties", "User", SimpleIdServer.Scim.SCIMConstants.SCIMEndpoints.User, "Custom properties", false) .AddDecimalAttribute("age") .AddBinaryAttribute("eidCertificate") .Build(); var firstRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { SCIMConstants.StandardSchemas.UserSchema, customSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "bjensen" }) .AddBooleanAttribute("active", "urn:ietf:params:scim:schemas:core:2.0:User", new List <bool> { true }) .AddDecimalAttribute("age", "urn:ietf:params:scim:schemas:core:2.0:CustomProperties", new List <decimal> { 22 }) .AddBinaryAttribute("eidCertificate", "urn:ietf:params:scim:schemas:core:2.0:CustomProperties", new List <string> { "aGVsbG8=" }) .AddStringAttribute("title", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "title" }) .AddStringAttribute("userType", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "Employee" }) .AddComplexAttribute("emails", "urn:ietf:params:scim:schemas:core:2.0:User", (c) => { c.AddStringAttribute("value", new List <string> { "example.com" }); c.AddStringAttribute("type", new List <string> { "work" }); }) .AddComplexAttribute("emails", "urn:ietf:params:scim:schemas:core:2.0:User", (c) => { c.AddStringAttribute("value", new List <string> { "example.org" }); }) .AddComplexAttribute("name", "urn:ietf:params:scim:schemas:core:2.0:User", (r) => { r.AddStringAttribute("familyName", new List <string> { "O'Malley" }); }) .Build(); firstRepresentation.LastModified = DateTime.Parse("2012-05-13T04:42:34Z"); firstRepresentation.Version = "2"; var secondRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { SCIMConstants.StandardSchemas.UserSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "Justine" }) .AddStringAttribute("title", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "title" }) .AddStringAttribute("userType", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "Intern" }) .AddComplexAttribute("ims", "urn:ietf:params:scim:schemas:core:2.0:User", (c) => { c.AddStringAttribute("type", new List <string> { "xmpp" }); c.AddStringAttribute("value", new List <string> { "foo.com" }); }) .AddComplexAttribute("emails", "urn:ietf:params:scim:schemas:core:2.0:User", (c) => { c.AddStringAttribute("value", new List <string> { "example.be" }); }) .Build(); secondRepresentation.LastModified = DateTime.Parse("2010-05-13T04:42:34Z"); var representations = new List <SCIMRepresentation> { firstRepresentation, secondRepresentation }; var otherResult = ParseAndExecuteFilter(representations.AsQueryable(), "emails co \"example.com\""); var firstResult = ParseAndExecuteFilter(representations.AsQueryable(), "userName eq \"bjensen\""); var secondResult = ParseAndExecuteFilter(representations.AsQueryable(), "name.familyName co \"O'Malley\""); var thirdResult = ParseAndExecuteFilter(representations.AsQueryable(), "userName sw \"J\""); var fourthResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr"); var fifthResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified gt \"2011-05-13T04:42:34Z\""); var sixResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified ge \"2011-05-13T04:42:34Z\""); var sevenResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified lt \"2011-05-13T04:42:34Z\""); var eightResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified le \"2011-05-13T04:42:34Z\""); var nineResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr and userType eq \"Employee\""); var tenResult = ParseAndExecuteFilter(representations.AsQueryable(), "title pr or userType eq \"Intern\""); var elevenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and (emails.value co \"example.org\" or emails.value co \"example.org\")"); var twelveResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType ne \"Employee\" and not (emails co \"example.com\" or emails.value co \"example.org\")"); var thirteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and (emails.type eq \"work\")"); var fourteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "userType eq \"Employee\" and emails[type eq \"work\" and value co \"example.com\"]"); var fifteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "emails[type eq \"work\" and value co \"example.com\"] or ims[type eq \"xmpp\" and value co \"foo.com\"]"); var sixteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified gt \"2011-05-13T04:42:34Z\" and meta.version eq \"2\""); var seventeenResult = ParseAndExecuteFilter(representations.AsQueryable(), "meta.lastModified pr"); var eighteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "age gt 15"); var nineteenResult = ParseAndExecuteFilter(representations.AsQueryable(), "eidCertificate eq \"aGVsbG8=\""); Assert.Equal(1, firstResult.Count()); Assert.Equal(1, secondResult.Count()); Assert.Equal(1, thirdResult.Count()); Assert.Equal(2, fourthResult.Count()); Assert.Equal(1, fifthResult.Count()); Assert.Equal(1, sixResult.Count()); Assert.Equal(1, sevenResult.Count()); Assert.Equal(1, eightResult.Count()); Assert.Equal(1, nineResult.Count()); Assert.Equal(2, tenResult.Count()); Assert.Equal(1, elevenResult.Count()); Assert.Equal(1, twelveResult.Count()); Assert.Equal(1, thirteenResult.Count()); Assert.Equal(1, fourteenResult.Count()); Assert.Equal(2, fifteenResult.Count()); Assert.Equal(1, sixteenResult.Count()); Assert.Equal(2, seventeenResult.Count()); Assert.Equal(1, eighteenResult.Count()); Assert.Equal(1, nineteenResult.Count()); }
public void When_Apply_Patch_To_SCIM_Representation() { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", "User Account") .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddStringAttribute("firstName") .AddStringAttribute("lastName") .AddStringAttribute("roles", multiValued: true) .AddStringAttribute("familyName") .AddComplexAttribute("adRoles", opt => { opt.AddStringAttribute("display"); opt.AddStringAttribute("value"); }, multiValued: true) .AddComplexAttribute("attributes", opt => { opt.AddStringAttribute("title"); opt.AddComplexAttribute("subattributes", sopt => { sopt.AddStringAttribute("str"); sopt.AddStringAttribute("sstr"); }, multiValued: true); opt.AddComplexAttribute("subtitle", sopt => { sopt.AddStringAttribute("str"); }); }, multiValued: true) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .Build(); var userRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { userSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "john" }) .AddStringAttribute("lastName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "lastName" }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "01" }); b.AddStringAttribute("type", new List <string> { "mobile" }); }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "02" }); b.AddStringAttribute("type", new List <string> { "home" }); }) .AddComplexAttribute("attributes", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("title", new List <string> { "title" }); b.AddComplexAttribute("subattributes", (sb) => { sb.AddStringAttribute("str", new List <string> { "1" }); }); b.AddComplexAttribute("subtitle", (sb) => { sb.AddStringAttribute("str", new List <string> { "1" }); }); }) .AddComplexAttribute("attributes", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("title", new List <string> { "secondTitle" }); b.AddComplexAttribute("subattributes", (sb) => { sb.AddStringAttribute("str", new List <string> { "1" }); }); }) .AddComplexAttribute("adRoles", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("display", new List <string> { "display" }); b.AddStringAttribute("value", new List <string> { "user1" }); }) .AddComplexAttribute("adRoles", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("value", new List <string> { "user2" }); }) .AddComplexAttribute("adRoles", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("value", new List <string> { "user3" }); }) .Build(); userRepresentation.ApplyPatches(new List <PatchOperationParameter> { new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Path = "phones.phoneNumber", Value = "NEWPHONE" }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Path = "userName", Value = "cassandra" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "phones", Value = JArray.Parse("[{ phoneNumber : '03', type: 'type1' }, { phoneNumber : '05', type: 'type2' }]") }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Path = "phones[phoneNumber eq 03].type", Value = "newType" }, new PatchOperationParameter { Operation = SCIMPatchOperations.REMOVE, Path = "phones[phoneNumber eq 01]" }, new PatchOperationParameter { Operation = SCIMPatchOperations.REMOVE, Path = "phones[phoneNumber eq 03].phoneNumber" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "familyName", Value = "familyName" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "familyName", Value = "updatedFamilyName" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "roles", Value = "firstRole" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "roles", Value = "secondRole" }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Value = JObject.Parse("{ 'firstName' : 'firstName' }") }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Value = JObject.Parse("{ 'lastName' : 'updatedLastName' }") }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Value = JObject.Parse("{ 'phoneNumber': '06', 'type': 'mobile' }"), Path = "phones" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "attributes[title eq title].subattributes", Value = JObject.Parse("{ 'str' : '2' }") }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "attributes[title eq title].subtitle", Value = JObject.Parse("{ 'str' : '2' }") }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Path = "attributes[title eq secondTitle].subattributes", Value = JObject.Parse("{ 'str' : '3' }") }, new PatchOperationParameter { Operation = SCIMPatchOperations.REPLACE, Path = "adRoles.display", Value = "NEWUSER" }, new PatchOperationParameter { Operation = SCIMPatchOperations.ADD, Path = "adRoles[value eq user3].display", Value = "NEWUSER3" } }, false); Assert.True(userRepresentation.FlatAttributes.Count(a => a.SchemaAttribute.FullPath == "adRoles.display" && a.ValueString == "NEWUSER") == 2); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "adRoles.value" && a.ValueString == "user1") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "adRoles.value" && a.ValueString == "user2") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "adRoles.value" && a.ValueString == "user3") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "adRoles.display" && a.ValueString == "NEWUSER3") == true); Assert.Equal("cassandra", userRepresentation.FlatAttributes.First(a => a.SchemaAttribute.Name == "userName").ValueString); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "phoneNumber" && a.ValueString == "03") == false); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "phoneNumber" && a.ValueString == "05") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "phoneNumber" && a.ValueString == "01") == false); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "phoneNumber" && a.ValueString == "06") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "familyName" && a.ValueString == "updatedFamilyName") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "roles" && a.ValueString == "firstRole") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "roles" && a.ValueString == "secondRole") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "userName" && a.ValueString == "cassandra") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.Name == "lastName" && a.ValueString == "updatedLastName") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "attributes.subattributes.str" && a.ValueString == "2") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "attributes.subtitle.str" && a.ValueString == "2") == true); Assert.True(userRepresentation.FlatAttributes.Any(a => a.SchemaAttribute.FullPath == "attributes.subattributes.str" && a.ValueString == "3") == true); }
public void ConfigureServices(IServiceCollection services) { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", SCIMResourceTypes.User, "User Account", true) .AddStringAttribute("userName", required: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE, caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("name", c => { c.AddStringAttribute("formatted", description: "The full name"); c.AddStringAttribute("familyName", description: "The family name"); c.AddStringAttribute("givenName", description: "The given name"); }, description: "The components of the user's real name.") .AddStringAttribute("roles", multiValued: true) .AddDecimalAttribute("age") .AddDateTimeAttribute("birthDate") .AddBooleanAttribute("active") .AddStringAttribute("duplicateAttr") .AddIntAttribute("nbPoints") .AddStringAttribute("organizationId") .AddBinaryAttribute("eidCertificate") .AddComplexAttribute("subImmutableComplex", opt => { opt.AddStringAttribute("value", mutability: SCIMSchemaAttributeMutabilities.IMMUTABLE); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddComplexAttribute("complexImmutable", opt => { opt.AddStringAttribute("value", description: "Phone number"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.IMMUTABLE) .AddComplexAttribute("emails", opt => { opt.AddStringAttribute("value"); opt.AddStringAttribute("display"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddStringAttribute("immutable", mutability: SCIMSchemaAttributeMutabilities.IMMUTABLE) .AddComplexAttribute("groups", opt => { opt.AddStringAttribute("value", mutability: SCIMSchemaAttributeMutabilities.READONLY); opt.AddStringAttribute("display", mutability: SCIMSchemaAttributeMutabilities.READONLY); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READONLY) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddComplexAttribute("adRoles", opt => { opt.AddStringAttribute("value", description: "Value"); opt.AddStringAttribute("display", description: "Display"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddComplexAttribute("scores", opt => { opt.AddComplexAttribute("math", sopt => { sopt.AddIntAttribute("score"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE); }, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddStringAttribute("type", canonicalValues: new List <string> { "manager", "employee" }) .AddStringAttribute("org", defaultValue: new List <string> { "ENTREPRISE" }, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .AddSCIMSchemaExtension("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", true) .Build(); var enterpriseUser = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", "EnterpriseUser", "EnterpriseUser", string.Empty, false) .AddStringAttribute("employeeNumber", required: true) .AddStringAttribute("duplicateAttr") .Build(); var entitlementSchema = SCIMSchemaBuilder.Create("urn:entitlement", "Entitlement", "Entitlement", string.Empty, true) .AddStringAttribute("displayName") .AddComplexAttribute("members", opt => { opt.AddStringAttribute("value"); opt.AddReferenceAttribute("$ref"); opt.AddStringAttribute("type"); }, multiValued: true) .Build(); var customUserSchema = SCIMSchemaBuilder.Create("urn:customuser", "CustomUser", "CustomUser", string.Empty, true) .AddStringAttribute("userName", required: true) .AddComplexAttribute("entitlements", opt => { opt.AddStringAttribute("value"); opt.AddReferenceAttribute("$ref"); opt.AddStringAttribute("type"); opt.AddStringAttribute("display"); }, multiValued: true) .Build(); var schemas = new List <SCIMSchema> { userSchema, enterpriseUser, StandardSchemas.GroupSchema, entitlementSchema, customUserSchema }; var attributesMapping = new List <SCIMAttributeMapping> { new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = userSchema.Attributes.First(a => a.Name == "groups").Id, SourceResourceType = userSchema.ResourceType, SourceAttributeSelector = "groups", TargetResourceType = StandardSchemas.GroupSchema.ResourceType, TargetAttributeId = StandardSchemas.GroupSchema.Attributes.First(a => a.Name == "members").Id }, new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = StandardSchemas.GroupSchema.Attributes.First(a => a.Name == "members").Id, SourceResourceType = StandardSchemas.GroupSchema.ResourceType, SourceAttributeSelector = "members", TargetResourceType = userSchema.ResourceType, TargetAttributeId = userSchema.Attributes.First(a => a.Name == "groups").Id }, new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = customUserSchema.Attributes.First(a => a.Name == "entitlements").Id, SourceResourceType = "CustomUser", SourceAttributeSelector = "entitlements", TargetResourceType = "Entitlement", TargetAttributeId = entitlementSchema.Attributes.First(a => a.Name == "members").Id }, new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = entitlementSchema.Attributes.First(a => a.Name == "members").Id, SourceResourceType = "Entitlement", SourceAttributeSelector = "members", TargetResourceType = "CustomUser", TargetAttributeId = customUserSchema.Attributes.First(a => a.Name == "entitlements").Id } }; services.AddMvc(o => { o.EnableEndpointRouting = false; o.ValueProviderFactories.Insert(0, new SeparatedQueryStringValueProviderFactory(",")); }).AddNewtonsoftJson(o => { }); services.AddAuthorization(opts => opts.AddDefaultSCIMAuthorizationPolicy()); services.AddAuthentication(SCIMConstants.AuthenticationScheme).AddCustomAuthentication(c => { }); services.AddSIDScim(o => { o.MaxOperations = 3; o.IgnoreUnsupportedCanonicalValues = false; }) .AddSchemas(schemas) .AddAttributeMapping(attributesMapping); }
public void ConfigureServices(IServiceCollection services) { var json = File.ReadAllText("oauth_puk.txt"); var dic = JsonConvert.DeserializeObject <Dictionary <string, string> >(json); var rsaParameters = new RSAParameters { Modulus = dic.TryGet(RSAFields.Modulus), Exponent = dic.TryGet(RSAFields.Exponent) }; var oauthRsaSecurityKey = new RsaSecurityKey(rsaParameters); services.AddMvc(o => { o.EnableEndpointRouting = false; o.AddSCIMValueProviders(); }).AddNewtonsoftJson(o => { }); services.AddLogging(opt => { opt.AddConsole(); opt.AddFilter((s, l) => { return(s.StartsWith("SimpleIdServer.Scim")); }); }); services.AddAuthorization(opts => { opts.AddPolicy("QueryScimResource", p => p.RequireAssertion(_ => true)); opts.AddPolicy("AddScimResource", p => p.RequireAssertion(_ => true)); opts.AddPolicy("DeleteScimResource", p => p.RequireAssertion(_ => true)); opts.AddPolicy("UpdateScimResource", p => p.RequireAssertion(_ => true)); opts.AddPolicy("BulkScimResource", p => p.RequireAssertion(_ => true)); opts.AddPolicy("UserAuthenticated", p => p.RequireAssertion(_ => true)); opts.AddPolicy("Provison", p => p.RequireAssertion(_ => true)); }); services.AddAuthentication(SCIMConstants.AuthenticationScheme) .AddJwtBearer(SCIMConstants.AuthenticationScheme, cfg => { cfg.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = "https://localhost:60000", ValidAudiences = new List <string> { "scimClient", "gatewayClient" }, ValidateIssuerSigningKey = true, IssuerSigningKey = oauthRsaSecurityKey }; }); var basePath = Path.Combine(_webHostEnvironment.ContentRootPath, "Schemas"); var userSchema = SCIMSchemaExtractor.Extract(Path.Combine(basePath, "UserSchema.json"), SCIMResourceTypes.User, true); var enterpriseUserSchema = SCIMSchemaExtractor.Extract(Path.Combine(basePath, "EnterpriseUserSchema.json"), SCIMResourceTypes.User); var groupSchema = SCIMSchemaExtractor.Extract(Path.Combine(basePath, "GroupSchema.json"), SCIMResourceTypes.Group, true); var customResource = SCIMSchemaBuilder.Create("urn:customresource", "CustomResource", "CustomResource", string.Empty, true) .AddStringAttribute("name") .AddStringAttribute("lastname") .AddDateTimeAttribute("birthDate") .Build(); var entitlementSchema = SCIMSchemaBuilder.Create("urn:entitlement", "Entitlement", "Entitlement", string.Empty, true) .AddStringAttribute("displayName") .AddComplexAttribute("members", opt => { opt.AddStringAttribute("value"); opt.AddStringAttribute("$ref"); opt.AddStringAttribute("type"); }, multiValued: true) .Build(); var customUserSchema = SCIMSchemaBuilder.Create("urn:customuser", "CustomUser", "CustomUser", string.Empty, true) .AddStringAttribute("userName", required: true) .AddComplexAttribute("entitlements", opt => { opt.AddStringAttribute("value"); opt.AddStringAttribute("$ref"); opt.AddStringAttribute("type"); }, multiValued: true) .Build(); userSchema.SchemaExtensions.Add(new SCIMSchemaExtension { Id = Guid.NewGuid().ToString(), Schema = enterpriseUserSchema.Id }); var schemas = new List <SCIMSchema> { userSchema, groupSchema, enterpriseUserSchema, customResource, entitlementSchema, customUserSchema }; services.AddSwaggerGen(c => { var currentAssembly = Assembly.GetExecutingAssembly(); var xmlDocs = currentAssembly.GetReferencedAssemblies() .Union(new AssemblyName[] { currentAssembly.GetName() }) .Select(a => Path.Combine(Path.GetDirectoryName(currentAssembly.Location), $"{a.Name}.xml")) .Where(f => File.Exists(f)).ToArray(); Array.ForEach(xmlDocs, (d) => { c.IncludeXmlComments(d); }); }); services.AddSCIMSwagger(); services.AddMassTransitHostedService(true); services.AddSIDScim(options: _ => { _.IgnoreUnsupportedCanonicalValues = false; }) .AddSchemas(schemas) .AddAttributeMapping(new List <SCIMAttributeMapping> { new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = userSchema.Attributes.First(a => a.Name == "groups").Id, SourceResourceType = StandardSchemas.UserSchema.ResourceType, SourceAttributeSelector = "groups", TargetResourceType = StandardSchemas.GroupSchema.ResourceType, TargetAttributeId = groupSchema.Attributes.First(a => a.Name == "members").Id }, new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = customUserSchema.Attributes.First(a => a.Name == "entitlements").Id, SourceResourceType = "CustomUser", SourceAttributeSelector = "entitlements", TargetResourceType = "Entitlement", TargetAttributeId = entitlementSchema.Attributes.First(a => a.Name == "members").Id }, new SCIMAttributeMapping { Id = Guid.NewGuid().ToString(), SourceAttributeId = entitlementSchema.Attributes.First(a => a.Name == "members").Id, SourceResourceType = "Entitlement", SourceAttributeSelector = "members", TargetResourceType = "CustomUser", TargetAttributeId = customUserSchema.Attributes.First(a => a.Name == "entitlements").Id } }); }