Create a Custom Authenticator

Version 5.1 by Thomas Mortagne on 2021/06/18

It is possible to plug to any existing authentication mechanism such as SiteMinder, etc.

To create a custom authentication do the following:

  1. Implement the XWikiAuthService interface. It's recommended to extends the XWikiAuthServiceImpl class which is a default implementation, this is very usefull if you want to reuse the standard login form for example).
  2. Edit the WEB-INF/xwiki.cfg file and add a xwiki.authentication.authclass property pointing to your class. For example:
xwiki.authentication.authclass = com.acme.MyCustomAuthenticationService

Here is an example code for a custom authenticator designed as a component:

public class MyCustomAuthenticationService extends XWikiAuthServiceImpl
{
    // We cannot use use "real" component injection here because authenticators are not component currently
    // But it's recommended to put most of your authenticator actual code in a component and use this component,
    // it will make a lot easier to reuse various XWiki tools and APIs
    private MyCustomAuthentor authenticator;

    // If you don't plan to reuse the standard XWiki login you should implement this method which is usually in charge or gathering the user credentials
    // or other means of indicating what is the current user (HTTP headers, etc.)
    @Override
    public XWikiUser checkAuth(XWikiContext context)
    {
        // Call the actual authenticator
        return this.authenticator.checkAuth(context);
    }

    // This is the method which will be called is you reuse the standard means of gathering of the credentials (login page, BASIC auth)
    // What's left on your side if to validate the credential and create/update the XWiki user profile (and eventually synchronize other user related info like the groups, etc.)
    @Override
    public Principal authenticate(String username, String password, XWikiContext context) throws XWikiException
    {
        // Call the actual authenticator
        return this.authenticator.checkAuth(context);
    }
}

@Component(roles = MyCustomAuthenticator.class)
@Singleton
public MyCustomAuthenticator
{
    @Inject
    private ObservationManager observation;

    public XWikiUser checkAuth(XWikiContext context)
    {
        // You authenticate a user somehow
        ...

        // Since 13.3, if this is a new authentication (the user was not already authenticated in this session) you should send a notification about that
        if (newAuth) {
          // You have to retrieve its UserReference
          // You should be able to use a UserReferenceResolver if needed
          UserReference userReference = ...;

          // Then, trigger a UserAuthenticatedEvent by passing previously retrieved user reference to UserAuthenticatedEvent constructor
          this.observationManager.notify(new UserAuthenticatedEvent(userReference), null);
        }
    }

  public Principal authenticate(String username, String password, XWikiContext context) throws XWikiException
  {
    ...
  }
}

You can find various authenticators examples in extensions or sandbox.

Here's a tutorial on implementing a custom authentication class for authenticating against Oracle's SSO.

Get Connected