Fix organization invitation endpoints to return 201 with Location header - #51558
Fix organization invitation endpoints to return 201 with Location header#51558SaadAhmed7 wants to merge 3 commits into
Conversation
…tion header
The invitation endpoints (invite-user, invite-existing-user, resend) were
returning HTTP 204 No Content. Per REST conventions, resource creation
should return 201 Created with a Location header pointing to the new
resource. The Location header now points to the invitation resource at
/admin/realms/{realm}/organizations/{orgId}/invitations/{invitationId}.
Closes keycloak#51298
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates organization invitation creation and resend endpoints to follow REST resource-creation semantics.
Changes:
- Returns
201 Createdwith the new invitation’sLocation. - Updates OpenAPI response annotations from 204 to 201.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
OrganizationMemberResource.java |
Updates invitation endpoint response documentation. |
OrganizationInvitationResource.java |
Builds the invitation URI and returns it with 201 responses. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| .path("invitations") | ||
| .path(invitation.getId()) | ||
| .build(); | ||
| return Response.created(location).build(); |
Update OrganizationInvitationManagementTest and OrganizationInvitationLinkTest to expect HTTP 201 Created for invite-user, invite-existing-user, and resend endpoints. Delete endpoint assertions remain at 204 No Content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
services/src/main/java/org/keycloak/organization/admin/resource/OrganizationInvitationResource.java:216
- The defining part of the new contract is still untested: the updated tests only assert
201, so a missing or malformedLocationheader (including one that retains the old ID after resend) would pass. Add assertions for all three endpoints thatresponse.getLocation()targets/admin/realms/{realm}/organizations/{orgId}/invitations/{newInvitationId}, with the resend assertion using the replacement invitation ID.
return Response.created(location).build();
Verify that invite and resend responses include a non-null Location header pointing to the correct invitations resource path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/OrganizationInvitationManagementTest.java:159
- The resend test only checks a path prefix, so it still passes if
Locationcontains the old or an unrelated invitation ID. Capture the returned path and compare its final segment withnewInvitationId, which is the key resend requirement from #51298.
assertThat(response.getLocation(), notNullValue());
assertThat(response.getLocation().getPath(), containsString("/organizations/" + organizationId + "/invitations/"));
Summary
Closes #51298
The organization invitation endpoints (
invite-user,invite-existing-user, andresend) were returning HTTP 204 No Content. Per REST conventions, creating a resource should return HTTP 201 Created with aLocationheader pointing to the newly created resource.Changes
OrganizationInvitationResource.sendInvitation(): ChangedResponse.noContent().build()toResponse.created(location).build(), where the Location URI points to/admin/realms/{realm}/organizations/{orgId}/invitations/{invitationId}@APIResponseannotations oninviteUser,inviteExistingUser, andresendInvitationfrom204 No Contentto201 CreatedAdminRoot.realmsUrl()following the existing Keycloak pattern used in other admin resources (OrganizationsResource,UsersResource,ClientsResource, etc.)Affected endpoints
POST /admin/realms/{realm}/organizations/{orgId}/members/invite-userPOST /admin/realms/{realm}/organizations/{orgId}/members/invite-existing-userPOST /admin/realms/{realm}/organizations/{orgId}/invitations/{id}/resend