Security Global Forum

Security Global Forum

Our mission is to provide clients with an online user community of industry peers and IBM experts, to exchange tips and tricks, best practices, and product knowledge. We hope the information you find here helps you maximize the value of your IBM Security solutions.

 View Only

Facebook Authentication to WebSEAL

By Shane Weeden posted Mon August 23, 2010 12:00 AM

  

I recently decided to look into how to add a “Login from Facebook” button to a website, in particular a website protected by Tivoli Access Manager WebSEAL (though this really isn’t all that important). Given that Facebook’s graph API is based on the draft OAuth 2.0 specification this seemed an interesting technology investigation. The surprise that awaited me was (for a change) a very pleasant one – this integration is very simple, and took just a few hours to implement from start to finish. I also wanted to perform the integration using Java/JSP rather than using python or php which have helper SDK’s from Facebook.

My primary piece of required reading was the Facebook Authentication documentation, although this blog post by Facebook developer Luke Shepard was also very useful. My particular area of interest was in authenticating users to a web application and extracting the user’s email address from their profile information at Facebook. The email address will be the username to login to WebSEAL. The email address must match a user identity in WebSEAL, or alternatively a Facebook ID can be used just like an Information Card or OpenID to link to an existing account and/or bootstrap a self-registration process as described in these developerworks articles:

Of course yet another choice exists, and that is to use the email address in a request to the TFIM STS to build a TAM credential without the user being in the TAM registry as described in my developerworks article on Using WebSEAL without a User Registry.

For ease of understanding in this article I’ll just assume that the email address does match an existing Tivoli Access Manager username in WebSEAL, and we’ll use the email address as a value in a response HTTP header as part of an EAI application junctioned behind WebSEAL. The important part to understand is how to securely obtain the user’s email address from Facebook using OAuth and the graph API – what you do with it after that is up to you.

Registering an OAuth Client Application

The first step to the integration was to register my OAuth client with Facebook and obtain an application key and secret. Interestingly your application URL doesn’t even need to be internet-facing as Facebook only ever redirects to it via the browser. As long as your browser can resolve the application URL, that is good enough. As a result you may use a completely internal target application environment provided it can connect out to the internet to contact Facebook. I used a locally hosted WebSEAL and WebSphere to test the integration while writing this article.

To register my OAuth client application, I visited the Facebook Developers Setup link, and registered an application as shown:

Site Name My Test Site
Site URL https://www.myrp.ibm.com/
Locale English (US)

What comes back is the information about your OAuth client registration, plus example code for people interested in the Javascript integration. The important pieces of information for this integration is the App ID and App Secret.

Understanding the OAuth Message Flow

The OAuth message flow used for this Facebook integration can be broken down into four steps:

  • Redirect to Facebook to obtain authorization from the user to access their basic account information and email address
  • Allow the user to grant authorization and return with an authorization code
  • Use the authorization code to request an authorized access token directly from Facebook
  • Use the authorized access token to get the user’s profile information directly from Facebook

Putting the Message Flow Into a JSP

I wrote a few small Java helper classes to handle retrieving data from a URL using standard J2SE HttpsURLConnection and some helper code for parsing query string parameters from a response. I also leveraged some free open source for parsing JSON objects from java from http://www.json.org/java/.

My WebSEAL server was addressed via https://www.myrp.ibm.com, with a junction /jct to a WebSphere server where the sample application fb.ear was installed.

Putting these pieces together resulted in this single fblogin.jsp which manages the entire authentication process:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"
  import="com.tivoli.am.fim.demo.AccessTokenRetriever"
  import="com.tivoli.am.fim.demo.ResourceRetriever"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Pragma" content="no-cache">
<title>Facebook Login</title>
<%
  String appid = "122317787817298";
  String appsecret = "64935e1806e935301d4a5237b2764fe3";
  String redirectURL = "https://www.myrp.ibm.com/jct/fb/fblogin.jsp";
  String email = null;

  String code = request.getParameter("code");
  if (code == null) {
    // initiate authorization flow
    String authorizeURLStr = "https://graph.facebook.com/oauth/authorize?client_id="
      + appid + "&redirect_uri=" + redirectURL + "&scope=email";
    response.sendRedirect(authorizeURLStr);
  } else {
    // we have an authorization code - first swap it for an access token
    // then use the access token to get the user's profile information
    String accessTokenURLStr = "https://graph.facebook.com/oauth/access_token?client_id="
      + appid + "&redirect_uri=" + redirectURL + "&client_secret=" + appsecret
      + "&code=" + code;


    AccessTokenRetriever atr = new AccessTokenRetriever(accessTokenURLStr);
    String accessToken = atr.getAccessToken();

    String resourceURLStr = "https://graph.facebook.com/me?access_token=" + accessToken;
    ResourceRetriever rr = new ResourceRetriever(resourceURLStr);
    email = rr.getEmail();

    // use the email address as a response header and redirect to the epac CGI
    response.setHeader("am-eai-user-id", email);
    response.setHeader("am-eai-redir-url", "https://www.myrp.ibm.com/cgi-bin/epac");
  }
