Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@namanONcode
Copy link
Contributor

@namanONcode namanONcode commented Jan 27, 2026

This pull request enhances the flexibility and correctness of the OID4VC issuer metadata by allowing credential builders to contribute format-specific metadata to the well-known endpoint. It introduces a new extension point in the CredentialBuilder interface, updates the issuer provider to use it, and adds targeted tests to ensure correct metadata exposure for different credential formats.

Format-specific metadata contribution:

  • Added a new contributeToMetadata method to the CredentialBuilder interface, enabling each credential format to customize the metadata it exposes in the well-known endpoint. Default implementation is a no-op for backward compatibility.
  • Implemented contributeToMetadata in JwtCredentialBuilder and SdJwtCredentialBuilder to ensure only relevant fields (credential_definition or vct) are present in the metadata for each format. [1] [2]

Provider logic updates:

  • Updated OID4VCIssuerWellKnownProvider to invoke contributeToMetadata for each supported credential configuration, using the factory pattern to obtain the correct builder for each format. This ensures that only format-appropriate metadata fields are included. [1] [2]

Testing:

  • Added CredentialMetadataWellKnownTest to verify that the well-known endpoint exposes the correct metadata for SD-JWT and JWT-VC credential types, ensuring that only the appropriate fields are present for each format.

These changes improve extensibility, ensure compliance with OID4VCI metadata requirements, and prevent leaking irrelevant metadata fields for unsupported formats.

Closes #45485

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request addresses inconsistencies in the OID4VCI well-known metadata endpoint by introducing format-specific metadata filtering. The PR adds a new extension point to allow credential builders to customize which metadata fields are exposed for each credential format, ensuring compliance with format-specific requirements.

Changes:

  • Added contributeToMetadata() method to the CredentialBuilder interface as an extension point for format-specific metadata customization
  • Implemented metadata filtering in JwtCredentialBuilder (removes vct field) and SdJwtCredentialBuilder (removes credential_definition field) to ensure only format-appropriate fields are present
  • Updated OID4VCIssuerWellKnownProvider to invoke the new extension point for each credential configuration using the factory pattern

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
CredentialBuilder.java Added new contributeToMetadata() interface method with default no-op implementation for backward compatibility
JwtCredentialBuilder.java Implemented contributeToMetadata() to remove vct field for JWT-VC format
SdJwtCredentialBuilder.java Implemented contributeToMetadata() to remove credential_definition field for SD-JWT-VC format
OID4VCIssuerWellKnownProvider.java Added applyFormatSpecificMetadata() method to apply format-specific metadata filtering using the credential builder factory pattern
CredentialMetadataWellKnownTest.java Added integration tests to verify correct metadata exposure for SD-JWT and JWT-VC credential types

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 497 to 513
try {
Map<String, Object> metadataMap = JsonSerialization.readValue(
JsonSerialization.writeValueAsString(config),
new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {}
);

credentialBuilder.contributeToMetadata(metadataMap);

if (!metadataMap.containsKey("vct")) {
config.setVct(null);
}
if (!metadataMap.containsKey("credential_definition")) {
config.setCredentialDefinition(null);
}
} catch (Exception e) {
LOGGER.warnf(e, "Failed to apply format-specific metadata for format: %s", format);
}
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

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

The serialize-deserialize approach used here is inefficient and fragile. The code serializes the entire SupportedCredentialConfiguration to JSON, deserializes it to a Map, allows the builder to modify the map, then checks the map to determine which fields to set to null on the original config object. This creates unnecessary overhead and complexity.

A more direct and maintainable approach would be to:

  1. Pass the SupportedCredentialConfiguration object directly to contributeToMetadata, or
  2. Have the builders return a set of field names to remove, or
  3. Have specific methods on the interface like shouldIncludeVct() and shouldIncludeCredentialDefinition()

This would eliminate the JSON serialization overhead and make the intent clearer.

