Open
Description
Describe the bug
I'm integrating logto cloud into my fastapi service with testing/development tenant.
I have seen this exception a few times while i was testing logto sign in flow:
logto.LogtoException.LogtoException: Invalid state in the callback URI
It doesn't happen consistently. I suspect it's due to multiple concurrent calls like below occurred causing it, but i'm not sure. I saw two calls like below.
https://auth.vid-craft.com/oidc/auth?client_id=87t2l9siglorrxfcslsgl&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fapi%2Fv1%2Fauth%2Fcallback&response_type=code&scope=openid+profile+email+phone+openid+offline_access+profile&prompt=consent&code_challenge=5QI8ErAmmqx0nBuEoMD318aZbjOsJJvB-TF7hpsD5VM&code_challenge_method=S256&state=LSoyZ3SvYQJfPe2vxGrMp9OnfBvJMVG0aCNk-sK5BlY&interaction_mode=signUp
Expected behavior
This may not be a bug, it's more of a question/asking for help.
My questions are:
- why does it happen? what's the root cause?
- how to handle this kind of exception in the server side?
How to reproduce?
The call that failed looks like below from my Chrome developer tool:
http://localhost:8000/api/v1/auth/callback?code=KdfejSLR7se2JBZeRgRutT8fp5BpFe38WITmx1AwJQM&state=5Aq2ukAcE-4m94UNT-XSeKvYYyjX5GzV1kAszXE0ylM&iss=https%3A%2F%2Fauth.vid-craft.com%2Foidc
Context
INFO: 127.0.0.1:53296 - "GET /api/v1/auth/callback?code=KdfejSLR7se2JBZeRgRutT8fp5BpFe38WITmx1AwJQM&state=5Aq2ukAcE-4m94UNT-XSeKvYYyjX5GzV1kAszXE0ylM&iss=https%3A%2F%2Fauth.vid-craft.com%2Foidc HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
+ Exception Group Traceback (most recent call last):
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 77, in collapse_excgroups
| yield
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 186, in __call__
| async with anyio.create_task_group() as task_group:
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py", line 736, in __aexit__
| raise BaseExceptionGroup(
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
| result = await app( # type: ignore[func-returns-value]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
| return await self.app(scope, receive, send)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/applications.py", line 113, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 187, in __call__
| raise exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 165, in __call__
| await self.app(scope, receive, _send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 185, in __call__
| with collapse_excgroups():
| ^^^^^^^^^^^^^^^^^^^^
| File "/opt/homebrew/Cellar/[email protected]/3.12.7_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 158, in __exit__
| self.gen.throw(value)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 83, in collapse_excgroups
| raise exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 187, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/app/main.py", line 102, in monitor_worker_health
| response = await call_next(request)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 163, in call_next
| raise app_exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 149, in coro
| await self.app(scope, receive_or_disconnect, send_no_error)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 185, in __call__
| with collapse_excgroups():
| ^^^^^^^^^^^^^^^^^^^^
| File "/opt/homebrew/Cellar/[email protected]/3.12.7_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 158, in __exit__
| self.gen.throw(value)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 83, in collapse_excgroups
| raise exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 187, in __call__
| response = await self.dispatch_func(request, call_next)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/app/main.py", line 86, in dispatch
| response = await call_next(request)
| ^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 163, in call_next
| raise app_exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 149, in coro
| await self.app(scope, receive_or_disconnect, send_no_error)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/cors.py", line 85, in __call__
| await self.app(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
| await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app
| raise exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app
| await app(scope, receive, sender)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 715, in __call__
| await self.middleware_stack(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 735, in app
| await route.handle(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 288, in handle
| await self.app(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 76, in app
| await wrap_app_handling_exceptions(app, request)(scope, receive, send)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app
| raise exc
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app
| await app(scope, receive, sender)
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 73, in app
| response = await f(request)
| ^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 301, in app
| raw_response = await run_endpoint_function(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 212, in run_endpoint_function
| return await dependant.call(**values)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/asia/work/vid_craft/backend/app/api/routes/auth.py", line 23, in callback
| await LOGTO_CLIENT.handleSignInCallback(str(request.url))
| File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/logto/LogtoClient.py", line 377, in handleSignInCallback
| raise LogtoException("Invalid state in the callback URI")
| logto.LogtoException.LogtoException: Invalid state in the callback URI
+------------------------------------
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/applications.py", line 113, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 187, in __call__
raise exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 185, in __call__
with collapse_excgroups():
^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.12.7_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 158, in __exit__
self.gen.throw(value)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 83, in collapse_excgroups
raise exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 187, in __call__
response = await self.dispatch_func(request, call_next)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/app/main.py", line 102, in monitor_worker_health
response = await call_next(request)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 163, in call_next
raise app_exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 149, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 185, in __call__
with collapse_excgroups():
^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.12.7_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 158, in __exit__
self.gen.throw(value)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 83, in collapse_excgroups
raise exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 187, in __call__
response = await self.dispatch_func(request, call_next)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/app/main.py", line 86, in dispatch
response = await call_next(request)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 163, in call_next
raise app_exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 149, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/cors.py", line 85, in __call__
await self.app(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app
raise exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app
await app(scope, receive, sender)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 715, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 735, in app
await route.handle(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 288, in handle
await self.app(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 76, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 62, in wrapped_app
raise exc
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 51, in wrapped_app
await app(scope, receive, sender)
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 73, in app
response = await f(request)
^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 301, in app
raw_response = await run_endpoint_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 212, in run_endpoint_function
return await dependant.call(**values)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/asia/work/vid_craft/backend/app/api/routes/auth.py", line 23, in callback
await LOGTO_CLIENT.handleSignInCallback(str(request.url))
File "/Users/asia/work/vid_craft/backend/.venv/lib/python3.12/site-packages/logto/LogtoClient.py", line 377, in handleSignInCallback
raise LogtoException("Invalid state in the callback URI")
logto.LogtoException.LogtoException: Invalid state in the callback URI
- Logto Cloud
- Self-hosted, Logto version =
- Container (Docker image)
- Raw Node.js