Skip to content

[OID4VCI] No key for id ... and algorithm ... available #45385

@Captain-P-Goldfish

Description

@Captain-P-Goldfish

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

oid4vc

Describe the bug

This bug is caused relatively randomly based on the order of supported-signature algorithms within the created credential.

The error expresses itself like this:

2026-01-13 11:24:28,348 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-14) Uncaught server error: org.keycloak.protocol.oid4vc.issuance.signing.CredentialSignerException: No key for id Asj26a8OT7gIo17UX6LZYuwfbtjAPL4kfeRygZuLo3M and algorithm PS384 available.
	at org.keycloak.protocol.oid4vc.issuance.signing.AbstractCredentialSigner.getKeyWithKidSubstitute(AbstractCredentialSigner.java:74)
	at org.keycloak.protocol.oid4vc.issuance.signing.AbstractCredentialSigner.getSigner(AbstractCredentialSigner.java:52)
	at org.keycloak.protocol.oid4vc.issuance.signing.JwtCredentialSigner.signCredential(JwtCredentialSigner.java:48)
	at org.keycloak.protocol.oid4vc.issuance.signing.JwtCredentialSigner.signCredential(JwtCredentialSigner.java:32)
	at org.keycloak.protocol.oid4vc.issuance.OID4VCIssuerEndpoint.lambda$getCredential$10(OID4VCIssuerEndpoint.java:1306)
	at java.base/java.util.Optional.map(Optional.java:260)
	at org.keycloak.protocol.oid4vc.issuance.OID4VCIssuerEndpoint.getCredential(OID4VCIssuerEndpoint.java:1306)
	at org.keycloak.protocol.oid4vc.issuance.OID4VCIssuerEndpoint.requestCredential(OID4VCIssuerEndpoint.java:793)
	at org.keycloak.protocol.oid4vc.issuance.OID4VCIssuerEndpoint$quarkusrestinvoker$requestCredential_87a0478bbda8200bde8b9c5f86010949e9b5f428.invoke(Unknown Source)
	at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:183)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:645)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2651)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2630)
	at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1622)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1589)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

The cause is, that the ClientScope configuration references a valid key that does not match the algorithm of the very first entry of the supported-signing-algorithms list:

Image

Then in the credentials-metadata we have currently this:

Image

then we have this method:

public static CredentialBuildConfig parse(KeycloakSession keycloakSession,
                                              SupportedCredentialConfiguration credentialConfiguration,
                                              CredentialScopeModel credentialModel) {
        final String credentialIssuer = Optional.ofNullable(credentialModel.getIssuerDid()).orElse(
                OID4VCIssuerWellKnownProvider.getIssuer(keycloakSession.getContext()));

        return new CredentialBuildConfig().setCredentialIssuer(credentialIssuer)
                                          .setCredentialId(credentialConfiguration.getId())
                                          .setCredentialType(credentialConfiguration.getVct())
                                          .setTokenJwsType(credentialModel.getTokenJwsType())
                                          .setNumberOfDecoys(credentialModel.getSdJwtNumberOfDecoys())
                                          .setSigningKeyId(credentialModel.getSigningKeyId())
                                          .setSigningAlgorithm(credentialConfiguration.getCredentialSigningAlgValuesSupported()
                                                                                      .get(0))
                                          .setHashAlgorithm(credentialModel.getHashAlgorithm())
                                          .setSdJwtVisibleClaims(credentialModel.getSdJwtVisibleClaims());
    }

which is simply retrieving the very first algorithm from the list. As a result I get the following error-message when the credential should be signed:

Uncaught server error: org.keycloak.protocol.oid4vc.issuance.signing.CredentialSignerException: No key for id Asj26a8OT7gIo17UX6LZYuwfbtjAPL4kfeRygZuLo3M and algorithm PS384 available.

Version

26.5.0

Regression

  • The issue is a regression

Expected behavior

a valid key with a fitting algorithm should be selected and the signature should be successfully applied

Actual behavior

the system claims that no key is present that is matching the required algorithm which is not true.

How to Reproduce?

see the steps above.

Anything else?

No response

Metadata

Metadata

Assignees

Type

No fields configured for bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions