Implementing Java-based custom authenticators
You can use default MobileFirst login modules and authenticators, or customize your own.
About this task
You can write custom login modules and authenticators when those that IBM MobileFirst™ Platform Foundation supplies do not match your requirements.
Procedure
Example
The following example shows how to implement a custom authenticator and login module. In the example, an adapter procedure is protected by a custom authenticator. When the user attempts to call the procedure from the application, the application requests the user's credentials and the authentication process starts.
- Configuration of the authenticationConfig.xml file
<securityTests> <customSecurityTest name="DummyAdapter-securityTest"> <test isInternalUserID="true" realm="CustomAuthenticatorRealm"/> </customSecurityTest> </securityTests> <realms> <realm name="CustomAuthenticatorRealm" loginModule="CustomLoginModule"> <className>com.mypackage.MyCustomAuthenticator</className> </realm> </realms> <loginModules> <loginModule name="CustomLoginModule"> <className>com.mypackage.MyCustomLoginModule</className> </loginModule> </loginModules>
- Coding the server side
- Code the following elements on the server side: adapter, authenticator, and login module.
- Adapter:
- Create a MobileFirst adapter.
- Add a procedure and protect it with the custom security test that
you created earlier. The implementation can return some hardcoded
value. For example:
<procedure name="getSecretData" securityTest="DummyAdapter-securityTest"/>
- Authenticator:
- Create a MyCustomAuthenticator.java class in
the server/java/com/mypackage folder. This class
must implement the com.worklight.server.auth.api.WorkLightAuthenticator interface,
as follows:
public class MyCustomAuthenticator implements WorkLightAuthenticator{}
- Add the generated serialVersionUID constant to the class.
- Implement the mandatory methods of the class.
- processRequest: This method retrieves the user
name and password credentials that are passed as request parameters.
Check the credentials for basic validity, collect the credentials,
and return SUCCESS. If a problem occurs with the
received credentials, add an errorMessage to the
response and return the CLIENT_INTERACTION_REQUIRED status
message. If the request does not contain authentication data, add
the authStatus:required property to the response
and again, return a CLIENT_INTERACTION_REQUIRED status
message.
public AuthenticationResult processRequest(HttpServletRequest request, HttpServletResponse response, boolean isAccessToProtectedResource) throws IOException, ServletException { if (request.getRequestURI().contains("my_custom_auth_request_url")){ String username = request.getParameter("username"); String password = request.getParameter("password"); if (null != username && null != password && username.length() > 0 && password.length() > 0){ this.username = request.getParameter("username"); this.password = request.getParameter("password"); return AuthenticationResult.createFrom(AuthenticationStatus.SUCCESS); } else { response.setContentType("application/json; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache, must-revalidate"); response.getWriter().print("{\"authStatus\":\"required\", \"errorMessage\":\"Please enter username and password\"}"); return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED); } } if (!isAccessToProtectedResource) return AuthenticationResult.createFrom(AuthenticationStatus.REQUEST_NOT_RECOGNIZED); response.setContentType("application/json; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache, must-revalidate"); response.getWriter().print("{\"authStatus\":\"required\"}"); return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED); }
- processAuthenticationFailure: This method writes
an error message to a response body and returns the CLIENT_INTERACTION_REQUIRED status
message.
public AuthenticationResult processAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, String errorMessage) throws IOException, ServletException { response.setContentType("application/json; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache, must-revalidate"); response.getWriter().print("{\"authStatus\":\"required\", \"errorMessage\":\"" + errorMessage + "\"}"); return AuthenticationResult.createFrom(AuthenticationStatus.CLIENT_INTERACTION_REQUIRED); }
- processRequest: This method retrieves the user
name and password credentials that are passed as request parameters.
Check the credentials for basic validity, collect the credentials,
and return SUCCESS. If a problem occurs with the
received credentials, add an errorMessage to the
response and return the CLIENT_INTERACTION_REQUIRED status
message. If the request does not contain authentication data, add
the authStatus:required property to the response
and again, return a CLIENT_INTERACTION_REQUIRED status
message.
- Create a MyCustomAuthenticator.java class in
the server/java/com/mypackage folder. This class
must implement the com.worklight.server.auth.api.WorkLightAuthenticator interface,
as follows:
- Login module:
- Create a MyCustomLoginModule.java class in the server/java/com/mypackage folder.
This class must implement the com.worklight.server.auth.api.WorkLightAuthLoginModule interface.
public class MyCustomLoginModule implements WorkLightAuthLoginModule{}
- Implement the mandatory methods of the class.
- login: This method retrieves the user name and
password credentials that the authenticator stored previously. In
this example, the login module validates the credentials against hardcoded
values. You can implement your own validation rules. If the credentials
are valid, the login method returns true. For example:
public boolean login(Map<String> authenticationData) { USERNAME =(String) authenticationData.get("username"); PASSWORD = (String) authenticationData.get("password"); if (USERNAME.equals("wluser") && PASSWORD.equals("12345")) return true; else throw new RuntimeException("Invalid credentials"); } </String>
- createIdentity: This method is called when the login method
returns true. It is used to create a UserIdentity object.
In that object, you can store your own custom attributes and use them
later in Java or adapter code.
The UserIdentity object contains user information.
Its constructor is as follows:
Here is an example of how to implement this method:public UserIdentity(String loginModule, String name, String displayName, Set<String> roles, Map<String, Object> attributes, Object credentials)
public UserIdentity createIdentity(String loginModule) { HashMap<String, Object> customAttributes = new HashMap<String, Object>(); customAttributes.put("AuthenticationDate", new Date()); UserIdentity identity = new UserIdentity(loginModule, USERNAME, null, null, customAttributes, PASSWORD); return identity; }
- login: This method retrieves the user name and
password credentials that the authenticator stored previously. In
this example, the login module validates the credentials against hardcoded
values. You can implement your own validation rules. If the credentials
are valid, the login method returns true. For example:
- Create a MyCustomLoginModule.java class in the server/java/com/mypackage folder.
This class must implement the com.worklight.server.auth.api.WorkLightAuthLoginModule interface.
- Adapter:
- Coding the client side
- Follow these steps:
- Create a MobileFirst application.
- Create a challenge handler in the application to handle challenges
from the custom authenticator realm. For example:
var myAppRealmChallengeHandler = WL.Client.createChallengeHandler ("CustomAuthenticatorRealm");
- Implement the mandatory isCustomResponse and isCustomResponse methods, and optional methods of the challenge handler, as described in Step 3.
What to do next
For a more extensive example of implementing custom authentication and login, see the Custom authentication in hybrid applications tutorial.
IBM MobileFirst Platform Foundation provides other custom authentication mechanisms:- Adapter-based custom authentication. For more information, see Implementing adapter-based authenticators.
- HTTP-based custom authentication. For more information, see HTTP-based authentication.