Skip to content

Dynamic SSO Code Explanation

Introduction

This document explains the SSO code developed by AIV. In this document, we have explained each method of SSO to help users understand. Additionally, we have demonstrated here how users and roles can be created dynamically.

With normal SSO, the signed-in user is checked against the list of users available in the AIV user table. However, there might be clients who require that if the logged-in user in the third-party application does not exist in AIV, then the user and role details should be read from the URL and automatically added to AIV, with the appropriate role assigned.

Considering this scenario, we have made changes in the SSO code to dynamically add users and roles.

Image

Prerequisites

  1. Download the sample project from here.

  2. The insertuser_enabled property should be added to the config.json file inside the ‘sso’ property. If you do not find this property in your ‘config.json’ file, please copy the property from below:

    {
    	"name" : "insertuser_enabled",
    	"displayName" : "Insert User",
    	"defaultValue" : true,
    	"type" : "checkbox"
    }

    Image

Code Explanation

  1. The code begins with importing the required dependencies, as shown in the code snippet below:

    package com.aiv.sso;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.FileHandler;
    import java.util.logging.Handler;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import java.util.logging.SimpleFormatter;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.io.IOUtils;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import com.activeintelligence.external.sso.SSOSecurity;
    
  2. The following code initializes the Java logger. In Java, logging is an important feature that helps developers to trace out the errors. Java is the programming language that comes with the logging approach. It provides a logging API that was introduced in Java version 1.4. It provides the ability to capture the log file.

  • Here, we have initialized the logger and provided the path where this log file will be stored.

    public class aivSSOImpl implements SSOSecurity {
    	private static final Logger logger = Logger.getLogger(aivSSOImpl.class.getName()); // init of logger
    	private static final String LOG_FOLDER = "C:/aiv/logs/";
    }
  1. Users can configure logger settings using the code snippet provided below. For example, they can set the logging level, components, logging handlers or appenders, logging formatters or layouts, and Java Logger class.

    	public aivSSOImpl() { // to read external settings if any
    		try {
    			Handler fileHandler = new FileHandler(LOG_FOLDER + "sso.log", true);
    			fileHandler.setLevel(Level.ALL);
    			fileHandler.setFormatter(new SimpleFormatter());
    
    			logger.addHandler(fileHandler);
    
    		} catch (IOException e) {
    			logger.severe(e.getMessage());
    		}
    	}
  2. The following code snippet contains the business logic for user authentication. It includes logic to extract the username, department, and token from the client application URL and authenticate with the list of users available in the AIV database. It will allow the user to access AIV when a match is found.

  • Here, we are providing default user and role options if the user is not found in AIV and the insertuser_enabled property is set to true in the config.json file.

    	@Override
    	public Map<String, Object> authenticate(ServletRequest request, ServletResponse response, String extraInfoIN) { // for
    		logger.info("Inside SSO");																										// external
    		HttpServletRequest req = (HttpServletRequest) request;
    		Map<String, Object> rtObj = null;
    		String userName =null;
    		String userToken = null;
    
    		String str = null;
    		
    		
    		try {
    			
    			str = IOUtils.toString(request.getInputStream());
    			JSONObject jsonObj = new JSONObject(str);
    			userName=jsonObj.getString("userName");
    			userToken=jsonObj.getString("token");
    			Map<String, Object> userOptions = new HashMap<String, Object>();
    			userOptions.put("firstName", userName);
    			userOptions.put("lastName", userName);
    			userOptions.put("userName", userName);
    			userOptions.put("status","Active");
    			userOptions.put("password", "");
    			userOptions.put("email", "sample@gmail.com");
    			userOptions.put("homeFolder", "/"+userName);
    			userOptions.put("backupUserId", "1");
    			userOptions.put("managerUserId", "1");
    			userOptions.put("adhocOption", "1");
    			userOptions.put("dashboardOption", "1");
    			userOptions.put("alertsOption", "1");
    			userOptions.put("reportOption", "1");
    			userOptions.put("mergeReportOption", "1");
    			userOptions.put("resourceOption", "1");
    			userOptions.put("quickRunOption", "1");
    			userOptions.put("mappingOption", "1");
    			userOptions.put("messageOption", "1");
    			userOptions.put("datasetOption", "1");
    			userOptions.put("parameterOption", "1");
    			userOptions.put("annotationOption", "1");
    			userOptions.put("notificationOption", "1");
    			userOptions.put("requestOption", "1");
    			userOptions.put("adminOption", "0");
    			userOptions.put("scheduleOption", "1");
    			userOptions.put("userType", "INT");
    			userOptions.put("default_dashboard", null);
    			userOptions.put("landing_page", "Documents/Reports");
    			userOptions.put("locale", "en");
    			userOptions.put("timezone", "SYSTEM");
    			userOptions.put("notification", "1");
    			userOptions.put("theme", "Default");
    			userOptions.put("department", "Default");
    			logger.info("Inside userOptions SSO");	
    			
    			
    			Map<String, Object> roleOptions = new HashMap<String, Object>();
    			roleOptions.put("description", "");
    			roleOptions.put("email", "sample@gmail.com");
    			roleOptions.put("dashboardOption", "1");
    			roleOptions.put("alertsOption", "1");
    			roleOptions.put("reportOption", "1");
    			roleOptions.put("mergeReportOption", "1");
    			roleOptions.put("adhocOption", "1");
    			roleOptions.put("resourceOption", "1");
    			roleOptions.put("quickRunOption", "1");
    			roleOptions.put("mappingOption", "1");
    			roleOptions.put("messageOption", "1");
    			roleOptions.put("datasetOption", "1");
    			roleOptions.put("parameterOption", "1");
    			roleOptions.put("annotationOption", "1");
    			roleOptions.put("notificationOption", "1");
    			roleOptions.put("requestOption", "1");
    			roleOptions.put("adminOption", "0");
    			roleOptions.put("scheduleOption", "1");
    			roleOptions.put("department", "Default");
    			logger.info("Inside roleOptions SSO");	
    			if (userName.equals("Admin") && userToken.equals("S3CUR3T0K3N")){
    				/*
    				* put your own Authenticate logic to verify userName, password and Token. In
    				* the below we are matching username and token and returning object value
    				*/
    				logger.info(userName + "|" + userToken + "|");
    				rtObj = new HashMap<String, Object>();
    				rtObj.put("userName", userName);
    				if(jsonObj.has("deptCode")) rtObj.put("deptCode", jsonObj.getString("deptCode"));
    				HttpServletResponse res = (HttpServletResponse) response;
    				res.setHeader("tokens", userToken);
    				if (str != null) {
    					rtObj.put("requestValues", jsonObj.toString());
    				}
    				return rtObj;
    			}
    			else {
    				rtObj = new HashMap<String, Object>();
    				rtObj.put("userName", userName);
    				logger.info(userName);
    				if(jsonObj.has("deptCode")) rtObj.put("deptCode", jsonObj.getString("deptCode"));
    				if (str != null) {
    					rtObj.put("requestValues", jsonObj.toString());
    				}
    				rtObj.put("userOptions", userOptions);
    				rtObj.put("roleOptions", roleOptions);
    				rtObj.put("assignedRole", "Administrator;example@gmail.com,Test2;example2@gmail.com");
    				return rtObj;
    			}
    		} catch (IOException | JSONException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    			return null;
    		}
    		
    	}

