Chapter 3. Single Sign On Sample

Table of Contents

Using Ambience APIs for Single Sign On

Using Ambience APIs for Single Sign On

The following example demonstrates the use of Ambience APIs to perform Single Sign On (SSO) to Ambience from a third party application.

The diagram in Figure 3.1, “Single Sign On Workflow” depicts the workflow:

Figure 3.1. Single Sign On Workflow

Single Sign On Workflow
  • A. Browser connects to user server.
  • B.User server POSTS to /elx/sso/[domain]/[user] with the authenticators - username and password.
  • C. Ambience checks that authenticator has SSOAuthentication permissions and that [user] is not admin. If these conditions are true, Ambience then returns an [sso-token].
  • D. User server sends a REDIRECT message back to the browser, sending it to /elx/sso/[sso-token]. This can also include a ?ret=XXX target URL.
  • E. Browser GETs /elx/sso/[sso-token]?ret=XXX.
  • F. Ambience checks valid [sso-token] and adds a session cookie to the reply. It then sends a reply (with the cookie) as part of a REDIRECT to XXX (the return value), or to the default landing page if the return value is not defined.
  • G. Browser visits the regular Ambience page (XXX) and is already authenticated by the cookie.

The following Java code sample demonstrates this functionality.

To run the sample, you need to compile it as a Java servlet and put it in a Java web server.

You can also re-implement the same logic in any other modern language, such as C#, Ruby or Python.

As a security consideration, do not use admin as the SSO Authenticator. It is only done for simplicity in this demo.


package com.elixirtech.sample.sso;

import java.io.DataInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

@SuppressWarnings("serial")
public class SSODemo extends HttpServlet {

  final static String url = "http://localhost:8080/elx/sso";

  @Override
  public void doGet(HttpServletRequest request, 
     HttpServletResponse response) 
     throws ServletException, java.io.IOException {

    String domain = "eno";
    
    // Ambience user with SSOAuthentication permission
    String ssoAuthName = "admin";
    String ssoAuthPassword = "sa";
    
    // user we want to sign-on
    String username = "test";

    DefaultHttpClient client = new DefaultHttpClient();
    
    HttpPost sso = new HttpPost(url + "/" + domain + "/" + 
      username); 
      
    List<NameValuePair> nameValuePairs = 
      new ArrayList<NameValuePair>(2);
	
    nameValuePairs.add(new BasicNameValuePair("username", 
        ssoAuthName));
	
    nameValuePairs.add(new BasicNameValuePair("password", 
      ssoAuthPassword));
      
    sso.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    
    sso.setHeader("ContentType", 
      "application/x-www-form-urlencoded");
      
    HttpResponse reply = client.execute(sso);
    
    StatusLine status = reply.getStatusLine();
    int code = status.getStatusCode();
    
    if (code < 400) {
      int length = (int)reply.getEntity().getContentLength();
      
      byte[] bytes = new byte[length];
      
      DataInputStream is = 
       new DataInputStream(reply.getEntity().getContent());
      
      is.readFully(bytes);
      is.close();
      
      String token = new String(bytes,"UTF-8");
      
      System.out.println("token = " + token);
      
      response.sendRedirect(url + "/" + token + 
         ret(request));
	 
      return;
    } 
    
    else {
      response.sendError(code,status.getReasonPhrase());
    }
  }
  
  private String ret(HttpServletRequest request) {
    String ret = request.getParameter("ret");
    
    if (ret==null || ret.trim().length()==0) return "";
    
    else {
    
      // prevent header splitting
      
      System.out.println("set ret to " + ret);
      
      return "?ret=" + ret.trim().replace("\r", "").
         replace("\n", "");
    }
  }
}