Chapter 2. How To Setup SSO with SAML v2
This section details the actual steps for setting up SSO via SAML v2 using JBoss EAP 6.
2.1. Components
As covered in the Section 1.1.1.1, “Entities” section as well as in the Security Architecture for Red Hat JBoss Enterprise Application Platform 6 document, there are three entites or parties involved in Browser-Based SSO using SAML v2:
- A principal using a user agent (browser) to request access to a secured resource.
- A service provider (SP) housing the secured resource.
- An identity provider (IDP) which issues security assertions to principals, allowing them to access secured resources on service providers (SPs).
In addition, the following will be needed to support browser-based SSO via SAML v2:
- Separate web applications serving as SPs and IDPs
- JBoss EAP 6 instances to host the SPs and IDPs
- Security Domains to support the SPs and IDPs
2.2. IDP and SP Setup and Configuration
This section covers setting up an application to be either an SP or IDP as well as setting up an JBoss EAP 6 instance to host those applications.
2.2.1. Setting up an IDP
To set up an application to serve as an IDP, the following steps must be performed:
The security domain should be created and configured before creating and deploying the application.
2.2.1.1. 1. Create a Security Domain for an IDP
The IDP handles challenging a principal for their credentials, handling the authentication and authorization of that principal, and issuing the proper security (SAML v2) assertions based on the result. This requires that an identity store be configured via a security domain. The only requirement around creating this security domain and identity store is that it has authentication and authorization mechanisms properly defined. Meaning, essentially many differently identity stores (e.g. properties file, database, ldap, etc) and their associated login modules could be used to support an IDP application. For more information on security domains, please see the Security Domains section of the Red Hat JBoss Enterprise Application Platform 6 Security Architecture document.
In the below example, a simple UsersRoles login module using properties files for an identity store is used.
/subsystem=security/security-domain=idp:add(cache-type=default)
/subsystem=security/security-domain=idp/authentication=classic:add
/subsystem=security/security-domain=idp/authentication=classic/login-module=UsersRoles:add( \ code=UsersRoles, \ flag=required, \ module-options=[ \ ("usersProperties"=>"idp-users.properties"), \ ("rolesProperties"=>"idp-roles.properties") \ ])
reload
<security-domain name="idp" cache-type="default"> <authentication> <login-module code="UsersRoles" flag="required"> <module-option name="usersProperties" value="${jboss.server.config.dir}/idp-users.properties"/> <module-option name="rolesProperties" value="${jboss.server.config.dir}/idp-roles.properties"/> </login-module> </authentication> </security-domain>
The above CLI commands were done assuming a standalone instance of JBoss EAP 6. For more details on using the CLI with JBoss EAP 6 domains, please consult The Management CLI section of the Red Hat JBoss Enterprise Application Platform 6 Administration and Configuration Guide.
idp-users.properties
Eric=samplePass Alan=samplePass
idp-roles.properties
Eric=All Alan=
2.2.1.2. 2. Configure the web.xml File for an IDP
The web.xml
file for an IDP should contain the following:
- A
<security-constraint>
with a<web-resource-collection>
containing a<url-pattern>
that maps to the URL pattern of the secured area. Optionally,<security-constraint>
may also contain an<auth-constraint>
stipulating the allowed roles. - A
<login-config>
configured for FORM authentication. - If any roles were specified in the
<auth-constraint>
, those roles should be defined in a<security-role>
. - Optionally, resources used by the login form (e.g. images, styles, etc) can be specified by an additional security constraint to be unsecured so they may be accessed prior to authentication (i.e. on the login page).
The <security-constraint>
and <security-role>
elements enable administrators to setup restricted or unrestricted areas based on URL patterns and roles. This allows resources to be secured or unsecured.
The <login-config>
defines the the login and error pages used by the IDP when authenticating users.
web.xml
file:<web-app> <display-name>IDP</display-name> <description>IDP</description> <!-- Define a security constraint that gives unlimited access to images --> <security-constraint> <web-resource-collection> <web-resource-name>Images</web-resource-name> <url-pattern>/images/*</url-pattern> </web-resource-collection> </security-constraint> <!-- Define a security constraint that requires the All role to access resources --> <security-constraint> <web-resource-collection> <web-resource-name>IDP</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>All</role-name> </auth-constraint> </security-constraint> <!-- Define the Login Configuration for this Application --> <login-config> <auth-method>FORM</auth-method> <realm-name>IDP Application</realm-name> <form-login-config> <form-login-page>/jsp/login.jsp</form-login-page> <form-error-page>/jsp/error.jsp</form-error-page> </form-login-config> </login-config> <!-- Security roles referenced by this web application --> <security-role> <description>The role that is required to log in to the IDP Application</description> <role-name>All</role-name> </security-role> </web-app>
It is recommended that a welcome page defined in the application. By default, JBoss EAP 6 will look for a file called index.jsp
but this can configured using the <welcome-file-list>
in the web.xml
.
login.jsp
file:<html> <head></head> <body> <form id="login_form" name="login_form" method="post" action="j_security_check" enctype="application/x-www-form-urlencoded"> <center> <p>Welcome to the <b>IDP</b></p> <p>Please login to proceed.</p> </center> <div style="margin-left: 15px;"> <p> <label for="username">Username</label> <br /> <input id="username" type="text" name="j_username"/> </p> <p> <label for="password">Password</label> <br /> <input id="password" type="password" name="j_password" value=""/> </p> <center> <input id="submit" type="submit" name="submit" value="Login"/> </center> </div> </form> </body> </html>
error.jsp
file:<html> <head></head> <body> <p>Login failed, please go back and try again.</p> </body> </html>
2.2.1.3. 3. Configure the Authenticator for an IDP
The authenticator is responsible for the authentication of users and for issuing and validating security assertions (in case, SAML v2 assertions). The authenticator is configured in the form of a <valve>
that resides in the jboss-web.xml
file along with the security domain to be used in authenticating and authorizing principals (see Step 1).
The jboss-web.xml
file should have the following: - A <security-domain>
to specify which security domain to use for authentication and authorization. - A <valve>
configured to use the SSO valve class (e.g. org.picketlink.identity.federation.bindings.tomcat.idp.IDPWebBrowserSSOValve)
jboss-web.xml
file:<jboss-web> <security-domain>idp</security-domain> <context-root>identity</context-root> <valve> <class-name> org.picketlink.identity.federation.bindings.tomcat.idp.IDPWebBrowserSSOValve </class-name> </valve> </jboss-web>
2.2.1.4. 4. Declare the Necessary Dependencies for an IDP
The web application serving as the IDP requires a dependency to be defined in jboss-deployment-structure.xml
, so that the org.picketlink
classes can be located. JBoss EAP 6 provides all necessary org.picketlink
and related classes, the application just needs to declare them as dependencies to use them.
<jboss-deployment-structure> <deployment> <dependencies> <module name="org.picketlink"/> </dependencies> </deployment> </jboss-deployment-structure>
Alternatively, this dependency may be defined in a META-INF/MANIFEST.MF
file instead:
Manifest-Version: 1.0 Build-Jdk: 1.6.0_24 Dependencies: org.picketlink
2.2.1.5. 5. Create and Configure a picketlink.xml File for an IDP
The picketlink.xml
file is responsible for the behavior of the Authenticator and is loaded at the application’s startup.
The file should contain at least the following elements:
<PicketLinkIDP>
defining the url of the IDP (<IdentityURL>
) and any hosts trusted by the identity provider.<Handlers>
defining the set of handlers needed for processing the SAML requests and responses.
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1"> <IdentityURL>${idp.url::http://localhost:8080/identity/}</IdentityURL> <Trust> <Domains>localhost,example.com</Domains> </Trust> </PicketLinkIDP> <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> </Handlers> </PicketLink>
Handlers are implemented using a Chain of Responsibility, with each individual handler performing logic on request and responses in the order defined in picketlink.xml
. It is very important to pay attention to the order in which the handlers are configured.
By default, picketlink.xml
is located in the WEB-INF directory of the IDP web application. However, a custom path to a picketlink.xml
that is external to the application can be configured. This is useful in cases where multiple applications across one or more JBoss EAP 6 instances share the same picketlink.xml
configuration.
jboss-web.xml
specifying for the path to picketlink.xml
, and timerInterval which specifies the interval in milliseconds to reload the configuration. <jboss-web> ... <valve> <class-name>...</class-name> <param> <param-name>timerInterval</param-name> <param-value>5000</param-value> </param> <param> <param-name>configFile</param-name> <param-value>path-to/picketlink.xml</param-value> </param> </valve> </jboss-web>
2.2.2. Setting up an SP
To set up an application to serve as an SP, the following steps must be performed:
The security domain should be created and configured before creating and deploying the application.
2.2.2.1. 1. Create a Security Domain for an SP
Since the IDP handles challenging the user for their credentials and issuing security (SAML v2) assertions, the SP is in charge of validating those assertions. A security domain is still needed to perform this validation, but an identity store is not. In this case, the security domain for the SP must use the SAML2LoginModule.
/subsystem=security/security-domain=sp:add(cache-type=default)
/subsystem=security/security-domain=sp/authentication=classic:add
/subsystem=security/security-domain=sp/authentication=classic/login-module=SAML2LoginModule:add( \ code=org.picketlink.identity.federation.bindings.jboss.auth.SAML2LoginModule, \ flag=required)
reload
<security-domain name="sp" cache-type="default"> <authentication> <login-module code="org.picketlink.identity.federation.bindings.jboss.auth.SAML2LoginModule" flag="required"/> </authentication> </security-domain>
The above CLI commands were done assuming a standalone instance of JBoss EAP 6. For more details on using the CLI with JBoss EAP 6 domains, please consult The Management CLI section of the Red Hat JBoss Enterprise Application Platform 6 Administration and Guide.
The SAML2LoginModule allows for authentication decisions to be deferred to an IDP, which will be configured in the SP’s picketlink.xml
.
2.2.2.2. 2. Configure the web.xml File for an SP
The web.xml
file for an SP should contain the following:
- A
<security-constraint>
with a<web-resource-collection>
containing a<url-pattern>
that maps to the URL pattern of the secured area. Optionally,<security-constraint>
may also contain an<auth-constraint>
stipulating the allowed roles. - If any roles were specified in the
<auth-constraint>
, those roles should be defined in a<security-role>
.
<web-app> <display-name>SP</display-name> <description>SP</description> <!-- Define a Security Constraint on this Application --> <security-constraint> <web-resource-collection> <web-resource-name>SP</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>All</role-name> </auth-constraint> </security-constraint> <!-- Security roles referenced by this web application --> <security-role> <description> The role that is required to log in to the SP Application </description> <role-name>All</role-name> </security-role>
It is recommended that a welcome page defined in the application. By default, JBoss EAP 6 will look for a file called index.jsp
but this can configured using the <welcome-file-list>
in the web.xml
.
The logout process will attempt to redirect principals to logout.jsp
on successful logout. Please ensure this file is defined at the directory root of the application.
2.2.2.3. 3. Configure the Authenticator for an SP
The authenticator is responsible for the authentication of principals based on the security assertions (in this case, SAML v2 assertions) issued by the IDP. They intercept each request made to the application, check if a SAML assertion is present in the request, validate the assertions, execute principal’s SAML specific validations, and create a security context for the principal in the requested application.
The authenticator is configured in the form of a <valve>
that resides in the jboss-web.xml
file along with the security domain to be used in authenticating and authorizing principals (see Step 1).
The jboss-web.xml
file for an SP should have the following:
- A
<security-domain>
to specify which security domain to use for authentication and authorization. - A
<valve>
configured to use the SSO Service Provider valve class (e.g. org.picketlink.identity.federation.bindings.tomcat.sp.ServiceProviderAuthenticator)
jboss-web.xml
File:<jboss-web> <security-domain>sp</security-domain> <context-root>sales-post</context-root> <valve> <class-name>org.picketlink.identity.federation.bindings.tomcat.sp.ServiceProviderAuthenticator</class-name> </valve> </jboss-web>
2.2.2.4. 4. Declare the Necessary Dependencies for an SP
The web application serving as the SP requires a dependency to be defined in jboss-deployment-structure.xml
, so that the org.picketlink
classes can be located. JBoss EAP 6 provides all necessary org.picketlink
and related classes, the application just needs to declare them as dependencies to use them.
<jboss-deployment-structure> <deployment> <dependencies> <module name="org.picketlink"/> </dependencies> </deployment> </jboss-deployment-structure>
Alternatively, this dependency may be defined in a META-INF/MANIFEST.MF
file instead:
Manifest-Version: 1.0 Build-Jdk: 1.6.0_24 Dependencies: org.picketlink
2.2.2.5. 5. Create and Configure a picketlink.xml File for an SP
The picketlink.xml
file is responsible for the behavior of the Authenticator and is loaded at the application’s startup.
The file should contain at least the following elements:
<PicketLinkSP>
defining the url of the IDP (<IdentityURL>
) and the url the SP (<ServiceURL>
).<Handlers>
defining the set of handlers needed for processing the SAML requests and responses.
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" BindingType="POST"> <IdentityURL>${idp.url::http://localhost:8080/identity/}</IdentityURL> <ServiceURL>${sales-post.url::http://localhost:8080/sales-post/}</ServiceURL> </PicketLinkSP> <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> </Handlers> </PicketLink>
While not recommended, the SP may also be configured to use HTTP/REDIRECT by changing BindingType="POST" to BindingType="REDIRECT".
Handlers are implemented using a Chain of Responsibility, with each individual handler performing logic on request and responses in the order defined in picketlink.xml
. It is very important to pay attention to the order in which the handlers are configured.
By default, picketlink.xml
is located in the WEB-INF directory of the IDP web application. However, a custom path to a picketlink.xml
that is external to the application can be configured. This is useful in cases where multiple applications across one or more JBoss EAP 6 instances share the same picketlink.xml
configuration.
jboss-web.xml
specifying for the path to picketlink.xml
, and timerInterval which specifies the interval in milliseconds to reload the configuration. <jboss-web> ... <valve> <class-name>...</class-name> <param> <param-name>timerInterval</param-name> <param-value>5000</param-value> </param> <param> <param-name>configFile</param-name> <param-value>path-to/picketlink.xml</param-value> </param> </valve> </jboss-web>
2.2.3. Using SP-initiated Flow
The SP-inited Flow is a common use case citied when describing browser-based SSO, and was covered in the Browser-Based SSO Using SAML and Multiple Red Hat JBoss Enterprise Application Platform Instances and Multiple Applications Using Browser-Based SSO with SAML sections of the Red Hat JBoss Enterprise Application Platform 6 Security Architecture document. In summary, a principal attempts to access a secured resource in a SP. The SP starts the flow by checking for a principal’s security assertions and redirecting any unauthenticated principal’s to the IDP. Upon successful authentication with the IDP, the principal is then redirected back to the initial SP with their security assertions for the SP to validate and permit/deny access to the original resource requested.
Walkthrough
- A principal attempts to access secured resource on a SP.
- SP performs a check on the principal. If the principal has not yet authenticated, they need to be redirected to the IDP. If they have already authenticated, then all other steps are skipped and the final step is performed.
- The SP locates the IDP and issue an authentication request to the IDP via the principal’s browser.
- The IDP attempts to authenticate the principal (e.g. challenging them with a login page) using the configured identity store.
- After the principal is identified by the IDP (e.g. successful login), the IDP issues a response (containing SAML v2 assertions with the principal’s security-related information) to the SP via the principal’s browser.
- The SP performs a check on the principal’s security assertions, and based the information contained in those assertions, the SP allows (or denies) access to the requested resource.
This flow requires no additional steps or configuration to setup. All redirects are handled by the configured SPs and IDPs and links to both secured and unsecured resources require no additional changes.
2.2.4. Using IDP-Initiated Flow
Most examples of browser-based SSO via SAML v2 using a SP-initiated flow as covered in the previous section, but SAML v2 supports an additional flow: the IDP-initiated or Unsolicited Response flow. In this scenario, the SP does not initiate the authentication flow and receive a SAML response from the IDP. Instead, the flow starts on the IDP-side and once authenticated, the principal can choose a specific SP from a list and then get redirected to its URL.
Walkthrough
- Principal accesses the IDP.
- The IDP seeing that there is neither SAML request nor response, assumes an IDP first scenario using SAML.
- The IDP challenges the principal to authenticate.
- Upon authentication, the IDP shows the hosted section where the principal gets a page that links to all the SP applications.
- The principal chooses an SP application.
- The IDP redirects the principal to the service provider with a SAML assertion in the query parameter, SAML response. In the cases where the POST binding is used, the IDP sends the SAML assertion to the service provider via an HTTP POST.
- The SP checks the SAML assertion and provides access.
HostedURI
attribute to the <PicketLinkIDP>
element: <PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" HostedURI="/hosted/"> ... </PicketLinkIDP> </Picketlink>
<a href="http://localhost:8080/identity?SAML_VERSION=2.0&TARGET=http://localhost:8080/sales-post/">Sales</a>
Note that the link above redirects the user to the IDP passing the TARGET query parameter, whose value is the URL to the target SP application. Once the user clicks the link above, the IDP extracts the TARGET parameter from the request, builds an SAML v2 response, and redirects the user to the target URL. When the user hits the SP, they are automatically authenticated. The SAML_VERSION query parameter is used to specify the SAML version that must be used by the IDP to create the SAML response.
2.2.5. Configuring the Global Logout Profile
2.2.5.1. Global Logout Profile
A Global Logout Profile initiated at one service provider logs out the user from the Identity Provider (IDP) and all the service providers.
For a Global Logout Profile to function appropriately ensure that only up to five SPs are configured per IDP.
<html> <head></head> <body> <p>You have successfully logged out.</p> </body> </html>
GLO=true
as a URL parameter in a link to an SP resource to initiate the Global Logout Profile process. <a href="?GLO=true">Click to LogOut</a>
2.2.5.2. Local Logout
In addition to global logout profile, local logout may also be used. Local logout, in contrast to global logout profile, logs a principal out of a single SP while leaving the session at the IDP and other SPs completely intact. Basically, local logout allows principals to be "locally logged out" at a single SP.
The process for using Local Logout is essentially the same as Global Logout Profile, with the URL parameter in the logout link taking the form of LLO=true
.
<a href="?LLO=true">Click to LogOut</a>
When a principal clicks on the Local Logout link at the SP, the SP will invalidate their session and forward the principal to the configured logout page.
If using Local Logout, please be aware of the security implications that result from it. Meaning, when a principal is only disconnected from one service provider, they still have an active session with the IDP and other SPs that may allow them to still access secured resources. While this behavior may be desired in circumstances, it is strongly recommended to use Global Logout in most scenarios.
2.3. Configuring IDPs and SPs via the Management Console
In addition to configuring IDPs and SP manually, SSO via SAML v2 may also be configured via a JBoss EAP 6 subsystem. This method of configuration is known as the Domain Model and allows all the configuration to reside centrally on the JBoss EAP 6 instance and not with the individual applications. This also enables the SSO configuration to be created and updated using the JBoss EAP management interfaces such as the Management Console and CLI.
2.3.1. Configuring the Subsystem
Before the subsystem can be used to setup federations, it needs to be enabled and configured in JBoss EAP 6. The following steps are needed to enable and configure the subsystem:
It is recommended that these steps be preformed while the JBoss EAP 6 instance is not running.
2.3.1.1. 1. Update the Extensions
In the JBoss EAP 6 configuration file (standalone.xml
for standalone instances or domain.xml
for domains), add the org.wildfly.extension.picketlink
extension:
<extensions> ... <extension module="org.wildfly.extension.picketlink"/> ... </extensions>
2.3.1.2. 2. Add the Subsystems
In the JBoss EAP 6 configuration file (standalone.xml
for standalone instances or domain.xml
for domains), add the jboss:domain:picketlink-federation:1.1
subsystem:
<profile> ... <subsystem xmlns="urn:jboss:domain:picketlink-federation:1.1"/> ... </profile>
Examples of configuration may also be found in the docs/examples/configs/standalone-picketlink.xml
file under the JBoss EAP 6 install directory.
2.3.2. Setting up a Federation
Once the subsystem has been setup and configured, it may be used (via the management interfaces) to configure federations. Configuring a federations requires the following steps:
2.3.2.1. 1. Preparing the SP and IDP Applications
As was covered in the previous section, when configuring SSO via SAML v2 manually, the following files were required to be created or updated:
web.xml
jboss-web.xml
picketlink.xml
jboss-deployment-structure.xml
When using the subsystem to setup federations for SSO via SAML v2, the vast majority of the configuration happens from the management interfaces without having to update any of those files. The only configuration that must be done to the application is to configure the <security-constraint>
and associated <security-role>
in the web.xml
of the IDPs and SPs. In addition, the <login-config>
in the web.xml
as well as the login and error pages will also have to be present in the IDP.
jboss-web.xml
picketlink.xml
jboss-deployment-structure.xml
Once the applications have been prepared, they may be deployed.
2.3.2.2. 2. Creating a Federation via the Management Interface
Once the JBoss EAP 6 instance has been configured and the applications have been setup and deployed, a federation may be created from the Management Console.
- Navigate to Management Console using a Web Browser for Example: http://localhost:9990/console
- Click on the Configuration tab at the top
- Click on PicketLink → Federation in the menu on the left side
- Click on the Add button to create a new federation
- Enter a name for the federation and click Save
- Click on the View for the federation to begin configuring
- Select Identity Provider under the Federation tab and click Add to configure a new IDP
- Enter in the information of the deployed IDP and click Save
- Select Service Provider under the Federation tab and click Add to configure a new SP
- Enter in the information of the deployed SP and click Save
The Details section in both the Identity Provider and Service Provider subtabs may be used to configure additional details or make updates to an existing IDP or SP:
When configuration changes are made relating to any IDPs or SPs within a federation (including any security domains used by the IDPs or SPs), it best to restart the affected IDPs and/or SPs. This can be accomplished using the Restart option on the Identity Provider and Service Provider subtab.
2.4. Configuring Identity Stores for IDPs
Since IDPs use security domains, the functionality of an IDP is independent from the actual identity store that backs it. As a result, administrators have many options when configuring security domains for IDPs. The specifics around security domains and login modules can be found in the Security Subsystem section of the Red Hat JBoss Enterprise Application Platform 6 Security Architecture. Just as with setting up any login module for a security domain, please keep in mind that different identity stores offer different functionality and performance tradeoffs.
The following steps are needed for setting up a security domain that uses an identity store:
For the purposes of this document, the Database login module and Ldap login module are shown as examples, but other identity stores and login modules may also be configured for use with IDPs.
The CLI commands for this section were done assuming a standalone instance of JBoss EAP 6. For more details on using the CLI with JBoss EAP 6 domains, please consult The Management CLI section of the Red Hat JBoss Enterprise Application Platform 6 Administration and Guide.
2.4.1. 1. Setting up the Identity Store
Before a security domain and login module can be configured to use an identity provider, the identity provider (and sometimes an connection to that identity provider) must be setup.
2.4.1.1. Configuring the Identity Store for the Database Login Module
The following operations are needed for setting up the Identity Store for the Database login module:
- Database Setup
- Adding a Datasource
The following datapoints are needed:
- Usernames
- Passwords
- Roles
- Role Groups
The Database Login module requires the ability to create a query that maps usernames to passwords and a query that maps usernames to roles and role groups. This information can be stored within the database in variety of ways, but creating a database with tables is not in the scope of this document. For the purposes of this example, it’s assumed the following tables have been created:
Table 2.1. sso-users
username | passwd |
---|---|
Sarah | Testing123! |
Table 2.2. sso-roles
username | role | role-group |
---|---|---|
Sarah | Sample | SSO-Users |
For the purposes of this example, it is assumed that a datasource named idpDS has been created, properly configured, and deployed to the JBoss EAP 6 instance. This datasource has a connection to the database storing the sso-users and sso-roles tables.
2.4.1.2. Configuring the Identity Store for the Ldap Login Module
A properly configured LDAP server is required prior to setting up the Ldap login module. Unlike the Database login module, a datasource is not needed for setting up the Ldap login module. The basics of LDAP and how it relates to JBoss EAP 6 security are covered in the Red Hat JBoss Enterprise Application Platform 6 Security Architecture document.
dn: dc=example,dc=com objectclass: top objectclass: dcObject objectclass: organization dc: example o: Example #============================= dn: ou=People,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: People #============================= dn: uid=jsmith,ou=People,dc=example,dc=com objectclass: top objectclass: uidObject objectclass: person uid: jsmith cn: John sn: Smith userPassword: theduke #============================= dn: ou=Roles,dc=example,dc=com objectclass: top objectclass: organizationalUnit ou: Roles #============================= dn: cn=Sample,ou=Roles,dc=example,dc=com objectclass: top objectclass: groupOfNames cn: Sample member: uid=jsmith,ou=People,dc=example,dc=com description: the Sample group
2.4.2. 2. Adding the Security Domain
Once the identity store itself has been setup and any needed connection between the JBoss EAP 6 instance and the identity store has been configured, the security domain may be created and configured. The below command shows how to create an empty security domain, replacing MY-DOMAIN with the desired name of the security domain.
/subsystem=security/security-domain=MY-DOMAIN:add(cache-type=default)
2.4.3. 3. Adding the Authentication Section and Login Module to the Security Domain
After the empty security domain has been created, the authentication section must be created with a login module added to it. The below command shows how to add an empty authentication section to an existing security domain, replacing MY-DOMAIN with the name of the security domain.
/subsystem=security/security-domain=MY-DOMAIN/authentication=classic:add
Once the empty authentication section has been created, a login module may then be added to it and configured to use the desired identity store. After adding a login module to a security domain, a configuration reload is usually required.
Below is the general command structure for adding a login module and reloading the configuration, replacing MY-DOMAIN, MY-LOGIN-MODULE, and MY-CONFIGURATION with the appropriate information:
/subsystem=security/security-domain=MY-DOMAIN/authentication=classic/login-module=MY-LOGIN-MODULE:add( MY-CONFIGURATION )
reload
2.4.3.1. Adding a Database Login Module
/subsystem=security/security-domain=idp-db-domain/authentication=classic/login-module=Database:add( \ code=Database, \ flag=required, \ module-options=[ \ ("dsJndiName"=>"java:/idpDS"), \ ("principalsQuery"=>"select passwd from 'sso-users' where username=?"), \ ("rolesQuery"=>"select role, role-group from 'sso-roles' where username=?") \ ])
reload
<security-domain name="idp-db-domain" cache-type="default"> <authentication> <login-module code="Database" flag="required"> <module-option name="dsJndiName" value="java:/idpDS"/> <module-option name="principalsQuery" value="select passwd from 'sso-users' where username=?"/> <module-option name="rolesQuery" value="select role, role-group from 'sso-roles' where username=?"/> </login-module> </authentication> </security-domain>
2.4.3.2. Adding an LDAP Login Module
The steps necessary for configuring both the LdapExtended login module (recommended) as well as the Ldap login module can be found in How To Configure Identity Management in Red Hat JBoss Enterprise Application Platform 6.
2.5. Configuring SSL/TLS with SPs and IDPs
The basics of SSL/TLS are covered in the Red Hat JBoss Enterprise Application Platform 6 Security Architecture. Adding SSL/TLS support to a browser-based SSO environment is not much different than adding it to non-SSO environment. Both the IDPs and SPs can have an HTTPS connector added to allow for traffic to be secured.
/subsystem=web/connector=HTTPS/:add(socket-binding=https,scheme=https,protocol=HTTP/1.1,secure=true)
/subsystem=web/connector=HTTPS/ssl=configuration:add(name=https,certificate-key-file="${jboss.server.config.dir}/keystore.jks",password=SECRET, key-alias=KEY_ALIAS)
/subsystem=web/connector=HTTPS/ssl=configuration/:write-attribute(name=protocol,value=TLSv1)
The above CLI commands were done assuming a standalone instance of JBoss EAP 6. For more details on using the CLI with JBoss EAP 6 domains, please consult The Management CLI section of the Red Hat JBoss Enterprise Application Platform 6 Administration and Guide.
The configuration example below validates any provided certificate. If no certificate is provided or if the authentication fails, the procedure falls back to a user/password based authentication.
For example:
<security-domain name="idp" cache-type="default"> <authentication> <login-module code="CertificateRoles" flag="optional"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="securityDomain" value="idp"/> <module-option name="verifier" value="org.jboss.security.auth.certs.AnyCertVerifier"/> </login-module> <login-module code="UsersRoles" flag="required"> <module-option name="password-stacking" value="useFirstPass"/> <module-option name="usersProperties" value="users.properties"/> <module-option name="rolesProperties" value="roles.properties"/> </login-module> </authentication> <jsse keystore-password="change_it" keystore-url="${jboss.server.config.dir}/server.keystore" truststore-password="change_it" truststore-url="${jboss.server.config.dir}/server.keystore" client-auth="true"/> </security-domain>
2.6. Additional Features
2.6.1. SAML Assertion Encryption
In addition to offering SSL/TLS encryption between IDPs and SPs, the SAML assertions themselves may also be encrypted. This is useful in securing SAML v2 assertions that are transmitted in an unsecured manner (e.g. not using SSL/TLS).
2.6.1.1. Enabling Encryption Directly in IDPs and SPs
To enable encryption of security assertions directly in IDPs and SPs, the following procedures must be performed to both the IDP and SP picketlink.xml
files:
- Enable Encrypt and SupportsSignatures
- Add Handlers
- Configure the KeyProvider
<PicketLinkIDP>
and <PicketLinkSP>
must be updated. For the IDP, add or update the Encrypt
and SupportsSignatures
attributes in <PicketLinkIDP>
to be true:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" Encrypt="true" SupportsSignatures="true"> ... </PicketLinkIDP> </PicketLink>
For the SP, add or update the SupportsSignatures
attribute in <PicketLinkSP>
to be true:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... </PicketLinkSP> </PicketLink>
<Handlers>
. For the IDP add SAML2EncryptionHandler
and SAML2SignatureValidationHandler
to the picketlink.xml
file:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2EncryptionHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" /> </Handlers> </PicketLink>
For the SP add SAML2SignatureGenerationHandler
and SAML2SignatureValidationHandler
to the picketlink.xml
file:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" /> </Handlers> </PicketLink>
Handlers are implemented using a Chain of Responsibility, with each individual handler performing logic on request and responses in the order defined in picketlink.xml
. It is very important to pay attention to the order in which the handlers are configured.
The SAML2SignatureGenerationHandler should not be configured in the same chain as the SAML2EncryptoinHandler. This will cause SAML messages will be signed several times.
<KeyProvider>
element must be added to BOTH picketlink.xml
files. This element provides the location and credentials for accessing the java keystore used for encrypting and decrypting security assertions. An example of generating a java keystore can be found here. For the IDP the element should be added to <PicketLinkIDP>
:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" Encrypt="true" SupportsSignatures="true"> ... <KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager"> <Auth Key="KeyStoreURL" Value="/my_keystore.jks" /> <Auth Key="KeyStorePass" Value="store123" /> <Auth Key="SigningKeyPass" Value="test123" /> <Auth Key="SigningKeyAlias" Value="servercert" /> <ValidatingAlias Key="idp.example.com" Value="servercert" /> <ValidatingAlias Key="localhost" Value="servercert" /> <ValidatingAlias Key="sp1.example.com" Value="servercert" /> <ValidatingAlias Key="sp2.example.com" Value="servercert" /> </KeyProvider> ... </PicketLinkIDP> ... <PicketLink>
For the SP the element should be added to <PicketLinkSP>
:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... <KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager"> <Auth Key="KeyStoreURL" Value="/my_keystore.jks" /> <Auth Key="KeyStorePass" Value="store123" /> <Auth Key="SigningKeyPass" Value="test123" /> <Auth Key="SigningKeyAlias" Value="servercert" /> <ValidatingAlias Key="idp.example.com" Value="servercert" /> <ValidatingAlias Key="localhost" Value="servercert" /> </KeyProvider> ... </PicketLinkSP> </PicketLink>
In order to properly encrypt and decrypt assertions, the IDP needs to generate signatures and the SP needs to verify those signatures as well as identify where they came from. This is accomplished via the <ValidatingAlias>
element. IDPs need to have a <ValidatingAlias>
for each trusted server/domain that is trusted (i.e. every entry in the <Trust>
element). SPs need to have a <ValidatingAlias>
for each server/domain containing an IDP.
2.6.2. Digital Signatures in Assertions
Digital Signatures allow IDPs to sign their security (SAML v2) assertions and have those signature (and assertions) validated by the SPs. This is useful for validating the authenticity of assertions, especially for assertions that are transmitted in an unsecured manner (e.g. not using SSL/TLS).
2.6.2.1. Enabling Digital Signatures Directly in IDPs and SPs
To enable digital signatures in security assertions directly in IDPs and SPs, the following procedures must be performed to both the IDP and SP picketlink.xml
files:
- Enable SupportsSignatures
- Add Handlers
- Configure the KeyProvider
<PicketLinkIDP>
and <PicketLinkSP>
must be updated. For the IDP and SP, add or update the SupportsSignatures
attribute in <PicketLinkSP>
to be true:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... </PicketLinkIDP> </PicketLink>
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... </PicketLinkSP> </PicketLink>
<Handlers>
. For the IDP and SP, add SAML2SignatureGenerationHandler
and SAML2SignatureValidationHandler
to the picketlink.xml
file:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" /> </Handlers> </PicketLink>
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" /> </Handlers> </PicketLink>
Handlers are implemented using a Chain of Responsibility, with each individual handler performing logic on request and responses in the order defined in picketlink.xml
. It is very important to pay attention to the order in which the handlers are configured.
The SAML2SignatureGenerationHandler should not be configured in the same chain as the SAML2EncryptionHandler. This will cause SAML messages will be signed several times.
<KeyProvider>
element must be added to BOTH picketlink.xml
files. This element provides the location and credentials for accessing the java keystore used for signing security assertions. An example of generating a java keystore can be found here. For the IDP the element should be added to <PicketLinkIDP>
:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... <KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager"> <Auth Key="KeyStoreURL" Value="/my_keystore.jks" /> <Auth Key="KeyStorePass" Value="store123" /> <Auth Key="SigningKeyPass" Value="test123" /> <Auth Key="SigningKeyAlias" Value="servercert" /> <ValidatingAlias Key="idp.example.com" Value="servercert" /> <ValidatingAlias Key="localhost" Value="servercert" /> <ValidatingAlias Key="sp1.example.com" Value="servercert" /> <ValidatingAlias Key="sp2.example.com" Value="servercert" /> </KeyProvider> ... </PicketLinkIDP> ... <PicketLink>
For the SP the element should be added to <PicketLinkSP>
:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> ... <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" SupportsSignatures="true"> ... <KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager"> <Auth Key="KeyStoreURL" Value="/my_keystore.jks" /> <Auth Key="KeyStorePass" Value="store123" /> <Auth Key="SigningKeyPass" Value="test123" /> <Auth Key="SigningKeyAlias" Value="servercert" /> <ValidatingAlias Key="idp.example.com" Value="servercert" /> <ValidatingAlias Key="localhost" Value="servercert" /> </KeyProvider> ... </PicketLinkSP> </PicketLink>
In order to properly sign and check assertions, the IDP needs to generate signatures and the SP needs to verify those signatures as well as identify where they came from. This is accomplished via the <ValidatingAlias>
element. IDPs need to have a <ValidatingAlias>
for each trusted server/domain that is trusted (i.e. every entry in the <Trust>
element). SPs need to have a <ValidatingAlias>
for each server/domain containing an IDP.
2.6.3. Handling AJAX Requests
In certain instances, SPs may need to recieve AJAX requests to secured resources. This is handled automatically without the need of any additional configuration. so authenticated and authorized users are able to make AJAX calls without issue. This is accomplished by checking for the existence of the X-Requested_With header in the request. In addition, cases where users are not authenticated, or if the request contains the header XMLHttpRequest, the IDP will respond with a 403 (Forbidden) status code instead of the login page.
Comments