Fix NPE in SCIM PATCH when request body contains "schemas": null - #51173
Fix NPE in SCIM PATCH when request body contains "schemas": null#51173sergioperezcheco wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Prevents SCIM PATCH requests with null schemas from causing HTTP 500 errors.
Changes:
- Adds null-safe PATCH schema validation.
- Adds regression coverage for null schemas.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
ScimResourceTypeResource.java |
Returns invalid-syntax HTTP 400 for null schemas. |
UserTest.java |
Adds regression test, but serialization omits the null field. |
| PatchRequest request = PatchRequest.create() | ||
| .add("active", "false") | ||
| .build(); | ||
| request.setSchemas(null); |
90ccc43 to
bb7a5f5
Compare
|
Good catch, thanks. You're right — PatchRequest has a class-level @JsonInclude(NON_NULL), so setSchemas(null) gets dropped during serialization and the server never sees the null. I've rewritten the test to send a raw PATCH with an explicit {"schemas": null, ...} JSON body over HTTP, so the deserialization path on the server side is actually exercised. |
| org.apache.http.client.methods.HttpPost tokenRequest = new org.apache.http.client.methods.HttpPost(tokenUrl); | ||
| tokenRequest.setHeader(HttpHeaders.CONTENT_TYPE, org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED.getMimeType()); | ||
| tokenRequest.setEntity(new StringEntity(tokenBody, org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED)); | ||
|
|
||
| String accessToken; | ||
| org.apache.http.HttpResponse tokenResponse = httpClient.execute(tokenRequest); | ||
| AccessTokenResponse atr = org.keycloak.util.JsonSerialization.readValue(tokenResponse.getEntity().getContent(), AccessTokenResponse.class); | ||
| accessToken = atr.getToken(); |
| String tokenBody = OAuth2Constants.GRANT_TYPE + "=" + OAuth2Constants.CLIENT_CREDENTIALS | ||
| + "&" + OAuth2Constants.CLIENT_ID + "=scim-client" | ||
| + "&" + OAuth2Constants.CLIENT_SECRET + "=secret"; |
| org.apache.http.HttpResponse response = httpClient.execute(patch); | ||
| assertEquals(400, response.getStatusLine().getStatusCode()); |
| Set<String> schemas = request.getSchemas(); | ||
| if (schemas == null || !schemas.contains(Scim.PATCH_OP_CORE_SCHEMA)) { | ||
| return invalidSyntax("No PATCH op schema provided in request"); | ||
| } |
ScimResourceTypeResource.patch() calls request.getSchemas().contains() without a null check. When a client sends a PATCH request body with "schemas": null, Jackson overwrites the default Set.of(SCHEMA) initializer in PatchRequest with null, and the .contains() call throws a NullPointerException resulting in HTTP 500 instead of a proper 400 Bad Request. Add a null check so a missing schemas set is treated the same as a schemas set without the PATCH op schema, returning invalidSyntax (400). Adds a test that sends a PATCH with a null schemas set and asserts the 400 response. Fixes keycloak#51156 Signed-off-by: sergioperezcheco <checo520@outlook.com>
bb7a5f5 to
0082a8c
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/UserTest.java:59
- None of these added imports should remain:
HttpClient,ContentType, andStringEntityare already imported below, whileHttpHeadersandHttpPatchare unused. Spotless'sremoveUnusedImports/import-order check runs in CI (pom.xml:1605-1610,.github/workflows/ci.yml:124-125), so this currently fails the formatting gate.
import org.apache.http.HttpHeaders;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
| import org.keycloak.OAuth2Constants; | ||
| import org.keycloak.representations.AccessTokenResponse; |
|
The parent issue was resolved. Please open a new bug issue if you think the fix was not sufficient. |
Sending a SCIM PATCH request whose body explicitly sets "schemas": null causes a NullPointerException and an HTTP 500 instead of the expected 400. Jackson deserializes the field as null, overwriting the default Set.of(SCHEMA) initializer in PatchRequest, and ScimResourceTypeResource.patch() then calls request.getSchemas().contains(Scim.PATCH_OP_CORE_SCHEMA) on the null set.
This adds a null check so a missing schemas set is treated identically to a schemas set lacking the PATCH op schema — both return invalidSyntax (400). Added a test that issues a PATCH with a null schemas set and asserts the 400 response.
Fixes #51156