Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Overview

This document is targeted towards developers writing a custom portlet that will support Shibboleth Delegated Authentication. For an "out of the box" solution look at using the Web Proxy Portlet with Delegated SAML Authentication

The delegated-saml-authentication project is a library that handles most of the complexities around delegated Shibboleth authentication for the portlet developer. The library provides a specially configured HttpClient from Commomns Http-Components 4.x that can be used to make requests to a remote service that will automatically use delegated authentication.

...

If the portlet is not using Maven the JAR can be downloaded from the Maven repository manually: [ http://repo1.maven.org/maven2/org/jasig/service/delegated-saml-authentication/1.1.0/

Usage

Introduction

The reason this library exists is to facilitate delegated SAML authentication for portlets that act on behalf of the logged on user. It is not the library's responsibility, nor was it its requirement, to retrieve any resources from the SAML-protected WSP. The library uses Apache HttpClient component. The only difference from using HttpClient directly is that instead of creating an instance of HttpClient, a developer obtains it from the library. The initial testing of this library was performed with only HTTP GET as the initial request to retrieve a protected resource. This is because that was the only method that would handle SAML authentication "as-needed." Support to preserve HTTP POST form post elements was recently added to the Shibboleth SP, but this will need to be tested in the future.

...

The delegated SAML authentication business logic is encapsulated in a class called SAMLDelegatedAuthenticationService. There is no need to make an explicit instance of this class, as it is created internally to the library. Here is an illustration of the steps required to retrieve a protected resource using HTTP GET:

Code Block
java
java

protected String samlAssertion = getAssertion(PortletRequest request); {
 // Example only. Map PortletuserInfo obtains= a String containing SAML assertion
samlSession = new SAMLSession(samlAssertion);
samlSession.setPortalEntityID(portalEntityID(Map) request.getAttribute(PortletRequest.USER_INFO);
    String samlAssertion = (String) userInfo.get("samlAssertion");
  // Set the portal's entityID.return samlAssertion;
}

Theprotected libraryString must provide it to the IdP.
Resource resource = new Resource ();  // Simple example class representing a protected resource
resource.setResourceUrl(urlgetIdPPublicKeys(PortletRequest request) {
    Map userInfo = (Map) request.getAttribute(PortletRequest.USER_INFO);
    String idpPublicKeys = (String) userInfo.get("idpPublicKeys");
  //  Thereturn urlidpPublicKeys;
variable}
here
is//Gets aor Stringcreates initializedthe elsewhereShibbolized getResource(samlSession, resource);  // Portlet's local method detailed belowHttpClient, caching the created version in the user's session
protected HttpClient getHttpClient(PortletRequest request) {
    PortletSession portletSession = request.getPortletSession();
    HttpClient client = (HttpClient)portletSession.getAttribute(HTTP_CLIENT_ATTR);
    if (client != null) {
        return client;
    }

    String samlAssertion = getAssertion(request);

    //Configure the connection manager that should be used by the delegated auth integration code
    HttpParams params = new BasicHttpParams();
    ClientConnectionManager clientConnectionManager = this.createClientConnectionManager(request, params);

    //Create the SAMLSession, providing it the assertion and the HttpClient configuration
    SAMLSession samlSession = new SAMLSession(samlAssertion, clientConnectionManager, params);
    samlSession.setPortalEntityID(portalEntityID);   // Set the portal's entityID.  The library must provide it to the IdP.

    //If the SP private key and cert are configured provide them to the SAMLSession
    if (spPrivateKey != null && spCertificate != null) {
        samlSession.setIdPClientPrivateKeyAndCert(spPrivateKey, spCertificate);
    }

    //If the IdP's public keys were provided pass them on to the SAMLSession
    String idpPublicKeys = getIdPPublicKeys(request);
    if (idpPublicKeys != null) {
        samlSession.setIdPServerPublicKeys(idpPublicKeys);
    }

    client = samlSession.getHttpClient();
    portletSession.setAttribute(HTTP_CLIENT_ATTR, client);
    return client;
}

The following is an example of a getResource method that a portlet may use:using the Shibbolized HttpClient

Code Block
java
java
private void getResource(SAMLSession samlSession, Resource resource) {(PortletRequest request) {
    String url = determineUrl(request); //portlet specific logic to figure out where to make the request to+

    HttpClient client = samlSession.getHttpClient(request);  // This is how to
obtain an instance of "authenticated" HttpClient
  HttpGet method = new HttpGet(resource.getResourceUrl());
  
    // There is no need to check the HTTP response status because the HTTP
    // client will handle normal HTTP protocol flow, including redirects
    // In case of error, HTTP client will throw an exception
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    String response;
    try {
       response = client.execute(method, responseHandler);
        resource.setResource(response);//Do Something Portlet Specific with the response
    }
    catch (Exception ex) {  // ClientProtocolException or IOException
        log.error("Exception while trying to retrieve the resource.", ex);
    }
    finally {
        //Cleanup after the HttpClient request
        response.getEntity().consumeContent();
    }
}

In this simplest of examples, assuming that SAML protects a RESTful Web Service, at the end of this sequence the portlet may call resource. getResource(), which will return a String representation of what came back from the WSP. Since the data encapsulating classes are stateful, SAMLSession and Resource should not be considered thread-safe.

...

The SAML assertion issued to the portal, the same assertion that the portlet uses as a constructor parameter when creating an instance of the SAMLSession class, contains an Issuer element. This identifies the IdP that issued the assertion. The IdP is identified by what's referred to as entityID. This may sometimes look like a URL, but it does not have to be. A fully-qualified URL is required by the library to obtain a delegated SAML assertion from the IdP and present to the WSP. In order to make this flexible, the library uses a "pluggable" resolver. The resolver wirks works with SAMLSession and an instance of the DelegatedSAMLAuthenticationState class, which is populated with the IdP's entityID. The IdP resolver will resolve the specific URL, or "endpoint." On successful resolution, the resolver places the IdP endpoint into the DelegatedSAMLAuthenticationState class. The resolver needs to implement a simple interface IdPEPRResolver:

...