-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Hello, thank you for the fix regarding the query parameters not being passed to the non-shortened URL.
After updating to 1.2.9, even though query parameters are now correctly passed, I noticed that Basic Auth using URL userinfo still does not work. (see RFC 3986, section 3.2.1).
After digging deeper into the extension and compiling a modified version, I managed to get it working.
The root cause is that client side redirects do not forward Basic Authentication credentials for security reasons.
How to reproduce:
- Try logging to your wiki instance using URL credentials through a shortened URL (e.g. https://username:password@wikiurl.com/short/d7914?basicauth=1)
- Try logging into your wiki instance using URL credentials without the shortener: (e.g. https://username:password@wikiurl.com?basicauth=1)
Observed behavior
- The first case will not work (after the fix for query parameters It will correctly ask for credentials) but the credentials are not automatically passed to the resolved non-short URL.
- The second case works as expected.
This demonstrates that the issue is on the URL Shortener extension side, not in XWiki itself.
The fix:
src/main/java/com/xwiki/urlshortener/internal/URLShortenerResourceReferenceHandler.java
if (null != documentReference) {
XWikiContext xcontext = xcontextProvider.get();
// Preserve query parameters from the shortened URL request.
String queryString = URLEncodedUtils.format(
urlResourceReference.getParameters().entrySet().stream()
.flatMap(entry ->
entry.getValue().stream()
.map(value -> new BasicNameValuePair(entry.getKey(), value)))
.collect(Collectors.toList()),
StandardCharsets.UTF_8
);
String stringURL = xcontext.getWiki().getURL(
documentReference, "view", queryString, "", xcontext
);
// Check if basicauth parameter is present
if (urlResourceReference.getParameters().containsKey("basicauth")) {
HttpServletRequest request =
((ServletRequest) this.container.getRequest()).getHttpServletRequest();
// Use xWiki's built-in auth service to check the request
try {
com.xpn.xwiki.XWiki xwiki = xcontext.getWiki();
com.xpn.xwiki.user.api.XWikiUser xwikiUser =
xwiki.getAuthService().checkAuth(xcontext);
if (xwikiUser != null) {
xcontext.setUser(xwikiUser.getUser());
}
} catch (Exception e) {
// If auth fails, continue anyway, will normally ask for credentials
}
// Build the forward path from the URL (need relative path for forward)
String forwardPath = stringURL;
// If it's an absolute URL, extract just the path + query
if (forwardPath.startsWith("http://") || forwardPath.startsWith("https://")) {
try {
java.net.URL url = new java.net.URL(forwardPath);
forwardPath = url.getPath();
if (url.getQuery() != null && !url.getQuery().isEmpty()) {
forwardPath += "?" + url.getQuery();
}
} catch (java.net.MalformedURLException e) {
response.sendRedirect(stringURL);
return;
}
}
RequestDispatcher dispatcher = request.getRequestDispatcher(forwardPath);
dispatcher.forward(request, response);
} else {
response.sendRedirect(stringURL);
}
} else {
response.sendError(
404,
String.format(
"No document is associated to the given ID: [%s]",
urlResourceReference.getPageId()
)
);
}PS. This is an actual fix that works in our production environment, It may not be the most elegant solution, but it does solve the problem. 😄
Thanks for the support as always!