Copilot uses AI. Check for mistakes.
*
* @param metadata mutable map representing the credential metadata entry
*/
default void contributeToMetadata(Map<String,Object> metadata) {
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

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

Missing space after comma in generic type parameter. Should be Map<String, Object> to match the codebase convention seen throughout the project (e.g., in JwtCredentialBuilder.java:110, SdJwtCredentialBuilder.java:139, and many other files).

Suggested change
default void contributeToMetadata(Map<String,Object> metadata) {
default void contributeToMetadata(Map<String, Object> metadata) {

Copilot uses AI. Check for mistakes.
@mposolda
Copy link
Contributor

@namanONcode Thanks! Could you please list existing issue (in the commit message and in the GH issue) and take care that "spotless" is working? See this message in your other PR for the details: #45809 (comment)

@namanONcode
Copy link
Contributor Author

@mposolda i have fixes both pr issue related to contribution guidelines please allow ci to run for both pr

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

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

@namanONcode Thanks! Added few comments inline. Could you check them please?

*
* @param metadata mutable map representing the credential metadata entry
*/
default void contributeToMetadata(Map<String,Object> metadata) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems much better if this method has signature with "typed" arguments. Maybe something like:

default void contributeToMetadata(SupportedCredentialConfiguration credentialConfig, CredentialScopeModel credentialScope);

instead of generic map.

This would allow that method implementations can "add" proper fields to the credentialConfig rather than "remove" previously added fields.

It seems to me this might work if the method is invoked somewhen from SupportedCredentialConfiguration.parse (that method should be updated also to remove credentialConfiguration.setVct and credentialConfiguration.setCredentialDefinition to make sure that this is added by the corresponding builders).


credentialBuilder.contributeToMetadata(metadataMap);

if (!metadataMap.containsKey("vct")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It will be good if this is not needed. In theory, the OID4VCIssuerWellKnownProvider should not have any knowledge of the fields like vct or credential_definition, which are specific to concrete credential types. This is related to my other comment (in CredentialBuilder class).

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class CredentialMetadataWellKnownTest extends OID4VCIssuerEndpointTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to use existing OID4VCIssuerWellKnownProviderTest and either update some existing tests in that class or introduce new test methods to that class?

That test would be better as it is usually better approach to do end-to-end testing (properly send HTTP request to the endpoint instead of using testingClient.server.run to test Java API directly).

Just a note that there is some existing PR #45784, which will introduce conflicts, so probably may be good to wait until that one is merged (would be probably later today).

Copy link
Contributor

Choose a reason for hiding this comment

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

PR #45784 already merged. Feel free to rebase to align with latest updates in Keycloak main.

@namanONcode
Copy link
Contributor Author

@namanONcode Thanks! Added few comments inline. Could you check them please?

Yeah I will look and implement these comments

@namanONcode
Copy link
Contributor Author

namanONcode commented Jan 28, 2026

@mposolda i have done suggested changes mentioned in comments also test are also refactored please allow run ci and i had implemented with latest fork of main branch as you mentioned to avoid merge conflicts

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

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

@namanONcode Thanks for the updates! Added few more minor comments inline.

Besides that, it will be good to look at the failing tests as those are caused by your changes probably: https://github.com/keycloak/keycloak/actions/runs/21447397428/job/61767431090?pr=45807 .

Maybe it is not needed to add new test methods as the vct and credentialDefinition fields are probably already tested for some existing credentials. So maybe it is sufficient to fix the existing tests instead and that is sufficient to test that metadata looks as expected?

public void contributeToMetadata(SupportedCredentialConfiguration credentialConfig, CredentialScopeModel credentialScope) {
String vct = Optional.ofNullable(credentialScope.getVct()).orElse(credentialScope.getName());
credentialConfig.setVct(vct);
credentialConfig.setCredentialDefinition(null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: I think this line can be omitted as it is not needed to explicitly call setCredentialDefinition here? As long as it is not set on any other place (which is not with your changes), it would be null automatically. No need for this impl to take care of credentialDefinition, which this builder doesn't understand at all in theory.

public void contributeToMetadata(SupportedCredentialConfiguration credentialConfig, CredentialScopeModel credentialScope) {
CredentialDefinition credentialDefinition = CredentialDefinition.parse(credentialScope);
credentialConfig.setCredentialDefinition(credentialDefinition);
credentialConfig.setVct(null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: I think this line can be omitted as it is not needed to explicitly call setVct here? As long as it is not set on any other place (which is not with your changes), it would be null automatically. No need for this impl to take care of vct, which this builder doesn't understand at all in theory.

* This is an end-to-end test using HTTP requests to the well-known endpoint.
*/
@Test
public void testSdJwtMetadataContainsVctAndNotCredentialDefinition() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can omit adding those new test methods, but instead, you can possibly update existing tests as there are some failure (with your changes), which are probably caused exactly by the fact that vct and credentialDefinition are not present.

BTW. If you think some new test is good to add, it would be good to avoid using Apache HTTP client directly, but instead using OAuthClient stuff (like other test methods of this class are using).

@namanONcode
Copy link
Contributor Author

namanONcode commented Jan 28, 2026

@mposolda all new suggestions are implemented to avoid ci test failure still fails please guide me to resolve this

Introduce a CredentialBuilder hook that allows credential formats to
contribute format-specific metadata to the OID4VC issuer well-known
configuration. The issuer delegates metadata shaping to the
corresponding CredentialBuilder implementation.

Refactor metadata contribution to work directly with
SupportedCredentialConfiguration and CredentialScopeModel, improving
type-safety and avoiding unnecessary serialization.

Add integration tests to verify that SD-JWT credentials expose `vct`
without `credential_definition`, and JWT_VC credentials expose
`credential_definition` without `vct`.

Closes keycloak#45485

Signed-off-by: NAMAN JAIN <[email protected]>
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] Inconsistencies in well-known OID4VC metadata (Same metadata for all formats)

2 participants