IBM Security Global Forum

 View Only

ISAM 9.0.2: The JWT STS Module and Junction SSO to WebSphere Liberty

By Shane Weeden posted Fri November 11, 2016 12:00 AM

  

Today we at IBM have released the latest version of IBM Security Access Manager – ISAM 9.0.2. This release has several new and improved capabilities, particularly in the space of mobile multi-factor authentication, however in this particular article I plan to discuss a new Security Token Service module that supports the generation and validation of JSON Web Tokens (JWT) and how these can be used to facilitate junction SSO to Websphere Liberty (tested with version 16.0.0.3), including roles-based access control in J2EE Applications.

JWT’s have been around for a few years now, and there is plenty of literature available in the public domain on their format and content. Essentially a JWT is an optionally signed and/or encrypted set of attributes (aka claims), with the claims being represented as a JSON object. Many of the claims themselves have been standardized, including iss, sub, aud, iat, nbf, exp and others. Not surprisingly these claims represent Issuer, Subject, Audience, IssuedAt, NotBefore, Expires. Where have I seen those types of identifiers before? …. why SAML of course. Yes, in my opinion, JWT’s are really just JSON-ified SAML Assertions, with significant improvements to the methods of encoding to be more compact and compatible with HTTP protocols.

ISAM 9 (and Tivoli Federated Identity Manager before it) offers a general purpose Security Token Service supporting the WS-Trust standard for the validation and exchange of one security token type for another. It is used internally by the ISAM Federation module for supporting federated SSO protocols, and by the ISAM web reverse proxy (WebSEAL) for supporting TFIM-SSO junctions (heritage terminology) and OAuth access token validation. It can also be called explicitly via WS-Trust SOAP/XML, as I have previously discussed:  Using cURL to send requests to the TFIM Security Token Service

WebSphere Liberty Application server is IBM’s current J2EE application runtime. Unlike it’s traditional WebSphere Application Server predecessor (here known as TWAS), Liberty is a lightweight composed set of plugins designed to be stripped down to the bare essentials needed for a specific application rather than carrying around a large filesystem and memory footprint with everything you could possibly need for any application all of the time. Instead of running a small number of TWAS clusters with redundant nodes, Liberty is designed to be able to run one-process-per-application, and is well suited to micro-services architectures as well as cloud runtimes. In fact Liberty is the primary runtime platform of the IBM Bluemix PAAS offering.

For many years customers of IBM have been running J2EE WebSphere applications on TWAS junctioned behind WebSEAL. In this architecture WebSEAL (now called the ISAM web reverse proxy) provides rich authentication and URL-level authorization services, and the WebSphere application server J2EE container provides role-based access control to applications using standard J2EE security constraints. Functionally, WebSEAL downstreams user session credential information to WebSphere in the form of a proprietary HTTP header called iv-creds, which contains encoded authenticated user and group information as asserted by WebSEAL. At the WebSphere side, a custom trust association interceptor (TAI) was configured to interpret this header and create a JAAS Subject with credentials that allow the J2EE container to enforce security constraints either defined in the deployment descriptor of the application, or programmed as logical “isUserInRole()” conditions in the application code itself. For more information on the TAM TAI++, see http://www.ibm.com/developerworks/tivoli/library/t-tamtai/.

