0 Replies Latest reply on Nov 20, 2014 5:03 PM by vjgorla

    Need to implement an IDP that supports authentication/authorization using another IDP

    vjgorla

      Hi Guys

      We have a requirement to implement an IDP that supports authentication/authorization using another external IDP in addition to the standard the username/password form authentication.

      Does picketlink support this scenario out of the box?.

       

      Here are the required components:

      1. Multiple SPs that depend on our IDP (Lets call it IDP-Internal) for authentication.

      2. IDP-Internal should support username/password form authentication using LdapLoginModule and a DatabaseLogingModule for different user groups. It should also support authentication using another IDP (Lets call it IDP-External)

      3. IDP-External is from an external provider with some SAML extensions.

       

      We have currently implemented the SP and IDP-Internal using picketlink (following picketlink samples). However, the IDP-Internal to IDP-External integration is currently implemented using some hacky borrowed code that handcrafts/parses SAML request/response (no picketlink here).

      I have managed to integrated this hacky code into IDP-Internal by extending picketlink's IDPWebBrowserSSOValve. This custom valve parses the incoming SAMLResponse from IDP-External and does the local container authentication using a SAML2LoginModule similar to how it is done on the SP side.

       

      Here is the custom valve:

       

      public class IDPInternalAuthentiationValve extends IDPWebBrowserSSOValve {

          @Override

          public void invoke(Request request, Response response) throws IOException, ServletException {

              String samlResponseXML = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY);

              if (isNotNull(samlResponseXML)) {

                  // This is a SAML Response from IDP-External

                  // Parse SAML and get subjectName and roles

                  // Lookup subject in an internal database and get local roles

                  ServiceProviderSAMLContext.push(subjectName, combinedRoles);

                  // Authenticate locally using SAML2LoginModule

                  Principal principal = container.getRealm().authenticate(subjectName, ServiceProviderSAMLContext.EMPTY_PASSWORD);

                  ServiceProviderSAMLContext.clear();


                  Session session = request.getSessionInternal(false);

                  // Save the authenticated Principal in our session

                  session.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);

       

                  String samlRequestFromSession = (String)session.getNote(GeneralConstants.SAML_REQUEST_KEY);

                  // This is the request from SP

                  if (isNotNull(samlRequestFromSession)) {

                      // Send a response back to SP using the principal created above

                      processSAMLRequestMessage(request, response);

                  }

              } else {

                  // Username/password form authentication flow

                  super.invoke(request, response);

              }

          }

      }

       

      This solutions, although works, feels a bit hacky. Is there a better way of doing this using just picketlink?