oidcc icon indicating copy to clipboard operation
oidcc copied to clipboard

PAR Request fails when using Keycloak

Open dabaer opened this issue 7 months ago • 7 comments

oidcc version

3.5.1

Erlang version

27.3.3

Elixir version

1.18.3

Summary

Under certain circumstances, the PAR request to Keycloak will fail. This seems to be partially related to #391, or at least that issue pointed me in the right direction.

Keycloak 26.2.0 seems to include the fix to the linked issue (and is the version I run), so I'm not sure if this is a Keycloak issue or an oidcc issue, but I'm hoping the maintainers would have a better idea of which system the issue lies in.

Current behavior

Keycloak refuses the initial PAR request with an error:

Invalid request: java.lang.RuntimeException: Request object encrypted with different algorithm than client requested algorithm

How to reproduce

I've narrowed it down to a very specific setting in the Keycloak client configuration.

When the advanced setting "Request Object Encryption Algorithm" is not set (i.e. doesn't appear in the attributes list of an export) everything works fine.

If the setting is set to "Any", or any of the available options, the PAR request is rejected and oidcc returns the dreaded Redirect URI Generation Failed error.

In the client export from Keycloak, the related setting is request.object.encryption.alg in the attributes object. I found while fiddling with the client settings it would randomly start failing, and apparently some unrelated options being saved will cause this setting to be added to the list with a value of any, and causes the error described.

Expected behavior

There should be an agreement between the requested encryption algorithm, and the actual encryption algorithm used in the PAR request.

dabaer avatar Apr 27 '25 02:04 dabaer

@dabaer Are you able to debug the keycloak error further?

Specifically: What is present in the encryptionAlg and jwt.getHeader().getRawAlgorithm() variables?

https://github.com/keycloak/keycloak/blob/08704df6516078cb31246861bb5858ef51838690/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestObjectParser.java#L101-L107

maennchen avatar Apr 27 '25 10:04 maennchen

Sorry for the delay, setting up Keyloak for dev was more involved than I had expected. Here's the output of those variables:

**********[encryptionAlg]: any **********[rawAlgorithm]: RSA-OAEP

Interestingly when I set the algorithm setting to RSA-OAEP I get a deserialization error:

Invalid request: java.lang.RuntimeException: Failed to deserialize JWT
 at org.keycloak.jose.jws.DefaultTokenManager.decodeClientJWT(DefaultTokenManager.java:169)
 at org.keycloak.protocol.oidc.endpoints.request.AuthzEndpointRequestObjectParser.<init>(AuthzEndpointRequestObjectParser.java:45)
 at org.keycloak.protocol.oidc.par.endpoints.request.ParEndpointRequestObjectParser.<init>(ParEndpointRequestObjectParser.java:33)
 at org.keycloak.protocol.oidc.par.endpoints.request.ParEndpointRequestParserProcessor.parseRequest(ParEndpointRequestParserProcessor.java:82)
 at org.keycloak.protocol.oidc.par.endpoints.ParEndpoint.request(ParEndpoint.java:109)
 at org.keycloak.protocol.oidc.par.endpoints.ParEndpoint$quarkusrestinvoker$request_af906d5d7425914e86d7ccc25bd818affb15f104.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:141)
 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:638)
 at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
 at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
 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)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'eyJhbGciOiJIUzI1NiJ9': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 22]
 at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2584)
 at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2610)
 at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2618)
 at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:825)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3662)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2749)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
 at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:5004)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4910)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3921)
 at org.keycloak.util.JsonSerialization.readValue(JsonSerialization.java:78)
 at org.keycloak.jose.jws.DefaultTokenManager.decodeClientJWT(DefaultTokenManager.java:167)
 ... 17 more

dabaer avatar Apr 27 '25 19:04 dabaer

Not sure where that deserialization error came from but I tried again and inspected some more of the variables in the code path:

**********[encryptionAlg]: RSA-OAEP
**********[rawAlgorithm]: RSA-OAEP
**********[encryptionEncAlg]: any
**********[headerEncAlg]: A256GCM

So the encryption encoding is also getting hung up. Seems like it's a Keycloak issue then? I imagine they should be handling the "any" case in these two places.

dabaer avatar Apr 27 '25 19:04 dabaer

The plot thickens, deserialization error returns:

**********[encryptionAlg]: RSA-OAEP
**********[rawAlgorithm]: RSA-OAEP
**********[encryptionEncAlg]: A256GCM
**********[headerEncAlg]: A256GCM
2025-04-27 13:51:04,906 WARN  [org.keycloak.services] (executor-thread-1) KC-SERVICES0097: Invalid request: java.lang.RuntimeException: Failed to deserialize JWT
 at org.keycloak.jose.jws.DefaultTokenManager.decodeClientJWT(DefaultTokenManager.java:169)
 at org.keycloak.protocol.oidc.endpoints.request.AuthzEndpointRequestObjectParser.<init>(AuthzEndpointRequestObjectParser.java:45)
 at org.keycloak.protocol.oidc.par.endpoints.request.ParEndpointRequestObjectParser.<init>(ParEndpointRequestObjectParser.java:33)
 at org.keycloak.protocol.oidc.par.endpoints.request.ParEndpointRequestParserProcessor.parseRequest(ParEndpointRequestParserProcessor.java:82)
 at org.keycloak.protocol.oidc.par.endpoints.ParEndpoint.request(ParEndpoint.java:109)
 at org.keycloak.protocol.oidc.par.endpoints.ParEndpoint$quarkusrestinvoker$request_af906d5d7425914e86d7ccc25bd818affb15f104.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:141)
 at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
 at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:638)
 at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
 at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
 at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
 at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
 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)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'eyJhbGciOiJIUzI1NiJ9': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 22]
 at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2584)
 at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2610)
 at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2618)
 at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:825)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3662)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2749)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
 at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
 at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:5004)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4910)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3921)
 at org.keycloak.util.JsonSerialization.readValue(JsonSerialization.java:78)
 at org.keycloak.jose.jws.DefaultTokenManager.decodeClientJWT(DefaultTokenManager.java:167)

dabaer avatar Apr 27 '25 19:04 dabaer

And here is the output of those variables when those attributes are removed in Keycloak:

**********[encryptionAlg]: null
**********[rawAlgorithm]: RSA-OAEP
**********[encryptionEncAlg]: null
**********[encryptionAlg]: null
**********[rawAlgorithm]: RSA-OAEP
**********[encryptionEncAlg]: null

dabaer avatar Apr 27 '25 19:04 dabaer

Thanks for tracking this down. This sure sounds like a Keycloak issue. Would you mind reporting that issue there?

maennchen avatar Apr 27 '25 21:04 maennchen

I ran into this issue with Keycloak.

To bypass this any issue, I ran:

docker exec -it <container> /opt/keycloak/bin/kcadm.sh \
  update clients/$CID -r cb \
  -s 'attributes."request.object.signature.alg"=' \
  -s 'attributes."request.object.encryption.alg"=' \
  -s 'attributes."request.object.encryption.enc"='

neelima32 avatar Oct 27 '25 21:10 neelima32