Create a Custom Authenticator

Last modified by Mohammad Humayun Khan on 2021/08/16

It is possible to plug to any existing authentication mechanism by providing a bridge for it.

To create a custom authentication do the following:

  1. Implement the XWikiAuthService interface. It's recommended to extend the XWikiAuthServiceImpl class which is the default implementation(this is very useful 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

13.3+ To comply with the latest best practices, your custom authentication should trigger a UserAuthenticatedEvent when it implements itself checkAuth(XWikiContext context) (if your authenticator is reusing the standard login form this part is handled by XWiki). You can find implementation examples in xwiki-platform-oldcore as MyFormAuthenticator and MyBasicAuthenticator. Note that a UserAuthenticatedEvent should be created with a UserReference.

Here is an example code for a custom authenticator:

public class MyCustomAuthenticationService extends XWikiAuthServiceImpl
{
   // We cannot use "real" component injection here because authenticators are not components currently
   // But it's recommended to put most of your authenticator's actual code in a component (or several components) and use this component,
   // it will make it 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 of 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 if you reuse the standard means of gathering the credentials (login page, BASIC auth)
   // What's left on your side is 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.

Tags:
   

Get Connected