Wiki source code of Create a Custom Authenticator
Last modified by Thomas Mortagne on 2023/04/28 10:34
Hide last authors
| author | version | line-number | content |
|---|---|---|---|
![]() |
6.1 | 1 | It is possible to plug to any existing authentication mechanism by providing a bridge for it. |
| |
1.1 | 2 | |
![]() |
10.7 | 3 | == Implement the authenticator == |
| |
1.1 | 4 | |
![]() |
10.2 | 5 | To implement a custom authentication the minimum is to implement the {{scm path="xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/user/api/XWikiAuthService.java"}}XWikiAuthService{{/scm}} interface. It's recommended to extend the {{scm path="xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java"}}XWikiAuthServiceImpl{{/scm}} class which is the default implementation(this is very useful if you want to reuse the standard login form, for example). |
| 6 | |||
| 7 | {{version since="13.3"}} | ||
| 8 | Your custom authentication should trigger a {{scm path="xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authentication/xwiki-platform-security-authentication-api/src/main/java/org/xwiki/security/authentication/UserAuthenticatedEvent.java"}}UserAuthenticatedEvent{{/scm}} 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 {{code}}xwiki-platform-oldcore{{/code}} as {{scm path="xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/user/impl/xwiki/MyFormAuthenticator.java"}}MyFormAuthenticator{{/scm}} and {{scm path="xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/user/impl/xwiki/MyBasicAuthenticator.java"}}MyBasicAuthenticator{{/scm}}. Note that a {{scm path="xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authentication/xwiki-platform-security-authentication-api/src/main/java/org/xwiki/security/authentication/UserAuthenticatedEvent.java"}}UserAuthenticatedEvent{{/scm}} should be created with a {{scm path="xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-api/src/main/java/org/xwiki/user/UserReference.java"}}UserReference{{/scm}}. | ||
| 9 | {{/version}} | ||
| 10 | |||
| 11 | {{version since="15.3"}} | ||
![]() |
10.6 | 12 | If you want your custom authenticator to be listed and selectable in the administration at runtime, you will need to expose it as a component with role `org.xwiki.security.authservice.XWikiAuthServiceComponent` and a unique hint. For existing authenticators adding this feature, a ##org.xwiki.security.authservice.AbstractXWikiAuthServiceWrapper## helper is provided which simply wrap your existing old style authenticator as a component. |
![]() |
10.2 | 13 | |
![]() |
10.7 | 14 | Note that you don't need to upgrade your XWiki dependency to 15.3 in your authenticator for this, you can depend on [[org.xwiki.contrib:authservice-backport:1.1.1>>extensions:Extension.AuthServiceBackport||anchor="HHaveyourauthenticatorappearinAuthServiceApplicationafterit27sinstalled"]] (which supports XWiki 8.4+) instead. |
![]() |
10.2 | 15 | {{/version}} |
| 16 | |||
![]() |
10.7 | 17 | == Use your authenticator == |
![]() |
10.2 | 18 | |
![]() |
10.4 | 19 | Edit the //WEB-INF/xwiki.cfg// file and add a //xwiki.authentication.authclass// property pointing to your class. For example: |
| |
1.1 | 20 | |
| 21 | {{code language="properties"}} | ||
| 22 | xwiki.authentication.authclass = com.acme.MyCustomAuthenticationService | ||
| 23 | {{/code}} | ||
| 24 | |||
![]() |
10.7 | 25 | == Example == |
![]() |
10.2 | 26 | |
![]() |
6.1 | 27 | Here is an example code for a custom authenticator: |
| |
4.1 | 28 | |
| 29 | {{code language="java"}} | ||
![]() |
10.5 | 30 | package com.acme; |
| 31 | |||
![]() |
5.1 | 32 | public class MyCustomAuthenticationService extends XWikiAuthServiceImpl |
| 33 | { | ||
![]() |
8.1 | 34 | // We cannot use "real" component injection here because authenticators are not components currently |
| 35 | // But it's recommended to put most of your authenticator's actual code in a component (or several components) and use this component, | ||
| 36 | // it will make it a lot easier to reuse various XWiki tools and APIs | ||
![]() |
10.1 | 37 | private MyCustomAuthentor authenticator = Utils.getComponent(MyCustomAuthenticator.class); |
| |
4.1 | 38 | |
![]() |
8.1 | 39 | // 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 |
![]() |
5.1 | 40 | // or other means of indicating what is the current user (HTTP headers, etc.) |
| 41 | @Override | ||
| 42 | public XWikiUser checkAuth(XWikiContext context) | ||
| 43 | { | ||
| 44 | // Call the actual authenticator | ||
| 45 | return this.authenticator.checkAuth(context); | ||
| 46 | } | ||
| |
4.1 | 47 | |
![]() |
8.1 | 48 | // This is the method which will be called if you reuse the standard means of gathering the credentials (login page, BASIC auth) |
| 49 | // 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.) | ||
![]() |
5.1 | 50 | @Override |
| 51 | public Principal authenticate(String username, String password, XWikiContext context) throws XWikiException | ||
| 52 | { | ||
| 53 | // Call the actual authenticator | ||
| 54 | return this.authenticator.checkAuth(context); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | @Component(roles = MyCustomAuthenticator.class) | ||
| 59 | @Singleton | ||
| 60 | public MyCustomAuthenticator | ||
| 61 | { | ||
| |
4.1 | 62 | @Inject |
![]() |
5.1 | 63 | private ObservationManager observation; |
| |
4.1 | 64 | |
![]() |
5.1 | 65 | public XWikiUser checkAuth(XWikiContext context) |
| |
4.1 | 66 | { |
| 67 | // You authenticate a user somehow | ||
![]() |
5.1 | 68 | ... |
| |
4.1 | 69 | |
![]() |
5.1 | 70 | // 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 |
| 71 | if (newAuth) { | ||
| 72 | // You have to retrieve its UserReference | ||
| 73 | // You should be able to use a UserReferenceResolver if needed | ||
| 74 | UserReference userReference = ...; | ||
| |
4.1 | 75 | |
![]() |
5.1 | 76 | // Then, trigger a UserAuthenticatedEvent by passing previously retrieved user reference to UserAuthenticatedEvent constructor |
| 77 | this.observationManager.notify(new UserAuthenticatedEvent(userReference), null); | ||
| 78 | } | ||
| |
4.1 | 79 | } |
| 80 | |||
![]() |
5.1 | 81 | public Principal authenticate(String username, String password, XWikiContext context) throws XWikiException |
| 82 | { | ||
| 83 | ... | ||
| 84 | } | ||
| |
4.1 | 85 | } |
![]() |
10.3 | 86 | |
| 87 | @Component | ||
| 88 | @Singleton | ||
| 89 | @Named(MyCustomAuthService.ID) | ||
| 90 | public class MyCustomAuthService extends AbstractXWikiAuthServiceWrapper implements XWikiAuthServiceComponent | ||
| 91 | { | ||
| 92 | /** | ||
| 93 | * The identifier of the authenticator. | ||
| 94 | */ | ||
| 95 | public static final String ID = "mycustom"; | ||
| 96 | |||
| 97 | /** | ||
| 98 | * Wrap a {@link MyCustomAuthenticationService} instance. | ||
| 99 | */ | ||
| 100 | public LDAPAuthService() | ||
| 101 | { | ||
| 102 | super(new MyCustomAuthenticationService()); | ||
| 103 | } | ||
| 104 | |||
| 105 | @Override | ||
| 106 | public String getId() | ||
| 107 | { | ||
| 108 | return ID; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | security.authservice.mycustom.name=My custom authenticator | ||
| 113 | security.authservice.mycustom.description=An example to show how to implement a custom authenticator | ||
| |
4.1 | 114 | {{/code}} |
| 115 | |||
![]() |
5.1 | 116 | You can find various authenticators examples in [[extensions>>http://extensions.xwiki.org/xwiki/bin/view/Main/WebHome#|t=extensions&p=1&l=30&s=doc.creationDate&d=desc&name=authenticator]] or [[sandbox>>https://github.com/xwiki-contrib/sandbox/tree/master/authenticators]]. |
| |
1.1 | 117 | |
| 118 | Here's a [[tutorial on implementing a custom authentication class for authenticating against Oracle's SSO>>http://bodez.wordpress.com/2008/10/15/xwiki-user-authentication-with-oracle-sso/]]. |

