Multiple Security Provider Implementation
The document provides an overview for implementing authentication for the application created in Studio using the Database as the security provider as well as using Google Oauth integration.
App settings to configure in Google Developer Console
- Login into the Google Developer Console https://console.developers.google.com/
- Create a project in the google developer account.
- From the API Manager left nav, select the Credentials option and navigate to the “OAuth Consent screen” tab. Provide Product Name and save the settings.
- Navigate to the Credentials tab, and create “oAuth client ID” credentials for the project.
- Choose the Application type as Web application. Enter the Authorized JavaScript Origin and Authorized Redirect URIs. An example of a sample redirect URI is as below:
https://www.wavemakeronline.com/run-[container-name]/[project-name]/prefabs/GoogleOAuth/oAuthHandler/callback
note
In the above URL change the container name and your project name accordingly.
- Click on Create. A client ID and client secret is issued for the specific client/user. Note down the client ID and secret as it will be used in the Studio application for further development purpose.
Configurations to be made in the Studio application
- Create a new application in Studio.
- Add Database to your app by Connect to Database to import Sample hrdb. You can choose to import any DB of your choice, ensure that there exists a table with Username/Role details.
- Create New page in the application to place the Google OAuth prefab for login.(lets call the page as GoogleLogin for reference in later points) NOTE: For the sake of convenience we have shown the use case with a different page for Google Login. You can implement these steps using the default Login page provided by WaveMaker.
- Drag and drop the Google OAuth prefab in this newly created page. For the prefab, specify the Secret, Scope, Appid, Page parameters. Please note that the Scope is with reference to the google API being utilised for ex: email. The Page parameter is the name of the page in which the googleOAuth prefab is placed i.e., the current page itself (GoogleLogin page)
- Open the Login page of the application and add a button widget below the Login button.
- Provide “Login Using Google” as the caption of the button widget. For the onClick event of the button widget, choose the Navigation variable for the page in which the google oAuth prefab is placed i.e., GoogleLogin page in the sample scenario.
- In the GoogleLogin page, create a page level Login action with the access token received from the googleOAuth prefab as input to the variable by binding it to the password field.
- For the on Load event of the google OAuth prefab, choose JavaScript as operation. In the function generated in the script tab of the page, place the code snippet below:
Page.<GoogleOAuth_prefab_name>Load = function(widget) {
angular.$watch('accesstoken', function(newVal) {
if (newVal) {
Page.Variables.<login_variable_page_level_name>.invoke();
}
});
};
- Open the File Explorer and locate pom.xml file and add the below dependency for the spring social google in the dependencies tag.
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-google</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
- Create a query which retrieves the user details based on the logged in user name. This query will be later on autowired and used in the Java Service for authenticating the user if DB as security provider is used.
- Create a Java Service named MyAuthenticationManager.
- Add the following import statements:
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.wavemaker.runtime.security.SecurityService;
import com.wavemaker.runtime.service.annotations.ExposeToClient;
import com.wavemaker.runtime.service.annotations.HideFromClient;
import jakarta.servlet.http.HttpServletRequest;
import com.wavemaker.runtime.security.SecurityService;
import com.wavemaker.runtime.service.annotations.ExposeToClient;
import com.wavemaker.runtime.service.annotations.HideFromClient;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.wavemaker.runtime.security.WMCustomAuthenticationManager;
import com.wavemaker.runtime.security.WMUser;
import org.springframework.social.google.api.Google;
import org.springframework.social.google.api.impl.GoogleTemplate;
import org.springframework.social.google.api.plus.Person;
import com.wavemaker.runtime.security.AuthRequestContext;
import org.springframework.data.domain.Page;
import com.hrdb.service.HrdbQueryExecutorService;
- The class definition is as follows:
//implementing the custom authentication Manager Class
@ExposeToClient
public class MyAuthenticationManager implements WMCustomAuthenticationManager {
private static final Logger logger = LoggerFactory.getLogger(MyAuthenticationManager.class);
@Autowired
private SecurityService securityService;
//autowiring the entity query executor for retrieving the logged in user details
@Autowired
private HrdbQueryExecutorService hrdbQueryExecutorService;
// overridding the authenticate method of custom authentication manager class
@Override
public WMUser authenticate(AuthRequestContext authRequestContext) {
HttpServletRequest httpServletRequest = authRequestContext.getHttpServletRequest();
//setting the logged in user object to null initially
WMUser user = null;
//checking for the security provider type i.e., whether it is OAuth or DB provider
String securityProvider = httpServletRequest.getParameter("j_username");
//logic for the OAuth as the security provider
if ("OAUTH".equals(securityProvider)) {
//obtaining the token from Prefab
String token = httpServletRequest.getParameter("j_password");
if (token == null) {
return null;
}
logger.info(" --------- Token is "+token);
try {
//passing the token to Google
Google google = new GoogleTemplate(token);
Person person = google.plusOperations().getGoogleProfile();
logger.info("----------------- -- - --- -----------"+ person.getDisplayName());
//creating the WMUSer i.e., logged in user object
user = new WMUser(token, person.getDisplayName(), Arrays.asList("user")); } catch (Exception e) {
logger.error("Failed to authenticate", e);
throw e;
}
} else {
//logic for the DB as security provider
String username = httpServletRequest.getParameter("j_username");
String providedPassword = httpServletRequest.getParameter("j_password");
//references the query created to obtain logged in user details
List<Object> userObjects = hrdbQueryExecutorService.executeGetUserByName(null, username).getContent();
if (userObjects == null || userObjects.size() != 1 ) {
return null;
}
Map userObject = (Map) userObjects.iterator().next();
String actualPassword = (String) userObject.get("PASSWORD");
if (providedPassword.equals(actualPassword)) {
user = new WMUser(username, username, Arrays.asList("user"));
}
}
// returning the logged in user object
return user;
}
}
- Open Security Dialog and choose the Security Provider as custom. Provide the Class Name property as the package name of the
MyAuthenticationManager
java service created above. Save the settings. - Run the Application.
- The login page appears, Login using the Login Page - admin/admin; you will see the Employee Data
- Logout and Login using Google Button; Google Login Page shows up