Custom Authenticator

Hi,

I’m implementing a Custom Authenticator and have read the guide here: https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/Create%20a%20Custom%20Authenticator/

How should MyCustomAuthenticationService look up the MyCustomAuthenticator? The sample code doesn’t show how.

From the sanbox samples linked to on that page, they all appear to use Utils.getComponent; however, that method and many others in Utils are deprecated. Following the chain of methods in the Javadocs, they suggest using the Script service instead but that sounds more like when you’re writing groovy scripts rather than doing a Java-to-Java component lookup?

Should I be using the deprecated method or is there another way?

As an aside, I tried putting my equivalent of MyCustomAuthenticator in a jar into XWiki’s WEB-INF/lib with the hope that I could put the rest of my code in an extension. The idea being that MyCustomAuthenticator would try to look up the extension and use it if it’s available, otherwise drop back to default XWiki behaviour; however, I’m getting NoCLassDefFoundError for the class in the extension. I’m currently using Util.getComponent even though it’s deprecated. Is that the cause or is it because of the classloader hierarchy doesn’t allow classes in WEB-INF lib to look up classes in an extension?

I can put the classes all in one extension. I just thought it would be nice to be able to set the property in xwiki.cfg, avoid the NoClassDefFoundError exception on startup before the extension is installed and benefit from being able to use the uninstall, clean, install process for the extension via the extension manager instead of having to restart xwiki each time I made a change to my authenticator. Hope that makes sense :slight_smile:

Thanks in advance,
Alex

The thing with authenticators is that they are still very much old style (at least their entry point is), so they have to go through Utils.getComponent yes. We have a TODO to design a new authentication API but since the current one works well enough for many case it has a hard time going up in the list.

It is.

You can still do something similar by just setting the xwiki.cfg and not put any JAR in WEB-INF/lib. If your authenticator is not found, XWiki will use the standard one.

An alternative to that is to make your authenticator register itself, the trick being to call XWiki#setAuthService in some listener of your extension. In that case xwiki.cfg is not needed at all but the downside if that if someone install your extension by mistake it’s going to break whatever auth setup is already in place.

Thank you @tmortagne, that’s very helpful.

I can’t redeploy (uninstall, clean, install) the extension without restarting XWiki though can I? I’ll try it again just in case I was doing something wrong when I tried it last. It’s the xwiki restart I was hoping to avoid by using a very basic/simple “loader” that lives in WEB-INF/lib and xwiki.cfg refers to that loads the extension class, if present.

That’s good to know, thank you! The extension won’t be useful outside of my own environment so others won’t be installing it so this approach may be a good option.

Note that this was actually not such great advice for recent versions of XWiki: just fixed XWIKI-19107.

Dealing with upgrading SNAPSHOT versions is indeed a bit of a pain right now, since XWiki recognize all local SNAPSHOT builds as the same version. Now I don’t see how having the JAR in WEB-INF/lib helps you for this use case, you still need to restart if you modify a JAR located in WEB-INF/lib.

Sorry, I’ve probably done a poor job of explaining myself or maybe I’m misunderstanding your point.

I was hoping to have a very simple, one class jar file that I drop into WEB-INF/lib. This class would be the one referenced by xwiki.cfg. That one class would extend XWikiAuthServiceImpl and in the checkAuth method(s) would attempt to look up the actual authenticator implementation, which is contained within an extension deployed via the extension manager. If it couldn’t locate the extension class (I.e. the extension is not deployed), it would drop back to standard xwiki auth. As such, that WEB-INF/lib jar/class would be very simple and would very rarely change. As that class is looking up the actual authentication implementation, I’d hopefully be able to redeploy the extension to pick up new builds without having to restart xwiki.

However, as you’ve confirmed that classes in WEB-INF/lib cannot access classes in extensions, the process above is not possible. That leaves me with either putting all of my authenticator code in a jar and dropping it into the WEB-INF/lib dir or I can package it into an extension and use the extension manager (which I prefer). However, in both cases, because this is code that is working with the “old core”, if I make a change to the code I need to restart xwiki.

I think we might be on the same page :slight_smile:

This is pretty much what happen already if you just put in xwiki.cfg the class of an authenticator located in an extension, you don’t need a “relay” for it. Since 13.2 every time an extension is installed/upgraded XWiki checks if it contains an authenticator referenced in xwiki.cfg and automatically load it, so no need to restart. If the authenticator cannot be found (or cannot be loaded) you get a warning and it fallback on the standard XWiki authenticator.

Ah, I see! I’m using 12.10.9 at the moment but will definitely keep that in mind when we upgrade to 13.x once it reaches LTS.

Thanks again.

OK so best is probably to use the register itself trick.

Thanks, will give it a try.