The Fedlet and U (Part 3): We Built This Application

NOTE : I've been getting errors with the following procedures. I am posting them anyway in hopes that someone can see what I have missed. I'm not an engineer and therefore am thinking my code deletion and additions are incorrect. If you are able to successfully deploy and test the following Fedlet procedures, let me know what you did so I can try it out. Thanks.

Thus far, in previous entries, I explained how to implement the Fedlet using the Common Tasks work flow in the OpenSSO console and using the pre-built but unconfigured fedlet.war. (There's also a bonus entry on how to remove a deployed fedlet.)

In this entry, you'll find the procedures to integrate the fedlet.war code with an existing service provider application. The following diagram illustrates the three ways in which this can be done.

  1. fedletSampleApp.jsp is modified to add the service provider's application logic and, thus, is used as the endpoint for the Fedlet on the service provider side here.
  2. fedletSampleApp.jsp is modified to forward the request to the service provider application URL and, thus, is also used as the endpoint for the Fedlet on the service provider side here.
  3. fedletSampleApp.jsp is replaced by a new JSP (servlet) to create a new endpoint or the Fedlet code in the fedletSampleApp.jsp is copied to the new endpoint code here.

NOTE: The diagram refers to fedletSampleApp.jsp, a sample JSP packaged with the fedlet.war thatprovides a default Assertion Consumer endpoint to process SAMLv2 Assertions from the identity provider. fedletSampleApp.jsp first invokes a util method to complete SAMLv2 protocol processing. A map containing various pieces of data (including a Response, an Assertion, and Attributes) is then returned to the caller for further processing. fedletSampleApp.jsp also provides some sample code to help you to understand how to retrieve data from the returned map.


<%--
   The contents of this file are subject to the terms
   of the Common Development and Distribution License
   (the License). You may not use this file except in
   compliance with the License.

   You can obtain a copy of the License at
   https://opensso.dev.java.net/public/CDDLv1.0.html or
   opensso/legal/CDDLv1.0.txt
   See the License for the specific language governing
   permission and limitations under the License.

   When distributing Covered Code, include this CDDL
   Header Notice in each file and include the License file
   at opensso/legal/CDDLv1.0.txt.
   If applicable, add the following below the CDDL Header,
   with the fields enclosed by brackets [] replaced by
   your own identifying information:
   "Portions Copyrighted [year] [name of copyright owner]"

   $Id: fedletSampleApp.jsp,v 1.2 2008/05/29 00:40:42 veiming Exp $

   Copyright 2008 Sun Microsystems Inc. All Rights Reserved
--%>

<%@page
import="com.sun.identity.saml2.common.SAML2Exception,
com.sun.identity.saml2.common.SAML2Constants,
com.sun.identity.saml2.assertion.Assertion,
com.sun.identity.saml2.assertion.Subject,
com.sun.identity.saml2.profile.SPACSUtils,
com.sun.identity.saml2.protocol.Response,
com.sun.identity.saml2.assertion.NameID,
com.sun.identity.plugin.session.SessionException,
java.io.IOException,
java.util.Iterator,
java.util.List,
java.util.Map"
%>
<%
    String deployuri = request.getRequestURI();
    int slashLoc = deployuri.indexOf("/", 1);
    if (slashLoc != -1) {
        deployuri = deployuri.substring(0, slashLoc);
    }
%>
<html>
<head>
    <title>Fedlet Sample Application</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <link rel="stylesheet" type="text/css" href="<%= deployuri %>/com_sun_web_ui/css/css_ns6up.css" />
</head>

<body>
<div class="MstDiv"><table width="100%" border="0" cellpadding="0" cellspacing="0" class="MstTblTop" title="">
<tbody><tr>
<td nowrap="nowrap"> </td>
<td nowrap="nowrap"> </td>
</tr></tbody></table>

<table width="100%" border="0" cellpadding="0" cellspacing="0" class="MstTblBot" title="">
<tbody><tr>
<td class="MstTdTtl" width="99%">
<div class="MstDivTtl"><img name="ProdName" src="<%= deployuri %>/console/images/PrimaryProductName.png" alt="" /></div></td><td class="MstTdLogo" width="1%"><img name="RMRealm.mhCommon.BrandLogo" src="<%= deployuri %>/com_sun_web_ui/images/other/javalogo.gif" alt="Java(TM) Logo" border="0" height="55" width="31" /></td></tr></tbody></table>
<table class="MstTblEnd" border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img name="RMRealm.mhCommon.EndorserLogo" src="<%= deployuri %>/com_sun_web_ui/images/masthead/masthead-sunname.gif" alt="Sun(TM) Microsystems,
Inc." align="right" border="0" height="10" width="108" /></td></tr></tbody></table></div><div class="SkpMedGry1"><a name="SkipAnchor2089" id="SkipAnchor2089"></a></div>
<div class="SkpMedGry1"><a href="#SkipAnchor4928"><img src="<%= deployuri %>/com_sun_web_ui/images/other/dot.gif" alt="Jump Over Tab Navigation Area. Current Selection is: Access Control" border="0" height="1" width="1" /></a></div>
<%
    // BEGIN : following code is a must for Fedlet (SP) side application
    Map map;
    try {
        // invoke the Fedlet processing logic. this will do all the
        // necessary processing conforming to SAMLv2 specifications,
        // such as XML signature validation, Audience and Recipient
        // validation etc.  
        map = SPACSUtils.processResponseForFedlet(request, response);
    } catch (SAML2Exception sme) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, sme.getMessage());
        return;
    } catch (IOException ioe) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, ioe.getMessage());
        return;
    } catch (SessionException se) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, se.getMessage());
        return;
    } catch (ServletException se) {
        response.sendError(response.SC_BAD_REQUEST, se.getMessage());
        return;
    }
    // END : code is a must for Fedlet (SP) side application
    
    String relayUrl = (String) map.get(SAML2Constants.RELAY_STATE);
    if ((relayUrl != null) && (relayUrl.length() != 0)) {
        // something special for validation to send redirect
        int stringPos  = relayUrl.indexOf("sendRedirectForValidationNow=true");
        if (stringPos != -1) {
            response.sendRedirect(relayUrl);
        }
    } 

    // Following are sample code to show how to retrieve information,
    // such as Reponse/Assertion/Attributes, from the returned map. 
    // You might not need them in your real application code. 
    Response samlResp = (Response) map.get(SAML2Constants.RESPONSE); 
    Assertion assertion = (Assertion) map.get(SAML2Constants.ASSERTION);
    Subject subject = (Subject) map.get(SAML2Constants.SUBJECT);
    String entityID = (String) map.get(SAML2Constants.IDPENTITYID);
    NameID nameId = assertion.getSubject().getNameID();
    String value = nameId.getValue();
    String format = nameId.getFormat();
    out.println("<br><br><b>Single Sign-On successful with IDP " 
        + entityID + ".</b>");
    out.println("<br><br>");
    out.println("<table border=0>");
    if (format != null) {
        out.println("<tr>");
        out.println("<td valign=top><b>Name ID format: </b></td>");
        out.println("<td>" + format + "</td>");
        out.println("</tr>");
    }
    if (value != null) {
        out.println("<tr>");
        out.println("<td valign=top><b>Name ID value: </b></td>");
        out.println("<td>" + value + "</td>");
        out.println("</tr>");
    }    
    Map attrs = (Map) map.get(SAML2Constants.ATTRIBUTE_MAP);
    if (attrs != null) {
        out.println("<tr>");
        out.println("<td valign=top><b>Attributes: </b></td>");
        Iterator iter = attrs.keySet().iterator();
        out.println("<td>");
        while (iter.hasNext()) {
            String attrName = (String) iter.next();
            List attrVals = (List) attrs.get(attrName);
            out.println(attrName + "="
                + attrVals.get(0) + "<br>");
        }
        out.println("</td>");
        out.println("</tr>");
    }
    out.println("</table>");
    out.println("<br><br><b><a href=# onclick=toggleDisp('resinfo')>Click to view SAML2 Response XML</a></b><br>");
    out.println("<span style='display:none;' id=resinfo><textarea rows=40 cols=100>" + samlResp.toXMLString(true, true) + "</textarea></span>");

    out.println("<br><b><a href=# onclick=toggleDisp('assr')>Click to view Assertion XML
<script>
function toggleDisp(id)
{
    var elem = document.getElementById(id);
    if (elem.style.display == 'none')
        elem.style.display = '';
    else
        elem.style.display = 'none';
}
</script>
</body>
</html>


The following procedures assume that you have downloaded the opensso.zip and extracted the contents. The /opensso directory is at the top-level of the machine to which it was downloaded.

Modify fedletSampleApp.jsp with Application Logic
  1. Unzip fedlet.war into a temporal directory; for example, /sp1.
    This directory must be accessible by the user running the web container; for example, if running your web container as root, the user's home directory is / so the sp1 directory should be located at /sp1.

    NOTE: This directory is the default location from which the Fedlet reads its metadata, circle of trust, and configuration properties. To change it, set the value of the JVM run-time property com.sun.identity.fedlet.home to the desired location; for example:

    -Dcom.sun.identity.fedlet.home=/export/fedlet/conf

    % mkdir /sp1
    % cd /sp1
    % jar xvf /opensso/fedlet/fedlet.war
    
  2. In fedletSampleApp.jsp (located at the top-level of the temporal directory) remove all text after the line, // END : code is a must for Fedlet (SP) side application.
  3. Merge the import statements between fedletSampleApp.jsp and the application code, if applicable.
    I'm using a simple hello.jsp (as below) so nothing to merge.


    
    <%--
       The contents of this file are subject to the terms
       of the Common Development and Distribution License
       (the License). You may not use this file except in
       compliance with the License.
    
       You can obtain a copy of the License at
       https://opensso.dev.java.net/public/CDDLv1.0.html or
       opensso/legal/CDDLv1.0.txt
       See the License for the specific language governing
       permission and limitations under the License.
    
       When distributing Covered Code, include this CDDL
       Header Notice in each file and include the License file
       at opensso/legal/CDDLv1.0.txt.
       If applicable, add the following below the CDDL Header,
       with the fields enclosed by brackets [] replaced by
       your own identifying information:
       "Portions Copyrighted [year] [name of copyright owner]"
    
       $Id: fedletDefault.jsp,v 1.2 2008/03/31 19:54:11 qcheng Exp $
    
       Copyright 2008 Sun Microsystems Inc. All Rights Reserved
    --%>
    <html>
    <head>
        <title>My Hello</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    </head>
    
    <body>
        <h1>
            Hello World
        </h1>
    </body>
    </html>
    

  4. Add your application logic underneath the line that begins with //END - prepending a %> before it and appending the closing HTML tags after it.

    
    &>
    <h1>
    Hello, World
    </h1>
    </body>
    </html>
    
  5. From inside the sp1 directory, pack up the contents using the jar command.
    jar cvf ./fedlet.war
  6. Deploy the WAR.
  7. Launch the deployed application.

Modify fedletSampleApp.jsp to Forward Request

  1. Unzip fedlet.war into a temporal directory; for example, sp2.
    % mkdir sp2
    % cd sp2
    % jar xvf /opensso/fedlet/fedlet.war
    
  2. In fedletSampleApp.jsp (located at the top-level of the temporal directory) remove all text after the line, // END : code is a must for Fedlet (SP) side application.
  3. Add redirect code underneath the line that begins with //END - prepending a %> before it and appending the closing HTML tags after it.
    
    &>
    response.sendRedirect("hello.jsp"); 
    </body>
    </html>
    
  4. Add the modified fedletSampleApp.jsp and the hello.jsp to the document root of the unpacked WAR directory structure.
  5. Pack up the WAR using the jar command.
    jar cvf ./fedlet.war
  6. Deploy the WAR.
  7. Launch the deployed application.

Replace fedletSampleApp.jsp

  1. Modify web.xml to set the servlet and servlet-mapping for your new servlet or JSP.
    You must map your new servlet/JSP to the url-pattern /fedletapplication since that is the URI set in the Fedlet metadata for the assertion consumer URL. For example:
    
                   yourapplication
                   /Your-Application.jsp
               
               
                   yourapplication
                   /fedletapplication
               
  2. Copy the following code from fedletSampleApp.jsp to your application processing code.
    Be sure to also copy any appropriate import statements.
    Map map;
    try {
        // invoke the Fedlet processing logic. this will do all the
    
    Map map;
    try {
        // invoke the Fedlet processing logic. this will do all the
        // necessary processing conforming to SAMLv2 specifications,
        // such as XML signature validation, Audience and Recipient
        // validation etc.
        map = SPACSUtils.processResponseForFedlet(request, response);
    } catch (SAML2Exception sme) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, sme.getMessage());
        return;
    } catch (IOException ioe) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, ioe.getMessage());
        return;
    } catch (SessionException se) {
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, se.getMessage());
        return;
    } catch (ServletException se) {
        response.sendError(response.SC_BAD_REQUEST, se.getMessage());
        return;
    }
    After obtaining the returned map object, follow the sample code to retrieve the data needed for your business logics.

