You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Configure OIDC provider as normal in RomM and Authentik.
In Authentik, go to the provider's page and copy the OpenID Configuration Issuer URL. It will contain a trailing /.
Use that URL for OIDC_SERVER_APPLICATION_URL.
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
The text was updated successfully, but these errors were encountered:
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.
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
/
.OIDC_SERVER_APPLICATION_URL
.Logged error:
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/301The text was updated successfully, but these errors were encountered: