GateIn and SAML2 integration for SSO authentication

Status

 

Finished and documented. See https://docs.jboss.org/author/display/GTNPORTAL35/SAML2 for latest informations.

 

 

Owner

 

Marek Posolda

 

 

Introduction

 

SAML (Security Assertion Markup Language) is Oasis standard for exchanging authentication and authorization data between security domains. SAML 2.0 is an XML-based protocol that uses security tokens containing assertions to pass information about a principal (usually an end user) between an identity provider and a web service. SAML 2.0 enables web-based authentication and authorization scenarios including single sign-on (SSO). (Definition took from [1])

 

SAML2 itself is set of specifications, which provides exact format of XML messages and context how these messages are exchanged between Identity Provider  (IDP, Web application, which acts as SSO provider and users are authenticated against it) and Service Provider (SP, Web application, which is used by client who wants to authenticate). More info about specifications in document [2].

 

GateIn already supports integration with couple of well-known SSO providers (CAS, JOSSO, OpenSSO, OpenAM, SPNEGO with JBoss Negotiation). SAML2 based authentication is another ideal feature to be provided in GateIn SSO component as another provider of seamless SSO authentication.

 

 

Solution

 

There is already JBoss project Picketlink Federation (PL Fed) [3], which provides solution for most important parts of SAML2 specification. Especially it supports SSO authentication with SAML2 HTTP Redirect Binding and SAML2 HTTP Post Binding and it supports SAML2 Global Logout feature.

 

Authentication workflow

 

SSO authentication is based on circle of trust between SP (in our case GateIn portal) and IDP.

circleOfTrust.png

 

Authentication works as follows (TODO: Provide graph. Maybe reuse the one from SAML specification??) :

 

1) User sends request to secured resource http://localhost:8080/portal/dologin

 

2) There is special Tomcat valve, which needs to be configured for portal context. This Valve will create SAML Request, which is basically XML message. Example below:

 

<samlp:AuthnRequest AssertionConsumerServiceURL="http://localhost:8080/portal/dologin" ID="ID_101dcb5e-f432-4f45-87cb-47daff92edef" IssueInstant="2012-01-12T17:53:27.294+01:00" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
   <saml:Issuer>http://localhost:8080/portal/dologin</saml:Issuer>
   <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
</samlp:AuthnRequest>

 

Valve will encapsulate SAML request into HttpResponse and it redirects it to IDP. Picketlink Federation supports SAML Redirect Binding, which basically means that SAML XML Request message is Base64 encoded and URL encoded and it is appended as URL parameter to GET request, which will be send to IDP. PL Fed also supports SAML POST Binding where is message encoded into Base64 and send in the body of POST request. SAML POST Binding is recommended in Picketlink Federation because with Redirect binding, which uses GET requests, URL with encoded message can be very long, which can be potentially problem for some web browsers.

 

3) IDP parses XML with SAML request and it sends login screen back to client. Now client (user) needs to authenticate himself. SAML specification does not mandate how exactly should be authentication of client on IDP side performed. Picketlink Federation based IDP can use standard FORM or BASIC authentication where user needs to provide only his username and password.

 

 

4) User fills his credentials into IDP FORM and submits request for JAAS authentication. GateIn SSO component will provide login module SAML2IdpLoginModule, which will authenticate user by sending callback request via REST API back to GateIn portal. There must be sso-auth-callback.jar library deployed in GateIn because this library provides REST endpoint, which will process callback request from IDP and authenticate user against GateIn Authenticator. This is similar approach like authentication with other SSO providers like CAS, which are also leveraging this REST service.

 

NOTE: Portal administrators are free to use their own login module stack instead of our REST callback based login module. However they need to make sure that authenticated users also need to exist in GateIn database. Otherwise their users may have authorization errors with 403 response code when they will try to access GateIn.

 

5) So after successful authentication will IDP create SAML assertion ticket and it creates SAML Response message with this ticket. Message can looks like this:

 

<samlp:Response ID="ID_5291c49e-5450-4b3b-9f99-f76606db9929" Version="2.0" IssueInstant="2012-01-12T17:53:59.237+01:00" Destination="http://localhost:8080/portal/dologin" InResponseTo="ID_101dcb5e-f432-4f45-87cb-47daff92edef">
   <saml:Issuer>http://localhost:8080/idp/</saml:Issuer>
   <samlp:Status>
      <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
   </samlp:Status>

   <saml:Assertion ID="ID_ebe89398-1e27-4257-9413-c3c17c40c9df" Version="2.0" IssueInstant="2012-01-12T17:53:59.236+01:00">
      <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">root</saml:Issuer>
      <saml:Subject>
         <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">root</saml:NameID>
         <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <saml:SubjectConfirmationData InResponseTo="ID_101dcb5e-f432-4f45-87cb-47daff92edef" NotBefore="2012-01-12T17:53:59.236+01:00" NotOnOrAfter="2012-01-12T17:54:06.236+01:00" Recipient="http://localhost:8080/portal/dologin"/>
         </saml:SubjectConfirmation>
      </saml:Subject>
      <saml:Conditions NotBefore="2012-01-12T17:53:57.236+01:00" NotOnOrAfter="2012-01-12T17:54:06.236+01:00"/>
      <saml:AuthnStatement AuthnInstant="2012-01-12T17:53:59.237+01:00">
         <saml:AuthnContext>
            <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
         </saml:AuthnContext>
      </saml:AuthnStatement>
      <saml:AttributeStatement>
         <saml:Attribute Name="Role">
            <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
         </saml:Attribute>
         <saml:Attribute Name="Role">
            <saml:AttributeValue xsi:type="xs:string">administrators</saml:AttributeValue>
         </saml:Attribute>
      </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

 

Message is then encapsulated into HttpResponse and redirected back to SP (GateIn).

 

6) On GateIn side is SAML response message decoded again by the Tomcat Valve and if assertion from response is valid, then username and his roles are added into ThreadLocal context variable. Valve then triggers JAAS authentication. GateIn SSO component will provide login module SAML2IntegrationLoginModule, which will parse authenticated username and it will perform GateIn specific operations, like creating Identity object and registering it into IdentityRegistry. Now user is successfully authenticated.

 

If client wants to authenticate against different SP application within same session, then he does not need to provide credentials again on IDP side because he has been already authenticated against IDP. So he has automatic authentication thanks to SSO.

 

 

SAML2 Global Logout

 

(TODO: Also provide graph. Maybe reuse the one from SAML specification??)

 

This is feature of SAML2 Specification, that if user triggers logout on GateIn side, then he is automatically logged-out also from IDP and all other SP applications. With GateIn it works this way:

 

1) User click logout and sends logout HTTP request like http://localhost:8080/portal:componentId=UIPortal&portal:action=Logout

 

2) Portal administrator can configure servlet filter if he wants to support SAML2 Global logout.

  • If servlet filter is not configured, then logout request is processed by GateIn portal and user is normally logged out.
  • If servlet filter is configured, then it will send redirection to another request "http://localhost:8080/portal/dologin?GLO=true". This request will be processed by the Tomcat valve (thanks to GLO=true parameter) and it will trigger SAML2 Global logout.

 

3) GateIn portal will send SAML2 Global logout request to IDP to trigger logout at IDP side. IDP will receive this request and it will send requests for all SP applications, which were logged in session for this client. It will cause logout of all SP applications.

 

4) We need special handler (component used internally by Tomcat Valve) to handle logout on GateIn side, because default behaviour is simply to call session.invalidate(), which is insufficient for GateIn. We need to override this behaviour and call WCI logout, which will trigger crossContext logout from all HTTP sessions on GateIn host.

 

 

Configuration

 

There are some necessary configuration changes, which needs to be done on GateIn side and on Identity provider to support Picketlink Federation with SAML2. Namely on GateIn side it is:

  • Adding Tomcat valve into gatein.ear/02portal.war/WEB-INF/context.xml.
  • Adding configuration for Picketlink federation with chain of handlers. SAML2Handler is special classes, which handle processing and creating of SAMLRequest and SAMLResponse messages.
  • Adding servlet filter for support of SAML2 Global logout. It's not needed if you don't want to support that.
  • Configure login module chain in gatein.ear/META-INF/gatein-jboss-beans.xml

 

Some informations about configuration can be found in Picketlink Federation user guide (See [3]), but we would need to provide some additional changes needed for portal as mentioned above.

 

 

Safe communication

 

Basic scenario with message exchanges is useful for testing purposes. However in production environment, it can be better to use additional mechanisms to exchange safe and trusted communication between IDP and SP. So we would need to use XML Signature and XML Encryption support. These features are already provided in Picketlink Federation, so maybe nothing specific will be needed for implementing in GateIn SSO component. (TODO: provide more concrete info later)

 

 

Specification

 

As mentioned above, it will be based on GateIn SSO and Picketlink Federation. Needed things to do are:

 

 

1) Picketlink Federation - Couple of bugfixes and feature requests to be implemented in Picketlink Federation library. Some are really needed to work properly with GateIn. Some are not necessary but it will be good to have them as it can introduce risks in production environment. List is here:

https://issues.jboss.org/browse/PLFED-254 - NonSerializable exception when using clustered service provider  (needed for GateIn because we have <distributable /> by default in 02portal.war/WEB-INF/web.xml)

https://issues.jboss.org/browse/PLFED-255 - Global logout: SPRedirectFormAuthenticator.authenticate should return false after redirecting to IP.  (needed by GateIn to have support for global logout)

https://issues.jboss.org/browse/PLFED-257 - Possible memory leak: tokens in DefaultTokenRegistry are not correctly cleared  (not necessary for GateIn integration, but memory leak can be annoying in production environment)

https://issues.jboss.org/browse/PLFED-258 - Handler for verification of "InResponseTo" (Feature request to have safer communication among GateIn and Identity provider)

https://issues.jboss.org/browse/PLFED-259 - Possibility to configure logout URL (Needed by GateIn as logoutURL was hardcoded in PL Fed and we need it configurable)

 

All these issues are already fixed but only in PL Fed trunk. We may need new release of Picketlink Federation to upgrade dependencies of our SSO component. Note: Maybe more JIRA issues will be found later.

 

2) GateIn SSO component - Some needed changes will need to be done in GateIn SSO component, which has been already mentioned in Specification section. Some of them are:

- Login module SAML2IntegrationLoginModule to provide needed integration with GateIn authentication

- SAML2GlobalLogoutFilter to trigger SAML2 Global logout

- SAML2IdpLoginModule - Login module and some related classes, which will be running on IDP side for callback against GateIn REST service

- Maybe other components (TODO: provide later as needed)

- Packaging to simplify cnfiguration and number of needed manual steps for GateIn portal administrators

 

3) Documentation with all needed changes in configuration files to have SAML2 Integration working

 

 

References

 

[1] http://en.wikipedia.org/wiki/SAML_2.0 - Nice Wikipedia article about SAML 2

[2] http://docs.oasis-open.org/security/saml/v2.0/ - SAML 2 specifications and documents

[3] http://www.jboss.org/picketlink/Fed - Picketlink Federation project homepage

[4] http://community.jboss.org/docs/DOC-14912 - Picketlink SAML on JBoss AS 5.1 (Useful "Hello word" type example)