Managed File Transfer

 View Only

Custom UI Link in SI dashboard Menu with SSO functionality

By Tanvi Kakodkar posted Tue February 25, 2020 01:12 AM

  
Originally updated on September 12, 2018 by Murali k

With Manage Layout being removed as part of SI 6.0, no custom tabs can be introduced and customers will have to migrate their Portlet based web components with integrating custom UIs into Dashboard. Since Menu item on the Dashboard left-nav-bar is configurable, one can configure a new URL that points to a webapp that's hosted on HttpServerAdapter or on an external web server.When the new URL is clicked, the webapp can do the SSO with B2Bi and open the url in a new Window/Tab

 

Steps to add custom link in SI dashboard Menu

  • System User can create an installation jar which will get installed to SI using InstallServices.sh or InstallServices.cmd.
  •  The installation jar should have following files laid out properly. It must follow the directory structure 

         < Project_name>

                      -----   exploded_wars

                     -----------------------admin

                      ------------------------------------jsp

                      -----------------------------------------custom.jsp

                      -----    factorysetup

                      -------------- XMLS

                      ----------------------- YFS_MENU.xml

                      ----------------------- YFS_RESOURCE.xml

                      -------------- installer.xml

                      -------------- custom_menu_installer.xml

                     ------files

                      -------------------properties

                     -------------------------------lang

                      ---------------------------------------en

                     ------------------------------------------------------ Sitemap_en.properties_custom_ext

 

  • Create custom jsp and place under Project_name/exploded_wars/admin/jsp/custom_folder_name/custom.jsp

Actual content will go here in this jsp (user can give any name for this jsp). This JSP will have   an link to launch custom application.

  • Add entry at Project_name/factorysetup/XMLS/ YFS_MENU.xml  to create custom menu items. It will appear on left tree menu on dashboard. User can provide sequence for reordering. 

Example is as below –

<YFS_MenuList>

 

    <Menu DisplayMode="" Icon=""

       MenuDescription="CustomMenu"

       MenuKey="ADM_62_010" MenuSeq="62" MenuType="MENU"

       ParentMenuKey="ADM" ResourceKey="" SystemDefined="Y"/>

 

    <Menu DisplayMode="" Icon=""

         MenuDescription="CustomLink"

         MenuKey="ADM_62_010_010" MenuSeq="10" MenuType="MENU"

         ParentMenuKey="ADM_62_010" ResourceKey="NEWCUSTOMLINK" SystemDefined="Y"/>

 

 </YFS_MenuList>

  • Create resource entries for the page defined at below location

               Project_name/factorysetup/XMLS/YFS_RESOURCE.xml

Example is as below –

<?xml version="1.0" encoding="UTF-8"?>

<YFS_ResourceList>

   <Resource ApplicationCode="plt" ApplicationName="PLTADM0001"

     CanAddToMenu="Y" DocumentType="" IsPermissionControlled="Y"

     ParentResourceId="PLTADM0001" ResourceCreateType="SYSTEM"

     ResourceDesc="custom sample link" ResourceId="NEWCUSTOMLINK"

     ResourceKey="NEWCUSTOMLINK" ResourceSeq="210" ResourceType="0"

     SupportsSearchToDetail="N" Url="./Page?next=page.samplecustomappmgmt"/>

</YFS_ResourceList>

 

  •  Make jsp entries in page.properties.in file

               For example page.<Name of page>.path  = /jsp/custom_folder_name/custom.jsp

 

  • Add entries for the custom menu description defined in YFS_MENU.xml as above in the file

Sitemap_en.properties_custom_ext.

For example -

Link.CustomMenu = Custom Menu

Link.CustomLink = Open Custom Web App

  • Create installer.xml and custom_menu_installer.xml and mention the resource xml file which need to be installed.

 In custom_menu_installer.xml we need to mention the name of xml files created under XMLS

Sample Entry for custom_menu_installer.xml 

