After updating our XWiki instance from 16.6.0 to 17.4.0 we are getting HTTP Status 500 – Internal Server Error
when attempting to log in using OIDC (Extension version 2.18.1) from a subwiki. Login from the main wiki works fine. The stack trace of the error is:
Stack trace
Exception
jakarta.servlet.ServletException: Failed to handle Resource Reference [path = authenticator/callback, endpoint = authenticator, pathSegments = [callback]]
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.handleResourceReference(ResourceReferenceHandlerServlet.java:162)
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.service(ResourceReferenceHandlerServlet.java:90)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter.doFilter(SetHTTPHeaderFilter.java:66)
org.xwiki.resource.servlet.RoutingFilter.doFilter(RoutingFilter.java:148)
org.xwiki.container.servlet.filters.internal.SavedRequestRestorerFilter.doFilter(SavedRequestRestorerFilter.java:211)
org.xwiki.container.servlet.filters.internal.SafeRedirectFilter.doFilter(SafeRedirectFilter.java:106)
org.xwiki.container.servlet.filters.internal.ResolveRelativeRedirectFilter.doFilter(ResolveRelativeRedirectFilter.java:129)
org.xwiki.container.servlet.filters.internal.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:120)
Root Cause
org.xwiki.resource.ResourceReferenceHandlerException: Failed to handle the OIDC endpoint
org.xwiki.contrib.oidc.provider.internal.OIDCResourceReferenceHandler.handle(OIDCResourceReferenceHandler.java:114)
org.xwiki.resource.internal.DefaultResourceReferenceHandlerChain.handleNext(DefaultResourceReferenceHandlerChain.java:79)
org.xwiki.resource.internal.AbstractResourceReferenceHandlerManager.handle(AbstractResourceReferenceHandlerManager.java:82)
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.handleResourceReference(ResourceReferenceHandlerServlet.java:160)
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.service(ResourceReferenceHandlerServlet.java:90)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter.doFilter(SetHTTPHeaderFilter.java:66)
org.xwiki.resource.servlet.RoutingFilter.doFilter(RoutingFilter.java:148)
org.xwiki.container.servlet.filters.internal.SavedRequestRestorerFilter.doFilter(SavedRequestRestorerFilter.java:211)
org.xwiki.container.servlet.filters.internal.SafeRedirectFilter.doFilter(SafeRedirectFilter.java:106)
org.xwiki.container.servlet.filters.internal.ResolveRelativeRedirectFilter.doFilter(ResolveRelativeRedirectFilter.java:129)
org.xwiki.container.servlet.filters.internal.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:120)
Root Cause
org.xwiki.contrib.oidc.provider.internal.OIDCException: Failed to get access token: invalid_grant
org.xwiki.contrib.oidc.auth.internal.OIDCTokenRequestHelper.requestTokenHTTP(OIDCTokenRequestHelper.java:112)
org.xwiki.contrib.oidc.auth.internal.endpoint.CallbackOIDCEndpoint.requestTokenFromAuthenticationResponse(CallbackOIDCEndpoint.java:354)
org.xwiki.contrib.oidc.auth.internal.endpoint.CallbackOIDCEndpoint.handle(CallbackOIDCEndpoint.java:210)
org.xwiki.contrib.oidc.provider.internal.OIDCResourceReferenceHandler.handle(OIDCResourceReferenceHandler.java:138)
org.xwiki.contrib.oidc.provider.internal.OIDCResourceReferenceHandler.handle(OIDCResourceReferenceHandler.java:110)
org.xwiki.resource.internal.DefaultResourceReferenceHandlerChain.handleNext(DefaultResourceReferenceHandlerChain.java:79)
org.xwiki.resource.internal.AbstractResourceReferenceHandlerManager.handle(AbstractResourceReferenceHandlerManager.java:82)
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.handleResourceReference(ResourceReferenceHandlerServlet.java:160)
org.xwiki.resource.servlet.ResourceReferenceHandlerServlet.service(ResourceReferenceHandlerServlet.java:90)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.xwiki.container.servlet.filters.internal.SetHTTPHeaderFilter.doFilter(SetHTTPHeaderFilter.java:66)
org.xwiki.resource.servlet.RoutingFilter.doFilter(RoutingFilter.java:148)
org.xwiki.container.servlet.filters.internal.SavedRequestRestorerFilter.doFilter(SavedRequestRestorerFilter.java:211)
org.xwiki.container.servlet.filters.internal.SafeRedirectFilter.doFilter(SafeRedirectFilter.java:106)
org.xwiki.container.servlet.filters.internal.ResolveRelativeRedirectFilter.doFilter(ResolveRelativeRedirectFilter.java:129)
org.xwiki.container.servlet.filters.internal.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:120)
Keycloak returns the following log entry (internal details removed):
WARN [org.keycloak.events] (executor-thread-#####) type="CODE_TO_TOKEN_ERROR", realmId="***", clientId="***", userId="***", sessionId="***", ipAddress="***", error="invalid_code", grant_type="authorization_code", code_id="***", client_auth_method="client-secret"
Enabling debug logging for the oidc
packages gave us the actual error response:
DEBUG c.o.a.i.OIDCTokenRequestHelper - OIDC Token response ({"error":"invalid_grant","error_description":"Incorrect redirect_uri"}
This led us to inspecting the redirect URI passed in the request to the IdP (Keycloak). Using xwiki.example.com
as a replacement for the actual address:
- Main wiki (login successful):
https://xwiki.example.com:443/oidc/authenticator/callback
- Subwikis (login fails with error):
https://xwiki.example.com/oidc/authenticator/callback
The Keycloak settings include both of these versions as valid redirect URIs. To be sure we temporarily set the valid redirect URIs to *
, but the issue persisted.
We have an NginX proxy set up in front of XWiki. Our Tomcat config is modified in two places:
- Added
secure=true
to the Connector on port 8080 - Added
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" protocolHeader="x-forwarded-proto" />
inside thelocalhost
host of theCatalina
engine.
Our main wiki is configured with Secure: Yes
and Port: 443
. The subwikis are configured with Secure: (blank)
and Port: -1
. We have tried setting the subwiki settings to the same values as the main wiki settings, but the issue persists.
We have used the following groovy script to check the headers of the request and the base URL:
Groovy script
{{groovy wiki="false"}}
println 'HTTP header "forwarded": ' + xcontext.request.getHeader('forwarded')
println 'HTTP header "x-forwarded-host": ' + xcontext.request.getHeader('x-forwarded-host')
println 'HTTP header "x-forwarded-for": ' + xcontext.request.getHeader('x-forwarded-for')
println 'HTTP header "x-forwarded-proto": ' + xcontext.request.getHeader('x-forwarded-proto')
println 'HTTP header "x-forwarded-port": ' + xcontext.request.getHeader('x-forwarded-port')
println 'Application server port: ' + xcontext.request.getServerPort()
println org.xwiki.container.servlet.HttpServletUtils.getSourceBaseURL(xcontext.request)
{{/groovy}}
Results are the same in main and subwikis:
Groovy results
HTTP header "forwarded": null
HTTP header "x-forwarded-host": xwiki.example.com
HTTP header "x-forwarded-for": null
HTTP header "x-forwarded-proto": https
HTTP header "x-forwarded-port": 443
Application server port: 443
https://xwiki.example.com
The following Velocity script returns different results between main and subwikis:
Velocity script
{{velocity}}
$xcontext.context.getURLFactory().getServerURL($xcontext.context)
{{/velocity}}
- Main wiki:
https://xwiki.example.com:443/
- Subwikis:
https://xwiki.example.com
Lastly, the debug log also contains the following line (the IP of the XWiki container in the internal Docker network is replaced with 1.2.3.4
). I don’t know if the use of an IP here is related to the issue, but the logging code is using httpRequest.getURL()
which makes me think it might:
DEBUG c.o.a.i.e.CallbackOIDCEndpoint - OIDC callback: starting with request [https://1.2.3.4:8080/oidc/authenticator/callback?state=...
I heavily assume the issue is related to the new application server request URL resolution. Are the inconsitencies in whether the port is attached a bug of the new resolution? Or does the OIDC extension miss some modifications required for the new resolution? Or do we have to change our Tomcat/NginX configuration to work with the new resolution?
Sorry for the very long post, but I wanted to include as much detail as possible.
Edit: Forgot to mention that our main wiki allows reading for unregistered users while our subwikis do not. So opening a link to a document in the main wiki will show the document and allow login by clicking the login button in the top bar (with the login succeeding). Opening a link to a document in a subwiki will immediately redirect to the IdP (with the error occuring on the redirect after authentication).