There are several issues with this approach. These have been amplified with the move from TWAS to WebSphere Liberty, and become even more obvious when looking at deployment scenarios involving embedded or cloud-hosted application runtimes such as IBM Bluemix. In short, this approach does not work with WebSphere Liberty at all. Here’s some of the reasons why it doesn’t work, and why IBM is moving away from TAI integration between ISAM and Liberty:

  • The TAM TAI++ relies on Java classes provided by PD.jar, typically shipped with ISAM. The PD.jar relies on WebSphere classes to be in the classpath that are not directly available in the Liberty OSGi runtime plug-in model.
  • PD.jar has JRE version dependencies that are not in lock-step with Liberty JRE requirements. This leads to unresolvable compatibility matrixes between ISAM and Liberty versions.
  • Use of classes in PD.jar as used by the TAM TAI++ requires configuration of the JRE to know about the TAM policy and authorization servers (pdjrtecfg and svrsslcfg). This is impossible in a cloud-hosted JRE/Liberty runtime environment such as IBM Bluemix.
  • The TAM TAI++ requires configuration of a symmetric secret so that WebSphere can assert a request has arrived from a trusted WebSEAL. In public cloud deployment scenarios such as Bluemix, this is undesirable. Instead asymmetric security should be used to allow secrets to be maintained only by the originator and verified by any intended recipient.
  • ISAM and Websphere have their own independent release schedules and targets, making it extremely difficult for product teams to keep in synch on version and configuration compatibility.

Instead what is needed is a protocol and on-the-wire security token contract with the following characteristics:

  • The security token passed from WebSEAL to Liberty should be compact, standards-based, and HTTP-transport compatible (i.e. not XML, and with a standard ASCII encoding suitable for headers)
  • ISAM should natively support generating the token format, and WebSphere should natively support consuming it. This decouples the products and means that ISAM-provided code does not need to be shipped with, or run on, Liberty.
  • WebSEAL should be able to authenticate that it is communicating with a trusted Liberty Server (this is achieved with server-authenticated SSL junctions), and Liberty should be able to authenticate that the token is generated by a trusted WebSEAL (this is achieved with signing of the JWT). Such mutual trust should be based on asymmetric key security.
  • Configuration of a User Registry in Liberty (or at a minimum the presence of ISAM users in the Liberty-configured registry) should be optional as the username, their groups, and their attributes should all be able to be asserted into the JAAS Subject. This is particularly important for hybrid cloud deployment scenarios where the on-premise user registry may not be reachable from cloud. TAM TAI++ does have this property today, but integrations like LTPAv2 cookies does not.

A number of different technologies were looked at to meet the needs of SSO between ISAM and Liberty, and for all of the reasons above, a signed JWT sent over a server-authenticated SSL/TLS junction was chosen as the preferred token format. The architecture for this solution, shown in the context of ISAM on-premise and the Liberty application running either on-premise or on Bluemix is as follows:

The remainder of this article discusses configuration of a demonstration of the solution.

Configuring ISAM Web Reverse Proxy to send JWT on a Junction

This type of junction is known, for historical reasons, as a TFIM-SSO Junction. The capability has been in WebSEAL for some time, and is quite well documented. There is also an excellent step-by-step example of setting up a TFIM-SSO Junction for SAML assertions (instead of JWT) in section 19 of the ISAM Federation Cookbook. Rather than repeating that documentation here, instead I will share the high-level steps and point out the differences in configuration with that of sending a SAML assertion across a junction. You should follow along with a copy of the ISAM Federation Cookbook open to chapter 19. In our example we will be passing the JWT using the header name “jwt”, and will make the assumption that the ISAM federation runtime is running on the same ISAM appliance as WebSEAL (i.e. localhost), and that basic-auth credentials for communicating with the federation runtime are “easuser:Passw0rd”. The easuser password can be set in the LMI as shown in section 17.4 of the ISAM Federation Cookbook. Ultimately these BA credentials need to represent an identity in the adminGroup of the Federation Runtime, as membership of this group is currently required to invoke the STS.

Step 1 – Load the SSL certificate of the federation runtime (i.e. localhost:443) into the pdsrv keystore

This is needed so that WebSEAL can communicate with the STS of the federation runtime. The federation cookbook guides you through how to do this in Appendix D – Load Federation Runtime SSL certificate into pdsrv trust store. Basically you:

  • Manage System Settings -> SSL Certificates
  • Select pdsrv and Mange->Edit SSL Certificate Database
  • With the Signer Certificates tab selected, Manage->Load
  • Enter “localhost” for the Server, and “443” for the Port, put in any certificate label, e.g. “Local Federation Runtime”, and press Load.
  • Press Close, then review and deploy changes.