Test End-to-End Flow

  • The provided code is used to validate the userName, deptCode, and tokens from the embed URL. If a user has a third-party application and wants to display a dashboard within their application, AIV offers the feature of an embed link for the dashboard. Users can embed this dashboard link into their application using an iframe. However, this embed link requires user credentials, such as a username, password, or session token, to be validated when the dashboard is called via the embed link. If the user credentials are invalid, the dashboard will not open within the iframe.

  • To load dashboard in an iframe, user need to send user name, password, department name and session token in URL and AIV will validate user credentials with SSO code provided above. This is basic SSO code and user can apply his own logic to validate valid user.

  • Here, we use the userName, deptCode, and static token to validate a valid user of AIV.

  • Let’s configure this code and verify the functionality of the Single Sign-On (SSO) user verification by using a sample embed link of the dashboard for an Admin user.

  • From the ‘Prerequisites’ section, download the sample project. Within the zip file, you will find a folder named “sample sso project.”

  1. Extract the project and open it in the Eclipse IDE.

  2. Open aivSSOImpl.java class from src/com.aiv.sso/ project path.

  3. Navigate to line 25 of the code in Eclipse and update the folder path for the “logs” folder as instructed in step 6 of the SSO & External security document.

  4. Save the changes you’ve made and ensure that there are no errors in the project.

  5. Right-click on the aivSSO project and select the Export option to create a JAR file.

  6. Select the JAR file from the export window and click ‘Next’.

  7. Provide jar file export path and name of jar file.

  1. Stop the Tomcat server if it’s running, then place this JAR file in the (your_directory)/aiv/tomcat/webapps/aiv/WEB-INF/lib/ folder.

  2. Restart Tomcat server.

  3. Log in to the AIV application, navigate to AIV Configurations, and select SSO Configuration from the left vertical menu to enable Single Sign-On (SSO) settings, as depicted in the accompanying figure.

    Image

  4. Enter in class name: com.aiv.sso.aivSSOImpl, as shown in figure. [It implements SSO JAR File class path].

  5. Click the Submit button to save the changes.

  6. Go to the dashboard section and generate an embed link for any working dashboard without enabling the bypass option.

  7. Copy this embed URL and paste it in any text editor application. Provide password at &a_p__ and static token at &a_t__ (static token we have used in SSO code : S3CUR3T0K3N) in copied embed link.

  • User can change in SSO code to get token dynamically.

  • Following embed link for example:

http://localhost:8080/aiv/embed/external/31767950674266325a554a743438647a6e7a4e374a4542777a67726650585833656d356d4f704f54587077253344/a_u__Admin&a_p__password&a_t__S3CUR3T0K3N&a_d__Default&a_ex__&a_af__false/noparam
  1. Run this embed link in a browser, the dashboard will be displayed if the user credentials are valid. The SSO code will retrieve credential details from the embed link, validate them with AIV user details, and allow the dashboard to load.

  2. If a user passed with the embed link is not available in AIV, when executing this embed link in the browser, AIV automatically creates the user and assigns a role to the user. Then, the dashboard will be displayed for that user. This entire process is completed on the fly without any extra effort.

  3. To understand this scenario, use the above embed link and change the username and password. Ensure that the username you enter is not available in AIV.

  4. Execute this embed link in the browser, and you will see the same dashboard open for that user. To verify that the user is created in AIV, log in to AIV with an Admin user and check if the user and role are created from the Administration section.