%>
</head>
<body>
If you see this, you haven't set the trigger URL properly in WebSEAL's config file.
<br />
User email address is: <%=email%>
</body>
</html>

Installation and Configuration of the Solution

This section covers installation and configuration of the example code provided with this article.

Install the EAR to WebSphere and Update fblogin.jsp

This is quite straight forward – just download and install the example fb.ear to your WebSphere server. When you download the example code your browser may wish to save the fb.ear file as a .zip. If that happens, just rename it to fb.ear after download. You will need to edit the fblogin.jsp file that is part of the application to insert your own application id and secret, and to modify the hostname of the WebSEAL server that is used in both the redirectURL and also in the am-eai-redir-url response header for EAI. Check that the EAI headers in your WebSEAL configuration file match those in the sample application.

Configure WebSphere for SSL Trust

The helper classes that connect to Facebook via HttpsURLConnection will leverage WebSphere’s J2SE SSL implementation including server certificate verification. Configuration is needed in WebSphere to install the SSL signer certificate of https://graph.facebook.com otherwise a “No Trusted Certificte Found” error will result. There are many ways to do this and the technique I show here is not the best but probably the quickest for setting up a test environment (for a more robust solution investigate WebSphere Dynamic outbound endpoint SSL configurations). In the WebSphere administration console, navigate to:

Security->SSL certificate and key management->Key stores and certificates->NodeDefaultTrustStore->Signer certificates

You will see a list of default signer certificates including default, dummyclientsigner and dummyserversigner. Click on the button: Retrieve from port

Enter settings as shown, then click: Retrieve signer information

You will then see the facebook certificate information. Press OK to save the alias in the NodeDefaultTrustStore. After the Save, your updated signer certificate list should include the facebook alias as shown:

Configure WebSEAL Junction, TAM policy and Trigger URL for EAI

The WebSEAL server requires a junction to the WebSphere. In this example I created /jct as shown:

pdadmin sec_master> server task default-webseald-sles10.ibm.com create -t tcp -h localhost -p 9080 -c all /jct

Unauthenticated access is required to access the application as it will be used to initiate authentication:

pdadmin sec_master> acl create unauth
pdadmin sec_master> acl modify unauth set group iv-admin TcmdbsvaBRrxl
pdadmin sec_master> acl modify unauth set group webseal-servers Tgmdbsrxl
pdadmin sec_master> acl modify unauth set user sec_master TcmdbsvaBRrxl
pdadmin sec_master> acl modify unauth set any-other Trx
pdadmin sec_master> acl modify unauth set unauthenticated Trx

pdadmin sec_master> acl attach /WebSEAL/<server_root>/jct/fb unauth

Updates are needed to the WebSEAL configuration file (typically webseald-default.conf) to enable EAI authentication:

[eai]
# HTTPS recommended for EAI 
eai-auth = https

# Header variables 
eai-pac-header = am-eai-pac
eai-pac-svc-header = am-eai-pac-svc
eai-user-id-header = am-eai-user-id
eai-auth-level-header = am-eai-auth-level
eai-xattrs-header = am-eai-xattrs
eai-redir-url-header = am-eai-redir-url

# Indicates that any login with a PAC completely replaces existing login credential
retain-eai-session = no


[eai-trigger-urls]
# The trigger URL for the EAI application. 
trigger = /jct/fb/fblogin.jsp*

[authentication-mechanisms]
# Change according to your particular platform - this example is for Linux.
ext-auth-interface = /opt/pdwebrte/lib/libeaiauthn.so

Testing the Solution

To initiate the test, simply access the fblogin.jsp in a browser via WebSEAL. In my case this was using the URL:

https://www.myrp.ibm.com/jct/fb/fblogin.jsp

The first time I access the page, authorization is required at Facebook. After authentication (if needed), you should be prompted with a Facebook authorization page similar to this:

After allowing authorization, authentication should complete automatically. Provided you have an account in WebSEAL matching your email address and the epac demo application is properly configured, the very next page you see should be the epac program as an authenticated user:

Subsequent tests should not require explicit authorization as Facebook will remember your first decision. If you wish to “unremember” this decision, login to Facebook and proceed to the Account->Privacy Settings page, then under Application and WebSites click on Edit your settings, as shown:

From this page you can click on Remove unwanted or spammy applications and delete your remembered authorizations.

Conclusion

The Facebook graph API utilizes the OAuth 2.0 (draft) specification to provide a simple interface to allow a user to delegate authorized access to parts of their user profile. The interface is very straight forward for consumers to use as evidenced by the short time in which I was able to develop a solution. A lot more information can be accessed than just the user’s basic profile and email address that I have shown here. There are also optomizations that could be implemented around caching authorization tokens for performance reasons. Error flows should also be considered in more detail should you wish to use this solution yourself. Many further integration scenarios are possible including using Facebook information for account linking and self-registration at a website just like OpenID and Information Cards. I believe this is just the tip of the iceberg and am looking forward to working more on a variety of OAuth integration scenarios.

0 comments
6 views

Permalink