Create a Custom Authenticator
Version 9.1 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:
- 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).
- 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:
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
{
...
}
}
{
// 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.