pingidentity / scim2

The UnboundID SCIM 2.0 SDK for Java
176 stars 72 forks source link

Microsoft Azure AD appears to send patch operations with mixed case 'op' values #152

Closed tomqwpl closed 1 year ago

tomqwpl commented 3 years ago

Really, this appears to be a bug at the Microsoft end, this is perhaps more of an FYI. I can see nothing in the spec to suggest that mixed case operation names are allowed, nor equally in the JSON Patch spec.

The error we get is: Could not resolve type id 'Add' as a subtype ofcom.unboundid.scim2.common.messages.PatchOperation: known type ids = [add, remove, replace] (for POJO property 'Operations')\n at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 82] (through reference chain: com.unboundid.scim2.common.messages.PatchRequest[\"Operations\"]->java.util.ArrayList[0])"}.

So evidently, Microsoft Azure AD is sending a PATCH with an "op" value of "Add" and not "add"

The good news is that apparently Jackson now has MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES (certainly in 2.12 anyway -- https://github.com/FasterXML/jackson-databind/commit/e5d22e2a49d00b76564b0b48eae45898546da0de) and uses this when processing the @JsonSubTypes annotations. So it would be possible to work around this.

In the mean time, it's possible to work around the problem and do something like : var mf = new MapperFactory(); mf.setMapperCustomFeatures(Collections.singletonMap(MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES, true)); JsonUtils.setCustomMapperFactory(mf); which is what I've done.

dahuber-github commented 3 years ago

I resolved this by changing PatchOperation. I changed...

@JsonSubTypes({ @JsonSubTypes.Type(value = PatchOperation.AddOperation.class, name="add"), @JsonSubTypes.Type(value = PatchOperation.RemoveOperation.class, name="remove"), @JsonSubTypes.Type(value = PatchOperation.ReplaceOperation.class, name="replace") })

to

@JsonSubTypes({ @JsonSubTypes.Type(value = PatchOperation.AddOperation.class, name="add"), @JsonSubTypes.Type(value = PatchOperation.RemoveOperation.class, name="remove"), @JsonSubTypes.Type(value = PatchOperation.ReplaceOperation.class, name="replace"), @JsonSubTypes.Type(value = PatchOperation.AddOperation.class, name="Add"), @JsonSubTypes.Type(value = PatchOperation.RemoveOperation.class, name="Remove"), @JsonSubTypes.Type(value = PatchOperation.ReplaceOperation.class, name="Replace") })

I post this in hopes it helps the development team.

joachimLengacher commented 2 years ago

With a newer version of Jackson there is a names member in JsonSubTypes.Type which would allow to do something like

@JsonSubTypes({
    @JsonSubTypes.Type(value = PatchOperation.AddOperation.class,
        name="add", names = {"Add", "ADD"}),
    @JsonSubTypes.Type(value = PatchOperation.RemoveOperation.class,
        name="remove", names = {"Remove", "REMOVE"}),
    @JsonSubTypes.Type(value = PatchOperation.ReplaceOperation.class,
        name="replace", names = {"Replace", "REPLACE"})})
public abstract class PatchOperation
kqarryzada commented 1 year ago

This issue should be resolved with the 2.3.8 release. We've made the SDK more permissive so that it accepts these operation types.