HowTo: Implement SSO for applications that do not use GAM

Official Content

Implementing SSO when using GeneXus Access Manager is very simple, but what if any of the applications in the system isn't integrated into GAM? Is it possible to use GAM as an Identity Provider even if at least one of the client applications doesn't use GAM?

Consider a scenario where an enterprise system already has identity information about the users of all the applications involved in the system. Rather than having each client application maintain their own user database with the user credentials, it would be easier to implement an SSO mechanism. The idea is to give the user access to all the web apps by logging in only once.

Applications using GeneXus Access Manager can easily implement SSO without any development costs. In such case, the client applications and the Identity Provider must have Enable Integrated Security property set to TRUE. 

But if you need to implement SSO in a system where none of the applications was generated with GeneXus X Evolution 3 or, in fact, it has Enable Integrated Security property = FALSE, you can also implement SSO. This is what this document is about.

In this case, it is a manual task on the client side of the system. In other words, as the clients aren't integrated into GAM, the developer has to program the necessary calls to the GAM Identity Provider emulating the real calls done when GAM is enabled on the client.

The calls follow the OAuth 2.0 protocol for solving the SSO problem.

Before you go on reading, make sure you understand the Behind the scenes of GAM SSO implementation.

Steps to Follow

Below is an example of an application generated using GeneXus X Evolution 2. Download the sample below.

1. The client application in this scenario isn't integrated into GAM. Anyway, we have to consider a fictitious client application and generate GUIDs for the application credentials - Client Id and Client Secret information. There are online GUID generators you can use.

Afterwards, define the application in the Identity provider using the previous credentials. You can run the GAM Web Backoffice and create a GAM Application:

i2015_04_30_00_58_331_png

In this case, it's important to detail the Local Login URL, and whether you want to get User Roles and Additional Data.

2. Define a transaction in the client KB which is used to store the parameters needed to establish the connection to the Identity Provider. In the example, the transaction is the following:

i2015_04_30_11_43_141_png

The table associated with the transaction stores the following parameters:

  • Identity Provider Host, PORT, Secure (HTTP or HTTPS)
  • Identity Provider Base URL 
  • Callback URL (Redirect URL). The Redirect URL must always be ../oauth/gam/callback. Afterwards, we define a redirection to a service associated with that end point. 
    The Callback URL parameter configuration is needed for Web Applications only. 
  • Client Id and Client Secret of the client application (the same specified in step 1)

3. The login web panel in the client calls a procedure - called "login" in the example xpz -  which does the following:

  • Generate a random state string; for this example the state is stored in the &state variable using the fixed value "GRESTD" plus a GUID value to make sure it is unique.
  • Redirect to ../oauth/gam/signin on the server, passing the client_id information, the redirect_uri, the scope and the state.

The code looks as follows:

&GXGUID = GUID.NewGuid()
&state = "GRESTD" + &GXGUID.ToString()
&WebSession.Set(!"State", &state)
&url = GetBaseUrl(&IdentityProvider) + !"/oauth/gam/signin"
&params= !"oauth=auth&client_id=" + &ClienteId.Trim() + 
       !"&redirect_uri=" + &IdentityProvider.IdentityProviderRedirUrl + 
       !"&scope=gam_user_data+gam_user_roles+gam_user_additional_data+&state=" + &state.Trim()
Link(&url, &params)

The execution of the URL (&url) checks in the Identity Provider GAM if there is a valid session. If not, the Local Login URL specified in step 1 (GAMRemoteLogin object) in the server is executed, so that the user can enter his credentials. Afterwards, the URL specified in the redirect_uri parameter is executed by a GET HTTP.

Remember that the redirect_uri is ../oauth/gam/callback.

4. The redirect to the redirect_uri specified in the previous step forces the execution of a procedure - called "loginresponse" in the example xpz - that executes what we detail below: 

  • Check the validity of the HTTP response
  • Web Applications: Generate a POST execution to oauth/gam/access_token on the server, to get the Access Token for the session.
  • Other Applications: Generate a POST execution to oauth/access_token on the server, to get the Access Token for the session.
  • Generate a POST execution to oauth/gam/userinfo on the server, to get user information.

Notes for implementing the solution

  • You may implement a way to save the session locally to the application, so it's valid for a period of time.
  • Take into account that a complete logout occurs when the logout is done on the server. Check this article for more detail.

Notes for the environment configuration

C#

If the client application is generated with C#, you need to add the following lines to the web.config file under the rules section:

<!--GXIGNORE_START-->
<rule name="GXGamCallback" stopProcessing="true">
  <match url="^oauth/gam/callback$" />
  <action type="Rewrite" url="aloginresponse.aspx" />
</rule>
<!--GXIGNORE_END-->

where "loginresponse" references the GeneXus procedure in charge of the processing.

Java

  • If the client application is generated with Java, you need to add the following lines to the web.xml file in the WEB-INF directory of the client web app:
     
<servlet>
                            <servlet-name>GAMOAuthCallback</servlet-name>
                            <servlet-class>aloginresponse</servlet-class>                                                                         
</servlet>
 <servlet-mapping>
                            <servlet-name>GAMOAuthCallback</servlet-name>
                            <url-pattern>/oauth/gam/callback</url-pattern>
</servlet-mapping>           
  • If the server application is generated with Java, it may be necessary to add a Filter in the Identity Provider web app, as shown below:
<filter>
    <filter-name>FiltroJSON</filter-name>
    <filter-class>sso.FiltroJson</filter-class>
</filter>
<filter-mapping>
    <filter-name>FiltroJSON</filter-name>
    <url-pattern>/oauth/gam/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

The filter should be added to the web.xml file in the WEB-INF directory of the Identity Provider web app.
Note that we used a package (optional) called sso. So, in this case the class is copied with its package under the WEB-INF\classes directory of the Identity Provider web app.

The following is the source of the class. You should compile the class and copy it to the server.

package sso;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class FiltroJson implements Filter {

    private FilterConfig config;

    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

    public void destroy() {
        config = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {

        response.setContentType("text/json");
        chain.doFilter(request, response);
    }
}

Download the sample

ssosampleClientWithoutGAM

See Also

Single Sign On in applications using GAM
GAM Remote Authentication Type
HowTo: Signout from a SSO applications not using GAM

Was this page helpful?
What Is This?
Your feedback about this content is important. Let us know what you think.