<Task Class="XMLMigrator" Description="custom menu Installation" When="First">

    <TaskInfo Completed="N">

                 <EntityList>

    <Entity AbortOnError="N" Class="YFS_Resource"  CommitCount="50" Completed="N" NumRecordsProcessed="0"  ResetEntityAttributes="Y" TruncateTable="N" XMLFile="YFS_RESOURCE.xml"/>

    <Entity AbortOnError="N" Class="YFS_Menu"  CommitCount="50" Completed="N" NumRecordsProcessed="0"  ResetEntityAttributes="Y" TruncateTable="N" XMLFile="YFS_MENU.xml"/>

                </EntityList>

    </TaskInfo>

</Task>

 

Sample Entry for installer.xml 

<Task When="AfterChildren" Description="Custom Menu Installation" Class="DoNothingMigrator">

    <TaskInfo Completed="N"/>

     <ChildTasks>

         <Task When="First" Description="Custom Menu installation" Class="MigratorMain">

            <TaskInfo Completed="N" InputFile="custom_menu_installer.xml"/>

        </Task>

    </ChildTasks>

</Task>

Here we need to mention custom menu installation.xml

  • Create jar file with the same folder structure as specified in above step
  •  Go to <SI install Location>/bin. and run ./InstallService.sh <jar file    Name>
  •  Restart SI server.

Once we have done this steps we should see custom menu links in SI dashboard.

 

SSO to custom Web App

The  REST API’s at B2Bi end used for SSO and authentication will be deployed as a WAR file on a HTTP Server adapter in B2Bi. Below is the HTTP Server Adapter deployed with rest war over SSL.

 

We have custom jsp (gets served when clicked on custom link created above) which would provide an link to launch an custom web app running on different server.

Sample custom jsp file which have link to launch the custom web application is as below,

 

Below is the custom jsp file code logic to fetch the dlsso token, username and nodename which is used by custom web app to authenticate with SI when did an SSO to custom web application by clicking on the custom link.

 

<%@page language="java" import="java.net.URLEncoder,com.sterlingcommerce.woodstock.ui.UIGlobals,com.sterlingcommerce.woodstock.ui.dlsso.DLSSOSessionHash,java.net.InetAddress,java.net.UnknownHostException,com.sterlingcommerce.woodstock.util.frame.Manager" errorPage="/jsp/error_report_info.jsp"%>

 

                                                                                <%          

                                                                               

                                                                                                String userName = (String)session.getAttribute(DLSSOSessionHash.USERNAME_ATTR);

                                                                                                String dlssoToken = null;

                                                                                                Cookie [] clist = request.getCookies();

                                                                                                for(int i = 0 ; i < clist.length ; i++ ) {

                                                                                                                if(DLSSOSessionHash.SSO_COOKIENAME.equals(clist[i].getName())){

                                                                                                                                dlssoToken = URLEncoder.encode(clist[i].getValue());

                                                                                                                }

                                                                                                }

                                                                                                String nodeName = UIGlobals.getNodeName();

                                          String ipaddr = Manager.getProperties("si_config").getProperty("CUSTOM_WEBAPP_HOST_ADDR");

                                                                                                String port = Manager.getProperties("si_config").getProperty("CUSTOM_WEBAPP_HTTP_PORT");

                                                                                                String httpsport = Manager.getProperties("si_config").getProperty("CUSTOM_WEBAPP_HTTPS_PORT");

                                                                                                           

                                                                               

                                                                                                String queryParams = "&userName="+userName+"&dlssoToken="+dlssoToken+"&nodeName="+nodeName;

                                                                                                                                                                               

                                                                                %>

 

                                               

We have configured  the host and port details where the custom web app deployed in sandbox.cfg and we get those  details and call the custom web app passing the query parameters( username,dlsso token, node name) in a new browser window.

 

If we have deployed some custom  HelloServlet web application and configured the hostname and port details about the custom web application in sandbox.cfg, the url link for the custom web application opened up on new browser window for SSO authentication would be as below,

http://ipaddr:port/HelloServlet/hello?&userName=admin&dlssoToken=U2Vzc2lvbklEbm9kZTA0bm52bXZxczhhNmJtMG0yMDkzY253cDQxMA%3D%3D&nodeName=node1

 

Custom WebAPP authenticating with B2Bi SSO API

Custom Web application would call the REST SSO API to check if user is authenticated.

When we get a request, we get the request parameters and check if we want to do an SSO

Authentication with B2Bi.

Below is the sample code to check if we want to call REST SSO API,

String userName = parameters.get("userName");

              String nodeName = parameters.get("nodeName");

              String ssoToken = parameters.get("dlssoToken");

 

              return !StringUtils.isEmpty(userName) && !StringUtils.isEmpty(nodeName) && !StringUtils.isEmpty(ssoToken);

 

If we see the request contains username, nodename, dlssotoken we would call the SSO REST API to authenticate the user.

Below sample code would make a REST call and parse the json string response to json object and check if the user is authenticated.

REST API –

POST  https://ipaddr:port/restwar/restapi/v1.0/authenticate/sso

userName=<USER NAME>

dlssoToken=<DLSSO TOKEN>

nodeName=<NODE NAME>

 

This API takes user name, dlsso token and node name as input and return JSON as output.

 

Sample Response from SI -

response -- > {"user": {

  "authenticated": "true",

  "groups": [

    "super",

    "notifications",

    "DEPLOYMENT",

    "mbiusers",

    "mboxadmins",

    "ACCOUNTS",

    "OPERATIONS",

    "SERVICES",

    "MAILBOX",

    "SSH",

    "ADVANCED_SETUP",

    "EBXML",

    "BPMONITOR",

    "ENVELOPES",

    "MAPS",

    "WEB_EXTENSIONS",

    "WEB_SERVICES",

    "ADAPTER_UTILITIES"

  ],

  "name": "admin"

}}

 

Sample code for SSO Authentication

We used apache wink as rest client for this sample.

                                               

private static boolean authenticateSSO(Map<String, String> parameters) {

             

              org.apache.wink.client.ClientConfig clientConfig = new org.apache.wink.client.ClientConfig();

              /**

               * clientConfig.setBypassHostnameVerification(true); 

               * used only to bypass hostname check for  self signed certificates used for internal testing

               * PRODUCTION- do not use this

               *

               */

              clientConfig.setBypassHostnameVerification(true);

      

              org.apache.wink.client.RestClient client = new org.apache.wink.client.RestClient(clientConfig);

              StringBuilder api = new StringBuilder( "https://ipaddr:port/restwar/restapi/v1.0/authenticate/sso");

             //get the required query params from request

              String userName = parameters.get("userName");

              String dlssoToken = parameters.get("dlssoToken");

              String nodeName = parameters.get("nodeName");

      

              org.apache.wink.client.Resource resource = client

                           .resource(api.toString()).accept("application/json");

              resource.contentType("application/x-www-form-urlencoded");

              StringBuilder body = new StringBuilder("userName=").append(userName).append("&").append("dlssoToken=").append(dlssoToken).append("&").append("nodeName=").append(nodeName);

             

              /**

               * trustAllCertificates()

               * used only to trust all certificates used for internal testing

               * PRODUCTION - we should not use this

               */

              trustAllCertificates();

             

              String resp = resource.post(String.class,body.toString());

              System.out.println(" response -- > " + resp);

              JSONParser jsonParser = new JSONParser();

              JSONObject jsonResponse = null;

              try {

                     jsonResponse = (JSONObject) jsonParser.parse(resp);

              } catch (ParseException e) {

                     e.printStackTrace();

         }

             

//Check the response if user is authenticated

               JSONObject errorObj = (JSONObject) jsonResponse.get( "error" );

               if ( errorObj != null ) {

                   String code = (String) errorObj.get( "code" );

                   String description = (String) errorObj.get( "description" );

                   String msg = (String) errorObj.get( "message" );

 

                   System.out.println("Error returned from SSO authentication API: code="+ code +  " description="+ description+ "  message=" +  msg );

                   return false;

               }

 

               

        JSONObject userObj = (JSONObject) jsonResponse.get( "user" );

        if ( userObj == null ) {

            System.out.println("\"Unrecognized response from SSO authentication API. Expected field not found: 'user'\"");

            return false;

        }

       

       

        String username = (String) userObj.get( "name" );

        if ( StringUtils.isEmpty( userName ) ) {

            System.out.println("Unrecognized response from SSO authentication API. Expected field not found: 'name'");

           return false;

        }

     

        String authenticated = (String) userObj.get( "authenticated" );

        if ( StringUtils.isEmpty( authenticated ) ) {

            System.out.println( "Unrecognized response from SSO authentication API. Expected field not found: 'authenticated'");

           return false;

        }

 

        System.out.println("Authenticated --> " + authenticated);

        if ( !Boolean.parseBoolean( authenticated ) ) {

            

            // Authentication failed

             System.out.println( "SSO authentication failed: userName=" +  username);

            return false;

        }

             

              return true;

             

       }