Step 2 – Load the SSL certificate chain of the server to be junctioned into the pdsrv keystore

This could be done using the same procedure as Step 1 if the junctioned server has a self-signed certificate, but it if is a real server cert signed by a trusted certificate chain, you may need to manually load the individual certificates of the signing chain into the keystore. Use Manage->Import (instead of Load) on the signer certs to do this from PEM files. If you don’t complete this step correctly you will have issues creating an SSL junction to your target Liberty server. In my example (junctioning to the production IBM Bluemix platform) I created two PEM files for the Digicert certificates (a root CA and an intermediate) that form the SSL trust chain for the *.mybluemix.net SSL certificate and loaded those. Your exact certificate requirements here will vary depending on the SSL cert of the Liberty application server you will junction to.

Step 3 – Create the STS template and chain in the Federation Runtime

In this step you are creating a chain to map ISAM credentials (iv-creds) to JWT. This is very similar to the techniques shown in sections 19.1 and 19.2 of the ISAM Federation Cookbook except that you are going to use a different mapping rule file, and you will use the JWT STS module instead of the SAML STS module (with appropriate configuration). Additionally the chain lookup properties need to match the parameter WebSEAL will send in WS-Trust requests to the STS. These will come from the [tfimsso:/jwtjct] stanza in the WebSEAL configuration file. You should set yours to match, as shown:

Here is an example of a Javascript mapping rule that I use when mapping from iv-creds to JWT. Download ivc_to_jwt.js here.

 

Note that what it ultimately does is populate a special ContextAttribute of the STSUniversalUser (stsuu) with the pre-formatted JSON claims that we want to construct and sign in the JWT. The JWT module, in issue mode, will first look for this special ContextAttribute (claim_json) and use it if present. If not present, it will build claims from the AttributeList of the STSUU assuming all attributes are string data types, along with applying other JWT module configuration for inserting special attributes like sub, iss, iat, exp, and so on. The advantage to using the claim_json special attribute is that you can construct rich, typed claims in your mapping rule – integers, arrays, nested JSON objects, etc. It puts a little more work into the mapping rule, but the benefit is the richness of claims you can express in your JWT.

You will see some special processing in the mapping rule for converting AZN_CRED_GROUP_NAMES to a “groups” array – this is important for our role-based access example.

Additionally there is code included for adding a “sess” attribute. This attribute is useful for a couple of different scenarios such as:

It is not compulsory, but can be useful, and I suggest you leave it in there.

When configuring properties of the JWT STS module, as all of the desired claims have already been populated by the mapping rule in the claim_json attribute, the only required configuration is the signing algorithm, keystore and key label. In this case the signing algorithm is RS256 (at the time of writing, this is the only asymmetric key algorithm supported by the Liberty runtime), and an appropriate key (rsakey1) has been selected from the keystore (myidp):

Other properties of the JWT STS module can be left unset.

Step 4 – Updating the WebSEAL configuration file

As shown in section 19.3 of the ISAM Federation Cookbook, the WebSEAL configuration file is then updated to include the following (passwords will be auto-obfuscated when saving the file updates):

[tfim-cluster:jwtjct]
 server = 9,https://localhost:443/TrustServerWST13/services/RequestSecurityToken
 ssl-keyfile = pdsrv.kdb
 ssl-keyfile-stash = pdsrv.sth
 handle-pool-size = 10
 handle-idle-timeout = 240
 timeout = 240
 basic-auth-user = easuser
 basic-auth-passwd = Passw0rd
