Skip to content

[OID4VCI]: Enforce ownership validation when deleting issued verifiable credentials via the account API - #51418

Merged
pskopek merged 2 commits into
keycloak:mainfrom
adorsys:issue-50368
Aug 7, 2026
Merged

[OID4VCI]: Enforce ownership validation when deleting issued verifiable credentials via the account API#51418
pskopek merged 2 commits into
keycloak:mainfrom
adorsys:issue-50368

Conversation

@Awambeng

@Awambeng Awambeng commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

This PR fixes an object-level authorization gap in the account REST API where the delete endpoint for issued verifiable credentials performed a global primary-key lookup and removal without verifying ownership of the credential.

Key changes:

  • Added a user-scoped removeIssuedVerifiableCredential(userId, credentialId) method to the UserProvider SPI and UserVerifiableCredentialFederatedStorage, implemented with an atomic lock-protected ownership check in the JPA local and federated providers.
  • Routed scoped credential removal through UserStorageManager and UserCacheSession, preserving local and federated storage handling.
  • Updated AccountIssuedVerifiableCredentialResource#delete to remove only credentials owned by the authenticated user and return 404 for unauthorized access, matching the list endpoint authorization behavior.
  • Added integration tests covering cross-user deletion attempts, successful owner deletion, and missing-role authorization checks.

Closes #50368

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Scopes issued credential deletion to the authenticated owner across local, federated, and cached storage paths.

Changes:

  • Adds user-scoped removal APIs and provider implementations.
  • Updates the account DELETE endpoint to return 404 for non-owned credentials.
  • Adds ownership and role authorization tests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/base/src/test/java/org/keycloak/tests/admin/user/FederatedIssuedVerifiableCredentialTest.java Tests federated ownership enforcement.
tests/base/src/test/java/org/keycloak/tests/account/AccountRestServiceRolesTest.java Tests account API deletion authorization.
services/src/main/java/org/keycloak/services/resources/account/AccountIssuedVerifiableCredentialResource.java Uses owner-scoped deletion.
server-spi/src/main/java/org/keycloak/models/UserProvider.java Adds the scoped removal SPI.
model/storage/src/main/java/org/keycloak/storage/federated/UserVerifiableCredentialFederatedStorage.java Adds scoped federated removal.
model/storage-private/src/main/java/org/keycloak/storage/UserStorageManager.java Routes removal by storage type.
model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java Implements federated ownership checks.
model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java Implements locked local removal.
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java Delegates scoped removal through caching.

- Add user-scoped removeIssuedVerifiableCredential(userId, credentialId) to UserProvider SPI and federated storage interface
- Implement ownership-checked removal in JpaUserProvider and JpaUserFederatedStorageProvider
- Route scoped removal through UserStorageManager and UserCacheSession
- Restrict AccountIssuedVerifiableCredentialResource deletion to the authenticated user
- Add integration tests for cross-user, owner, and missing-role deletion scenarios

Closes keycloak#50368

Signed-off-by: Awambeng Rodrick <awambengrodrick@gmail.com>
Signed-off-by: Awambeng Rodrick <awambengrodrick@gmail.com>
Copilot AI review requested due to automatic review settings August 4, 2026 09:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@jimmychakkalakal jimmychakkalakal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the ownership enforcement fix across all storage layers. The approach is correct — atomic check-then-delete with PESSIMISTIC_WRITE, consistent routing via StorageId.isLocalStorage, and no information leakage (404 for both "not found" and "not owned"). Test coverage is solid.

Two observations for follow-up (not blocking):

  1. The admin API endpoint UserVerifiableCredentialResource.revokeIssuedCredential has the same unscoped deletion pattern — an admin authorized for User A could delete User B's credential by ID. Lower severity but same class of vulnerability.
  2. The old single-arg removeIssuedVerifiableCredential(String) in the SPI could benefit from a @Deprecated annotation or Javadoc warning to prevent future user-facing code from accidentally using the unscoped version.

@jimmychakkalakal jimmychakkalakal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix. Good fix with test coverage. I approve the PR.

@VinodAnandan

Copy link
Copy Markdown
Contributor

@ahus1, @pskopek: As @mposolda is currently on holiday, could you please help us with merging of this PR when you get a chance? Your help would be greatly appreciated !

@pskopek
pskopek merged commit d60cebd into keycloak:main Aug 7, 2026
92 checks passed
@Awambeng
Awambeng deleted the issue-50368 branch August 7, 2026 12:09
@ahus1

ahus1 commented Aug 7, 2026

Copy link
Copy Markdown
Member

@VinodAnandan - please don't share people's holidays in public forums, this is avoidable OSINT. When there is a need to share any urgency, share it in a private channel. Once Marek is back, agree on a stand-in.

Looking at the test cases, there are IMHO things that would be worth reviewing in follow-up steps:

  • They are using quite a lot runOnServer for "arrange" steps (creating VCs), and for the federation also to "act". This might then miss issues in requests using APIs. I'd usually suggest to maybe use them when no external API is available for something.

  • The assertDeleteEndpointStatus constructs a manual HTTP request, which might be better handled in a common helper. Maybe @lhanusov or @vaceksimon can provide some hints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OID4VCI: Account API delete endpoint for issued verifiable credentials missing ownership validation

6 participants