Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonDecodingException when calling wallet's useOfferRequest in a multi-instance deployment #668

Closed
alegomes opened this issue Aug 5, 2024 · 1 comment
Assignees
Labels

Comments

@alegomes
Copy link
Contributor

alegomes commented Aug 5, 2024

Describe the bug

Failure when trying to use offer request in a multi-instance Issuer API deployment with no hint for troubleshooting.

Request:

> POST http://localhost:7001/wallet-api/wallet/80ca6d43-9e41-463d-8bad-d654fa903079/exchange/useOfferRequest
> content-type: text/plain
> data "openid-credential-offer://caddy:9092/?credential_offer_uri=http%3A%2F%2Fcaddy%3A9092%2Fopenid4vc%2FcredentialOffer%3Fid%3Dbfc251dc-2f8b-48a4-9aa3-149e745efd0f"
< 400 Bad Request
< vary: Origin
< content-length: 87
< content-type: text/plain; charset=UTF-8
< connection: close

Response body:

Cannot read Json element because of unexpected end of the input at path: $
JSON input: 

Wallet API log:

10:40:40.632618977  INFO [          D-worker-1] :               WebLog : REQUEST  -> POST http://localhost:7001/wallet-api/wallet/80ca6d43-9e41-463d-8bad-d654fa903079/exchange/useOfferRequest (axios): body: "openid-credential-offer://caddy:9092/?credential_offer_uri=http%3A%2F%2Fcaddy%3A9092%2Fopenid4vc%2FcredentialOffer%3Fid%3Dbfc251dc-2f8b-48a4-9aa3-149e745efd0f", cookies: "{login=ee15885e0f59cad445efd10e8d77f0b5%2F920556ee5626d9e2b88e8aa0c3a0799ee1ea91237edcf4fc97dd10ecec6aaa50bc15c89e8363c12a3ecd9ffb21cd9e9aa075973e41884e4d5ac3e0d42ae51e2f781cb522d2a9723070a6ac5d362e53e12d741a6c18a42b8942e20d17c5a53619eedd8eaf3368239cf19ebba7a272681668902bec1e22180a99204c4e38924289095b48889448e6ab9a0bdbd4b07b7cf7074ccb243fededda0c92a8bd0cd784cd975f400e2d859e2d169d94fa98180f4b0340ada2509b7fd3538132edae81dc4419adc9f83bbd8432abee495fe4413d12a42217256515ce0fef3bfc7dac5ea49bdb123d369e0019baff4479af749aa855f2388e1656aa5cfd019aa6dc9c96d5f008019fb05d2c468abcf6db53ced344f0f2cea37581422714ba890d2735512156b89e0501f2f9f6d80579a7e6a74141f2d6220625b743450f276e8604fd23a11d9b059f2158ade90f76a7d1a286faf607%3Ac13e48da3fe19c5fd355784ce2c51836124b49df818db0f68ac1992cd38795c4}"
HttpClient: REQUEST: http://caddy:9092/openid4vc/credentialOffer?id=bfc251dc-2f8b-48a4-9aa3-149e745efd0f
METHOD: HttpMethod(value=GET)
COMMON HEADERS
-> Accept: application/json
-> Accept-Charset: UTF-8
CONTENT HEADERS
-> Content-Length: 0
BODY Content-Type: null
BODY START

BODY END
HttpClient: RESPONSE: 200 OK
METHOD: HttpMethod(value=GET)
FROM: http://caddy:9092/openid4vc/credentialOffer?id=bfc251dc-2f8b-48a4-9aa3-149e745efd0f
COMMON HEADERS
-> content-length: 0
-> date: Mon, 05 Aug 2024 10:40:40 GMT
-> server: Caddy
BODY Content-Type: null
BODY START