[tfimsso:/jwtjct]
 token-type = urn:ietf:params:oauth:token-type:jwt
 applies-to = http://appliesto/jwt
 renewal-window = 15
 preserve-xml-token = false # Note - false here means strip off the <BinarySecurityToken> XML label included in WS-Trust response
 always-send-tokens = true
 tfim-cluster-name = jwtjct
 one-time-token = false # Note - false here means that a single token will be retrieved from STS and used during the WebSEAL session
 token-collection-size = 1
 token-transmit-type = header
 token-transmit-name = jwt

Save the file, then review and deploy changes, then restart your WebSEAL server instance.

Step 5 – Create the TFIM-SSO junction

As shown in section 19.4 of the ISAM Federation Cookbook, it is recommended that junction create be done with pdadmin, or automated. Using pdadmin this can be done as follows:

pdadmin> server task default-webseald-isam.myidp.ibm.com create -t ssl -h <your_Liberty_server_host> -p <your_Liberty_server_port> -Y /jwtjct

In my case, I have an application deployed on Bluemix, at jwtjct.mybluemix.net:443 and my create looks like:

pdadmin> server task default-webseald-isam.myidp.ibm.com create -t ssl -h jwtjct.mybluemix.net -p 443 -Y /jwtjct

This concludes all configuration of ISAM for sending JWT’s across a junction called /jwtjct.

When trying to debug configuration issues, you should first look in the reverse proxy message log, and also in the federation runtime (also known as the mobile runtime) message log.

You can ultimately verify that JWT’s are created and sent by enabling pdweb.snoop trace for the WebSEAL server, then making a request across the junction whilst monitoring the pdweb.snoop.log trace file.

Configuring Liberty to Require and Accept JWT as an Identity Propagation Token

The feature discussed in this section was added to Liberty in 2016. Whilst I am not certain of the first version of Liberty to contain it, I have tested with 16.0.0.3 successfully, so would recommend this version or later.

The heart of any Liberty server configuration is server.xml. This defines what features are configured for the server. In our example it also defines the authentication requirements of the application itself. JWT identity propagation is managed via a special configuration of the OpenID Connect Client in Liberty, using the inboundPropagation parameter. You can read more about JWT authentication in Liberty here:

http://www.ibm.com/support/knowledgecenter/SSEQTP_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_sec_config_jwt.html

For our purposes I plan to simply present the server.xml of the Liberty server that I have used for this demonstration. Use the settings here, and the reference information above to understand more:

 

<?xml version="1.0" encoding="UTF-8"?>
 <server description="new server">
<!-- Enable features -->
 <featureManager>
 <feature>jsp-2.3</feature>
 <feature>openidConnectClient-1.0</feature>
 <feature>ssl-1.0</feature>
 </featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
 <httpEndpoint id="defaultHttpEndpoint"
 httpPort="9080"
 httpsPort="9443"
 host="*" />
<keyStore id="defaultKeyStore" password="Liberty"/>
<openidConnectClient
 id="RS"
 inboundPropagation="required"
 issuerIdentifier="https://www.myidp.ibm.com"
 audiences="ALL_AUDIENCES"
 signatureAlgorithm="RS256"
 trustStoreRef="defaultKeyStore"
 trustAliasName="rsakey1"
 realmName="defaultRealm"
 groupIdentifier="groups"
 headerName="jwt"
 />
<!-- Automatically expand WAR files and EAR files -->
 <applicationManager autoExpand="true"/>
 </server>

Note that in this case my Liberty server includes the PUBLIC KEY for rsakey1 in the <server_root>/resources/security/key.jks file (i.e. the defaultKeyStore) of the Liberty server.

I also have a J2EE application deployed in the dropins directory of my Liberty Server. My application is called SubjectDumper, and I’ve included the complete EAR file containing it for you to download here.

The SubjectDumper has a couple of useful JSPs that introspect the JAAS Subject and display discoverable content. Additionally there are security constraints and role->group mappings defined in the application deployment descriptors.

