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

[Bug] OIDC crashes if auth url has trailing slash #1430

Open
DarkVirtue opened this issue Jan 7, 2025 · 1 comment
Open

[Bug] OIDC crashes if auth url has trailing slash #1430

DarkVirtue opened this issue Jan 7, 2025 · 1 comment
Assignees
Labels
bug Something isn't working

Comments

@DarkVirtue
Copy link

DarkVirtue commented Jan 7, 2025

RomM version
3.7.0

Describe the bug
If OIDC_SERVER_APPLICATION_URL ends wtih a / (as displayed on a provider's page in Authentik), the resulting redirect causes an "Internal Server Error".

To Reproduce

  1. Configure OIDC provider as normal in RomM and Authentik.
  2. In Authentik, go to the provider's page and copy the OpenID Configuration Issuer URL. It will contain a trailing /.
  3. Use that URL for OIDC_SERVER_APPLICATION_URL.
  4. Try to log in, receive "Internal Server Error" in the browser.

Logged error:

romm-1  | httpx.HTTPStatusError: Redirect response '301 Moved Permanently' for url 'https://auth.[REDACTED].com/application/o/romm-application//.well-known/openid-configuration'
romm-1  | Redirect location: '/application/o/romm-application/.well-known/openid-configuration'
romm-1  | For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301

Note how /application/o/romm-application//.well-known/openid-configuration contains two / before .well-known and is redirected to the same path with one /.

Expected behavior
The configuration should work the same with or without the trailing /.

Additional context

Logs from failed login with trailing / and redirect romm-1 | [2025-01-07 22:06:26 +0000] [20] [ERROR] Exception in ASGI application romm-1 | Traceback (most recent call last): romm-1 | File "/src/.venv/lib/python3.12/site-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi romm-1 | result = await app( # type: ignore[func-returns-value] romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 69, in __call__ romm-1 | return await self.app(scope, receive, send) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__ romm-1 | await super().__call__(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 409, in _sentry_patched_asgi_app romm-1 | return await middleware(scope, receive, send) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/asgi.py", line 161, in _run_asgi3 romm-1 | return await self._run_app(scope, receive, send, asgi_version=3) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/asgi.py", line 262, in _run_app romm-1 | raise exc from None romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/asgi.py", line 257, in _run_app romm-1 | return await self.app( romm-1 | ^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/applications.py", line 113, in __call__ romm-1 | await self.middleware_stack(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 187, in __call__ romm-1 | raise exc romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 165, in __call__ romm-1 | await self.app(scope, receive, _send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 185, in __call__ romm-1 | with collapse_excgroups(): romm-1 | ^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/usr/lib/python3.12/contextlib.py", line 158, in __exit__ romm-1 | self.gen.throw(value) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/_utils.py", line 82, in collapse_excgroups romm-1 | raise exc romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 187, in __call__ romm-1 | response = await self.dispatch_func(request, call_next) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/backend/utils/context.py", line 41, in set_context_middleware romm-1 | return await call_next(request) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 163, in call_next romm-1 | raise app_exc romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/base.py", line 149, in coro romm-1 | await self.app(scope, receive_or_disconnect, send_no_error) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/backend/handler/auth/middleware.py", line 147, in __call__ romm-1 | await self.app(scope, receive, send_wrapper) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 348, in _sentry_authenticationmiddleware_call romm-1 | await old_call(self, scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/authentication.py", line 48, in __call__ romm-1 | await self.app(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/cors.py", line 85, in __call__ romm-1 | await self.app(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 298, in _sentry_exceptionmiddleware_call romm-1 | await old_call(self, scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/starlette.py", line 200, in _create_span_call romm-1 | return await old_call(app, scope, new_receive, new_send, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 62, in __call__ romm-1 | await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app romm-1 | raise exc romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app romm-1 | await app(scope, receive, sender) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/routing.py", line 715, in __call__ romm-1 | await self.middleware_stack(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/routing.py", line 735, in app romm-1 | await route.handle(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/routing.py", line 288, in handle romm-1 | await self.app(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/routing.py", line 76, in app romm-1 | await wrap_app_handling_exceptions(app, request)(scope, receive, send) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app romm-1 | raise exc romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app romm-1 | await app(scope, receive, sender) romm-1 | File "/src/.venv/lib/python3.12/site-packages/starlette/routing.py", line 73, in app romm-1 | response = await f(request) romm-1 | ^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/fastapi.py", line 143, in _sentry_app romm-1 | return await old_app(*args, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 301, in app romm-1 | raw_response = await run_endpoint_function( romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 212, in run_endpoint_function romm-1 | return await dependant.call(**values) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/backend/endpoints/auth.py", line 224, in login_via_openid romm-1 | return await oauth.openid.authorize_redirect(request, OIDC_REDIRECT_URI) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/authlib/integrations/starlette_client/apps.py", line 34, in authorize_redirect romm-1 | rv = await self.create_authorization_url(redirect_uri, **kwargs) romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/authlib/integrations/base_client/async_app.py", line 95, in create_authorization_url romm-1 | metadata = await self.load_server_metadata() romm-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ romm-1 | File "/src/.venv/lib/python3.12/site-packages/authlib/integrations/base_client/async_app.py", line 77, in load_server_metadata romm-1 | resp.raise_for_status() romm-1 | File "/src/.venv/lib/python3.12/site-packages/httpx/_models.py", line 763, in raise_for_status romm-1 | raise HTTPStatusError(message, request=request, response=self) romm-1 | httpx.HTTPStatusError: Redirect response '301 Moved Permanently' for url 'https://auth.[REDACTED].com/application/o/romm-application//.well-known/openid-configuration' romm-1 | Redirect location: '/application/o/romm-application/.well-known/openid-configuration' romm-1 | For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301
@DarkVirtue DarkVirtue added the bug Something isn't working label Jan 7, 2025
@adamantike adamantike self-assigned this Jan 7, 2025
adamantike added a commit that referenced this issue Jan 8, 2025
Use `authlib` util `get_well_known_url` to get the well-known URL for
the OIDC server metadata. This will ensure that the URL is correctly
formatted and does not fail when the OIDC server application URL has a
trailing slash.

Fixes #1430.
@adamantike
Copy link
Collaborator

Thanks for reporting this issue! A fix was developed in #1440 and will be available in the next release.

In the meantime, as you mentioned, the workaround is to remove the trailing slash from OIDC_SERVER_APPLICATION_URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants