Project

General

Profile

Single Sign On

Summary

FWD's Single Sign On (SSO) is a web feature providing the toolset for implementing flexible end-user authentication for both Virtual Desktop and Embedded modes. FWD's SSO combines into one the multiple login screens previously present in Virtual Desktop mode. The first login was for the framework to determine the operating system (OS) user and password before spawning the client. The second login screen was part of the 4GL app and was asking for the user's in-app credentials. With some additions to directory configurations and Admin UI, FWD places the OS authentication in the background and moves the in-app user authentication before the 4GL client spawn, which spares allocating resources for running clients with anonymous sessions. In addition the customer is presented a complete toolset to implement any authentication strategy: integration with any authentication server, DB or directory, Single Sign-On, Two-Factor Authentication or simply applying the brand styles to the login and logout pages.

FWD's SSO involves both front-end and back-end development. FWD's SSO defines a Java API with the SsoAuthenticator interface, allowing the customer to take full control over the specifics of authenticating users in the back-end, while at the same the framework integrates seamlessly the process with other FWD features and the 4GL converted app. There are several options, when it comes to the front-end. The customer can decide to completely take over the looks and functionality of the login / logout pages or use the pages provided by default and rebrand them with their own logo and styles. Both options support easy replacement of the corresponding web resources. The contract with the front-end is through a non-CORS POST request to /gui, /chui or /embedded, that is performed by fwd_sdk.js.

Migration

The initial work on SSO went under #3931. When it's merged, certain migration steps will have to be performed.

  • all customers using Embedded mode will have to fully migrate to SSO, since the previous authentication mechanisms are not supported any more.
  • customers using Virtual Desktop are not required to migrate to SSO immediately, but there are some general changes that will require migration of current configurations.

Common migration to latest trunk for all modes

Here come the common changes affecting all web modes:
  • Embedded remote network interface WebClientLauncher is removed.
  • The login page is already served in <iframe>. It will break UI tests. The fix should go along the lines of const window = document.querySelector("#main-iframe").contentWindow;.
  • Enabling drivers in directory configurations is streamlined. Only two props are supported:
    • The original webClient/virtualDesktopEnabled is renamed to webClient/virtualDesktop;
    • Embedded is now enabled by webClient/embedded;
    • webClient/enabled is removed;
    • embeddedWebApp/enabled is removed.
  • The default operating system user for web clients is now defined by a webClient/defaultOsUser, originally webCLient/defaultAccount.
  • trustedspawner security plugin is removed.
  • remotelaunchoption security plugin is not used at present and its configs in directory can be removed.
  • Reconversion is needed to support the new attribute SESSION:AUTH-BLOB.

Migration to SSO

For all embedded clients it's required to enable SSO.

  • The customer should implement the interface SsoAuthenticator and add the new Java class to the jar in their build script.
  • Auto-login is supported with overriding the default methods in SsoAuthenticator.
  • The authenticator should be enabled with directory config auth-mode/ssoplugin with the fully qualified name of the custom class and an optional auth-mode/ssopluginoption with any custom string that can be parsed and used as configs by the authenticator.
  • A full list of the possible OS users for spawning web clients should be defined in the Admin UI under /accounts/os-users.
  • In-app users are authenticated with SsoAuthenticator and a corresponding FWD user is returned. All / some of the FWD users should be mapped to OS users explicitly in the Admin UI under /accounts/users in the Edit User dialog, and / or a default OS user should be defined in webClient/defaultOsUser (renamed from webClient/defaultAccount).
  • embeddedWebApp/cfgOverrides was moved to webClient/cfgOverrides and now can be used for Virtual Desktop as well for configs like client:cmd-line-option:startup-procedure.

Interface (API, SDK)

Back-End

com.goldencode.p2j.security.SsoAuthenticator is the interface defining the contract between the FWD framework and the customer's authentication logic in the back-end. The customer provides their own implementation with their jar in the classpath and configure the fully qualified class name in the directory configs. The FWD framework instantiates the authenticator using reflection and a default (no-args public constructor) and immediately after that feeds the configured ssopluginoption value to the instance, so that any external configuration can be easily passed in.

Auto-login can be configured by overriding the two default methods in the interface: getAuthCookieName (a non-null value expected) and Result authenticate(Cookie[] cookies, LicensingData licensingData).

On login page request (GET /gui, GET /chui, GET /embedded) the framework first tries to do auto-login and checks if the incoming http request contains the expected cookie name. If the auto-login cookie is present, the request details are passed in to the corresponding authenticate method.
If the auto-login succeeds, the response is a redirect to the newly spawned client url.
If the auto-login fails, the framework asks the custom authenticator for the login page with getLoginPage (more details in Front-End section). If the method returns a non-empty string, it's served as the login page html, otherwise a custom / default resource file is loaded and served as the html.

On login attempt (POST /gui, POST /chui, POST /embedded) the framework calls the corresponding authenticate method and passes in a map of all form / query parameters, all cookies and any other browser client information it was able to gather.

If the authenticator responds with success, it also returns the corresponding fwd user and auth blob. The FWD user should be present in directory accounts/users and should have the osuser attribute with a valid os username. The os user should exist in the list accounts/osusers. If the FWD user doesn't have a valid osuser attribute, the default OS user from webClient/defaultOsUser is used.

The new client is spawned and the url is returned to the login page for redirect.

Front-End

General info on web login page functionality and customization can be found on the Customizing the Web Client Sign In Page wiki page.

SSO offers one more way to customize the login page and that is through the custom implementation of SsoAuthenticator.getLoginPage. The method accepts a String as an argument, that is the found and loaded login page resource, and returns a String, that is the final content of the login page. When SSO is enabled, SsoAuthenticator.getLoginPage is called by the FWD framework on a GET request for the login page. The FWD framework looks for the login page resource web_partial_login.html in the custom root webres/ dir and, if not found, in FWD's main package dir com/goldencode/p2j/main. The resource is loaded as String and passed in to SsoAuthenticator.getLoginPage, where it can be further enhanced, but it's up to the customer to decide if a completely different content is to be returned. If the returned value is not null, it is served as the login page.

4GL

Several 4GL attributes help maintain the integration between the customer's app and FWD.
  • SESSION:SESSION-ID - uuid assigned to each new session;
  • SESSION:AUTH-BLOB - custom text returned from the authenticator with the auth result, directly passed in to 4GL.

Privacy

The SDK provides the end-user's IP address to the SsoAuthenticator and eventually more specific information (like browser fingerprint) may be added. If the application code decides to store this data and use it for identification of users, you may have to add some privacy policy agreement somewhere to comply to privacy laws such as the GDPR. This is out of scope in FWD itself since FWD does not store such information by default.

Configurations

Example

          <node class="container" name="001500">
            <node class="strings" name="subjects">
              <node-attribute name="values" value="admins_pw"/>
            </node>
            <node class="adminRights" name="rights">
              <node-attribute name="permissions" value="'00000011'B"/>
              <node-attribute name="type" value="1"/>
            </node>
            <node class="resource" name="resource-instance">
              <node-attribute name="reference" value="/accounts/osusers"/>
              <node-attribute name="reftype" value="TRUE"/>
            </node>
          </node>
      <node class="container" name="config">
        <node class="authMode" name="auth-mode">
          <node-attribute name="ssoplugin" value="com.goldencode.p2j.security.SampleSsoAuthenticator"/>
          <node-attribute name="ssopluginoption" value="bogus"/>
        </node>
      </node>
      <node class="container" name="accounts">
        <node class="container" name="osusers">
          <node class="osuser" name="[OS-USER]"/>
        </node>
        <node class="container" name="users">
          <node class="user" name="bogus">
            <node-attribute name="osuser" value="[OS-USER]"/>
          </node>
        </node>
      </node>
        <node class="container" name="webClient">
          <node class="boolean" name="virtualDesktop">
            <node-attribute name="value" value="TRUE"/>
          </node>
          <node class="boolean" name="embedded">
            <node-attribute name="value" value="FALSE"/>
          </node>
          <node class="string" name="cfgOverrides">
            <node-attribute name="value" value="client:cmd-line-option:startup-procedure=dir/legacyproc.p"/>
          </node>
          <node class="string" name="defaultOsUser">
            <node-attribute name="value" value="[OS-USER]"/>
          </node>
          <node class="boolean" name="override">
            <node-attribute name="value" value="TRUE"/>
          </node>
          <node class="string" name="loginPageTitle">
            <node-attribute name="value" value="FWD Login Page"/>
          </node>
          <node class="string" name="logoutPageTitle">
            <node-attribute name="value" value="FWD Logout Page"/>
          </node>
        </node>
  • config/auth-mode/ssoplugin - Specifies the fully qualified name for the custom SsoAuthenticator implementation;
  • config/auth-mode/ssopluginoption - A free text that is fed to the custom SsoAuthenticator implementation on instantiation. Can be used to pass in any type of configs;
  • accounts/osusers - Container for defining OS users, optionally with passwords. Has to be managed through the web interface, in the Admin UI. All OS users mapped to FWD accounts and the default webClient/defaultOsUser should be listed here;
  • webClient/virtualDesktop - Config to enable Virtual Desktop;
  • webClient/embedded - Config to enable Embedded;
  • webClient/cfgOverrides - Options to be passed to the web client process;
  • webClient/defaultOsUser - The default OS user to be used for spawning a new client, when no OS user is found associated with the FWD account;
  • webClient/override - When TRUE, webClient/defaultOsUser will always be used as the OS user for spawning a new client;
  • webClient/loginPageTitle - The HTML title for the login page (/gui, /chui, embedded);
  • webClient/logoutPageTitle - The HTML title for the logout page (/gui/logout, /chui/logout).

FWD Administration Console

FWD Administration Console (usually found at localhost:7443/admin) allows configuration of operating system accounts and their passwords, that will be used for spawning new client processes. The dialog for editing FWD user accounts has a new select field, where an OS user can be selected.

webClient/defaultOsUser needs to be defined in accounts/osusers (can be done in the Administration Console), but it doesn't show up as an associated OS user for FWD accounts and vise-versa.

Enforcing Licensing Policies

On end-user sign-in attempt, the SsoAuthenticator implementation receives certain details about the request in an argument of type SsoAuthenticator.LicensingData:
  • request external IP (the last machine's IP);
  • request internal IP (the first machine's IP with proxy, otherwise the same as external IP);
  • browser fingerprint (hash code to identify uniquely the browser on the end-user machine) - to be implemented in #4853;

On sign-in attempt, SsoAuthenticator receives also all query (path) and form params of the request, as well as all cookies.

On launching the client, in 4GL a custom session attribute is available SESSION:SESSION-ID: unique id for the current session.

A Session Initialization and Termination Hook is available to be implemented in Java to allow visibility on when FWD sessions are started or ended. A DB table in the customer schema can keep track of the live sessions. The interface com.goldencode.p2j.main.InitTermListener can be implemented by the same class extending SsoAuthenticator. InitTermListener.initialize is called on the context-aware thread and can access SessionUtils.getSessionId().

On server restart, all FWD sessions are ended. This can be tracked in the SsoAuthentication default constructor. The configured implementation is instantiated on FWD server start and kept in SecurityCache. Since a custom code can instantiate the class additionally, it's recommended to use static AtomicBoolean flag to confirm it's the first instantiation. On server start, the DB table keeping track of live FWD sessions should be updated to remove all of them (if only one server instance persists in the table).


© 2023 Golden Code Development Corporation. ALL RIGHTS RESERVED.