There are three roles defined in the application (from ibm-application-bnd.xml):

 <security-role name="all">
   <special-subject type="ALL_AUTHENTICATED_USERS" />
 </security-role>
 <security-role name="RoleA">
   <group name="groupa" access-id="group:defaultRealm/groupa" />
 </security-role>
 <security-role name="RoleB">
   <group name="groupb" access-id="group:defaultRealm/groupb" />
 </security-role>

 

These are the server-relative URL paths of the key parts of the application explained, along with the required security constraints (which are defined in web.xml):

/dumpHeaders.jsp – Any user can access this, authenticated or unauthenticated. It dumps a HTML page of the HTTP headers received.
/dump.jsp – Requires the “all” role. Dumps the contents of the JAAS Subject. Any jwt-header authenticated user should be able to access this.
/whoami.jsp – Requires the “all” role. Dumps a simplified view of the JAAS Subject Principal.
/rolea/dump.jsp – Requires the “RoleA” role, content is identical to /dump.jsp.
/rolea/whoami.jsp – Requires the “RoleA” role, content is identical to /whoami.jsp.
/roleb/dump.jsp – Requires the “RoleB” role, content is identical to /dump.jsp.
/roleb/whoami.jsp – Requires the “RoleB” role, content is identical to /whoami.jsp.

Exercising the End to End Flow

When the liberty server starts up, you can try accessing /dumpHeaders.jsp with a browser. This should return a HTML page showing all the received HTTP headers. Now try accessing /dump.jsp. You should get back a 401 Unauthorized response (check with curl), and if you view the Liberty server logs, a message like this will be shown:

[ERROR ] CWWKS1726E: The resource server failed the authentication request because the request does not have a required propagation token, such as: an access token or jwt token.

Now access /dump.jsp via WebSEAL, for example: https://www.myidp.ibm.com/jwtjct/dump.jsp

Provided your configuration is correct, you should see a HTML page with extensive information about the user you logged in as at WebSEAL (I have a user called “testuser”), similar to that shown below:

Try adding your testuser to an ISAM group called “groupa”, then re-authenticate and access /rolea/dump.jsp. What happens if you access /roleb/dump.jsp, and are not in a group called “groupb”?

Advanced – Using JWK URI to advertise public keys and facilitate no-interruption key rollover

In the server.xml example shown for my Liberty server, notice the following two parameters that are used to identify the public key used to verify the signature on the JWT included in the “jwt” header:

  trustStoreRef="defaultKeyStore"
  trustAliasName="rsakey1"

Whilst this works, it is a very static type of configuration, and pins the configuration of the target Liberty server to a specific signing key. This does not allow the WebSEAL server to gracefully perform key rollover without syncrhonizing that operation with a junctioned application update.

The OpenID Connect Client configuration of the WebSphere Liberty server has another way to indirectly reference the public keys that may be used for signature validation. This is called the jwkEndpointUrl, and the usage of a URL to represent a JSON Web Key Set is documented in RFC 7517 (https://tools.ietf.org/html/rfc7517).

Instead of specifying trustStoreRef and trustAliasName, you can specify a jwkEndpointUrl. This should point to a https endpoint (with trust being established via the public certificates in your Liberty server’s key.jks) that returns a JSON Web Key Set. For example:

<openidConnectClient
 id="RS"
 inboundPropagation="required"
 issuerIdentifier="https://www.myidp.ibm.com"
 audiences="ALL_AUDIENCES"
 signatureAlgorithm="RS256"
 jwkEndpointUrl="https://jwksuri.mybluemix.net/certs.jsp"
 realmName="defaultRealm"
 groupIdentifier="groups"
 headerName="jwt"
 />

In this example the URL https://jwksuri.mybluemix.net/certs.jsp points to an application that returns a JSON Web Key set, with all keys that can be used as signing keys. For example:

{
 "keys": [
  {
    "kty": "RSA",
    "kid": "zOZqm7l5SG5bLiXek7uY2x3SMsn3aMLIZK3W6Be0Pgo",
    "use": "sig",
    "n": "pg9abrFXRaqGcVs_xEzn-mZhmQG0YClKP69_A0WgB91yO7dV1jov5hPEy247CVht7PS9JsHHu-Ayc9AFzX75kJWj5e0IhZSI-JN1sadUAQiQb5XeMuNEegWfUP3JwES8vQuWos4if7KWH5d6gl0BuvONnRt8htsaEsa7aBsAj6E",
    "e": "AQAB"
  },
  {
    "kty": "RSA",
    "kid": "PdRpKXH8hlzbHWbVs0t_XpUCOSYkRE_cZEZaAN6sIf8",
    "use": "sig",
    "n": "y9ehOS1Q_xIbb_Qp08KIVAot8XoIeQmAKCP0W8WljPbYwa9wc2OQaUh4W4XvGt8wEs_exZ-K9bIeT8hTcs0bhaAE_flPaVpoZ_lI61PM6q2WXaq-F1XMgXjmCPvBEK-bqj-y3ALu20kPN79nR1lz4VP8Dcq6C7o3EtAsX2LV9Pc",
    "e": "AQAB"
  }
 ]
}

When WebSEAL sends a JWT across as a HTTP header, the JWT includes a header of it’s own which specifies the signing algorithm and the Key Identifier (known as the “kid”). Provided the kid has a matching public key in the document pointed to by the jwkEndpointUrl, the Liberty OpenID Connect client can verify the signature of the JWT without having to have the signing key in a local keystore.

The administrator of the WebSEAL configuration should also be the owner of the application that servers the jwkEndpointUrl. If wanting to roll over the signing key, the administrator would:

  • first update the application pointed to by the jwkEndpointUrl to include both the old and the new kid’s
  • then update the JWT STS module in ISAM to use the new signing key

Liberty servers will automatically go and re-retrieve the document at the jwkEndpointUrl when a new kid is seen in the JWT.

Having tried this, I found it necessary to know how ISAM automatically derives and generates a kid for a particular public key so that I could write an application which could serve up a set of public keys in a JSON document from a single keystore containing all the possible public signing keys (the keystore is embedded within my jwksuri.mybluemix.net application and is updated whenever I add a new signing key to WebSEAL). The algorithm (as shown in Java code) is:

String kid = Base64Url.encode(MessageDigest.getInstance("SHA-256").digest(cert.getEncoded()));

I have included the certs.jsp (which makes use of the jose4j library published by Brian Campbell – see https://bitbucket.org/b_c/jose4j) so that you can see how to generate a JSON Web Key Set compatible with ISAM from a keystore containing just the public keys used for signing. Download certs.jsp here.

Note again – you don’t NEED to use a jwkEndpointUrl to contain your signing certs – you can of course pin a particular sigining cert by including it in the local keystore of your Liberty server and directly reference it with trustStoreRef/trustAliasName. The reason for using a jwkEndpointUrl has everything to do with being a little more flexible and allowing scenarios like key rollover to be managed independent of changes to the Liberty application server.

Conclusion

In this article I have described a change in technical direction for facilitating junction based single sign-on between ISAM WebSEAL and the WebSphere Liberty application server. I have explained why the change in technical direction is needed and the advantages to the new approach, which includes flexible support for hybrid cloud application deployment.

I have explained precisely how to configure both your ISAM environment and your WebSphere Liberty environment to allow secure identity propagation using a JSON Web Token. Finally I showed an advanced configuration option to allow discovery of the public keys used for signature verification which will permit automatic key rollover operations without impacting deployed junctioned applications.

I hope you find this article useful if you are on a cloud migration journey of your own and particularly if you are using or looking to use ISAM in front of WebSphere Liberty Applications. This is particularly relevant for customers with on-premise ISAM junctioning to public or dedicated Bluemix environments.

0 comments
18 views

Permalink