Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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) {
   // ExampleMap only.userInfo = Portlet 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.  The library must provide it to the IdP.
Resource resource = new Resource ();  // Simple example class representing a protected resource
resource.setResourceUrl(url);   // The url variable here is a String initialized elsewhere
getResource(samlSession, resource);  // Portlet's local method detailed below

...

return samlAssertion;
}

protected String getIdPPublicKeys(PortletRequest request) {
    Map userInfo = (Map) request.getAttribute(PortletRequest.USER_INFO);
    String idpPublicKeys = (String) userInfo.get("idpPublicKeys");
    return idpPublicKeys;
}

//Gets or creates the Shibbolized HttpClient, 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 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:

...