Considering how we built these applications, now rock out to the much-maligned but still pleasurable We Built This City, Starship's number 1 hit from the 1980s.

Comments:

I was wondering what errors you were getting. I'm running the fedSampleApp.jsp which does some similar stuff. I'm blowing up at map = SPACSUtils.processResponseForFedlet(request, response);

I was wondering if you are blowing up at the some place.

Posted by Mike Sacauskis on March 30, 2009 at 09:32 AM PDT #

Mike, I can't remember what my errors were. I suggest you send your error info to users@opensso.dev.java.net. There's a lot of people on that alias who will be able to help.

Posted by DocTeger on March 30, 2009 at 09:41 AM PDT #

Hi,

I didn't try your tutorial for now but please forgive me if I'm wrong :

I was looking at the Fedlet generating menu and maybe when we create it we should declare <SP Host URL>/<our application> in the SP end-point field instead of <SP Host URL>/"fedlet".

i think these declarations are written in the metadatas in the IDP side, and it could not match the right SP for the federation after we modify the fedlet's configuration files.

Posted by lourderadj on October 07, 2009 at 10:45 PM PDT #

Hi. Maybe that's why I could never get this to work. Or maybe the metadata has changed since I wrote this entry. Why don't you check it out and let us know if it worked for you? ;>

Posted by Michael Teger on October 08, 2009 at 01:29 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

docteger

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today