Custom Webapp authenticating with B2Bi useraccount
 

If we need to login to custom webapplication by using any user account of B2Bi, we can call REST API exposed from B2Bi by passing the username and password details entered from the login page to the B2Bi Rest API


REST Authentication API
 

These API are used for authentication. When a user is authenticated a JSESSION ID will be returned in the response header. This JSESSION ID should be used in subsequent API calls.

 

POST https://9.113.211.25:21097/restwar/restapi/v1.0/authenticate

userName=<USER NAME>

password=<PASSWORD>

 

This API takes user name and password as input and return JSON as output.

 

Sample Output

 

{"user": {

  "authenticated": "true",

  "groups": [

    "super",

    "spe_admin",

  ],

  "name": "admin"

}}

 

Sample code for Authentication

 

private static boolean authenticateLogin(Map<String, String> parameters) {

              org.apache.wink.client.ClientConfig clientConfig = new org.apache.wink.client.ClientConfig();

              /**

               * clientConfig.setBypassHostnameVerification(true); 

               * used only to bypass hostname check for  self signed certificates used for internal testing

               * PRODUCTION- do not use this

               *

               */

              clientConfig.setBypassHostnameVerification(true);

             

              org.apache.wink.client.RestClient client = new org.apache.wink.client.RestClient(clientConfig);

              StringBuilder api = new StringBuilder( "https://ipaddr:port/restwar/restapi/v1.0/authenticate");

 

//get the username and password from the request          

String username = parameters.get("un");

              String password = parameters.get("pw");

             

      

              org.apache.wink.client.Resource resource = client

                           .resource(api.toString()).accept("application/json");

              resource.contentType("application/x-www-form-urlencoded");

              StringBuilder body = new StringBuilder("userName=").append(username).append("&").append("password=").append(password);

              /**

               * trustAllCertificates()

               * used only to trust all certificates used for internal testing

               * PRODUCTION - we should not use this

               */

              trustAllCertificates();

              String resp = resource.post(String.class,body.toString());

             

 

              System.out.println(" response -- > " + resp);

              JSONParser jsonParser = new JSONParser();

              JSONObject jsonResponse = null;

              try {

                     jsonResponse = (JSONObject) jsonParser.parse(resp);

              } catch (ParseException e) {

                     e.printStackTrace();

}

             

               JSONObject errorObj = (JSONObject) jsonResponse.get( "error" );

               if ( errorObj != null ) {

                   String code = (String) errorObj.get( "code" );

                   String description = (String) errorObj.get( "description" );

                   String msg = (String) errorObj.get( "message" );

 

                   System.out.println("Error returned from Login authentication API: code="+ code +  " description="+ description+ "  message=" +  msg );

                   return false;

               }

 

               

        JSONObject userObj = (JSONObject) jsonResponse.get( "user" );

        if ( userObj == null ) {

            System.out.println("\"Unrecognized response from Login authentication API. Expected field not found: 'user'\"");

            return false;

        }

       

       

        String userName = (String) userObj.get( "name" );

        if ( StringUtils.isEmpty( userName ) ) {

            System.out.println("Unrecognized response from Login authentication API. Expected field not found: 'name'");

           return false;

        }

     

        String authenticated = (String) userObj.get( "authenticated" );

        if ( StringUtils.isEmpty( authenticated ) ) {

            System.out.println( "Unrecognized response from Login authentication API. Expected field not found: 'authenticated'");

           return false;

        }

 

        System.out.println("Authenticated --> " + authenticated);

        if ( !Boolean.parseBoolean( authenticated ) ) {

            

            // Authentication failed

             System.out.println( "Login authentication failed: userName=" +  userName);

            return false;

        }

             

              return true;

       }


#DataExchange
#IBMSterlingB2BIntegratorandIBMSterlingFileGatewayDevelopers
0 comments
29 views

Permalink