BODY END
kotlinx.serialization.json.internal.JsonDecodingException: Cannot read Json element because of unexpected end of the input at path: $
JSON input:
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
	at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
	at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:580)
	at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:578)
	at kotlinx.serialization.json.internal.JsonTreeReader.read(JsonTreeReader.kt:107)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeJsonElement(StreamingJsonDecoder.kt:50)
	at kotlinx.serialization.json.JsonElementSerializer.deserialize(JsonElementSerializers.kt:50)
	at kotlinx.serialization.json.JsonElementSerializer.deserialize(JsonElementSerializers.kt:27)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:165)
	at id.walt.oid4vc.providers.OpenIDCredentialWallet.httpGetAsJson(OpenIDCredentialWallet.kt:499)
	at id.walt.oid4vc.providers.OpenIDCredentialWallet.resolveCredentialOffer(OpenIDCredentialWallet.kt:187)
	at id.walt.webwallet.service.exchange.IssuanceService.useOfferRequest(IssuanceService.kt:56)
	at id.walt.webwallet.usecase.claim.ExplicitClaimStrategy.claim(ExplicitClaimStrategy.kt:19)
	at id.walt.webwallet.web.controllers.ExchangeControllerKt$exchange$1$2$2.invokeSuspend(ExchangeController.kt:52)
	at id.walt.webwallet.web.controllers.ExchangeControllerKt$exchange$1$2$2.invoke(ExchangeController.kt)
	at id.walt.webwallet.web.controllers.ExchangeControllerKt$exchange$1$2$2.invoke(ExchangeController.kt)
	at io.ktor.server.routing.Route$buildPipeline$1$1.invokeSuspend(Route.kt:116)
	at io.ktor.server.routing.Route$buildPipeline$1$1.invoke(Route.kt)
	at io.ktor.server.routing.Route$buildPipeline$1$1.invoke(Route.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:131)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:89)
	at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:109)
	at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
	at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
	at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
	at io.ktor.server.routing.Routing.executeResult(Routing.kt:190)
	at io.ktor.server.routing.Routing.interceptor(Routing.kt:64)
	at io.ktor.server.routing.Routing$Plugin$install$1.invokeSuspend(Routing.kt:140)
	at io.ktor.server.routing.Routing$Plugin$install$1.invoke(Routing.kt)
	at io.ktor.server.routing.Routing$Plugin$install$1.invoke(Routing.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:131)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:89)
	at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invokeSuspend(BaseApplicationEngine.kt:124)
	at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invoke(BaseApplicationEngine.kt)
	at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invoke(BaseApplicationEngine.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:131)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:89)
	at io.ktor.server.application.hooks.CallFailed$install$1$1.invokeSuspend(CommonHooks.kt:45)
	at io.ktor.server.application.hooks.CallFailed$install$1$1.invoke(CommonHooks.kt)
	at io.ktor.server.application.hooks.CallFailed$install$1$1.invoke(CommonHooks.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:61)
	at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:261)
	at io.ktor.server.application.hooks.CallFailed$install$1.invokeSuspend(CommonHooks.kt:44)
	at io.ktor.server.application.hooks.CallFailed$install$1.invoke(CommonHooks.kt)
	at io.ktor.server.application.hooks.CallFailed$install$1.invoke(CommonHooks.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:131)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:89)
	at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:109)
	at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invokeSuspend(DefaultEnginePipeline.kt:123)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invoke(DefaultEnginePipeline.kt)
	at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invoke(DefaultEnginePipeline.kt)
	at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:131)
	at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:89)
	at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:109)
	at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
	at io.ktor.server.cio.CIOApplicationEngine$handleRequest$2$invokeSuspend$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
	at io.ktor.server.cio.CIOApplicationEngine$handleRequest$2$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.server.cio.CIOApplicationEngine$handleRequest$2$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
	at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
	at io.ktor.server.cio.CIOApplicationEngine$handleRequest$2.invokeSuspend(CIOApplicationEngine.kt:239)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
10:40:40.656084411  INFO [          D-worker-1] :               WebLog : RESP 400 -> POST http://localhost:7001/wallet-api/wallet/80ca6d43-9e41-463d-8bad-d654fa903079/exchange/useOfferRequest (axios): body: "Cannot read Json element because of unexpected end of the input at path: $
JSON input: " (400 Bad Request)

To Reproduce
Steps to reproduce the behavior:

  1. Create a docker user-defined network
docker network create waltid
  1. Start instance 1 of the Issuer API
docker run --rm --name issuer1 --net waltid -p 7002:7002 waltid/issuer-api -- --webPort=7002 --baseUrl=http://caddy:9092
  1. Start instance 2 of the Issuer API
docker run --rm --name issuer2 --net waltid -p 8002:8002 waltid/issuer-api -- --webPort=8002 --baseUrl=http://caddy:9092
  1. Start Caddy as load balancer
docker run --rm --net waltid --name caddy -p 9092:9092 -v $(pwd)/waltid-services/waltid-issuer-api/distributed-test.Caddyfile:/etc/caddy/Caddyfile caddy
  1. Start Redis as data store for shared session
docker run --rm --net waltid --name redis-stack-server -p 6379:6379 redis/redis-stack-server:latest
  1. Start the Wallet API
docker run --rm --name wallet --net waltid -p 7001:7001 -it -v $(pwd)/waltid-services/waltid-wallet-api/config:/waltid-wallet-api/config -v $(pwd)/waltid-services/waltid-wallet-api/data:/waltid-wallet-api/data -t waltid/wallet-api
  1. Open http://localhost:9092/swagger/index.html
  2. Start an OIDC exchange session /openid4vc/jwt/issue
  3. Save the Offer URL
  4. Open http://localhost:7001/swagger/index.html
  5. Create a new user with /wallet-api/auth/create
  6. Sign in with the user just created with /wallet-api/auth/login
  7. Get user's wallet id with /wallet-api/wallet/accounts/wallets
  8. Claim the offered VC with /wallet-api/wallet/{wallet}/exchange/useOfferRequest

Expected behavior

Receive the offered VC.

Actual behavior

image

Environment
Desktop (please complete the following information):

  • OS: macOS 14.5 build 23F79
  • Browser: Chrome 126.0.6478.127
  • Version: Commit 8734205

Additional context

Issuer API features:

cat waltid-services/waltid-issuer-api/config/_features.conf
enabledFeatures = [
    persistence
    # entra,
    # lsp-potential,
    # ...
]
disabledFeatures = [
    # ...
]

Issuer API persistence config:

cat waltid-services/waltid-issuer-api/config/persistence.conf
# Storage
// type = "memory"
type = "redis"
nodes = [{host = "redis-stack-server", port = 6379}]
user: "default"
password: ""

Caddy config:

$ cat waltid-services/waltid-issuer-api/distributed-test.Caddyfile
http://localhost:9092 {
    reverse_proxy {
        to issuer1:7002
        to issuer2:8002
        lb_policy round_robin
    }
}
http://localhost:9093 {
    reverse_proxy {
        to verifier1:7003
        to verifier2:8003
        lb_policy round_robin
    }
}
Copy link

github-actions bot commented Oct 8, 2024

This issue has been marked as stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants