z/OS Connect - Group home

Using a JWT with z/OS Connect EE

  
This blog was originally published on April 25, 2017, by Aymeric Affouard, IBM Systems Center Montpellier.

1. Introduction

In the article Security considerations with z/OS Connect EE we showed how z/OS Connect EE can be used to authenticate REST clients, authorize access to APIs, audit requests, and ensure confidentiality and data integrity. This article focuses on using JSON Web Tokens with z/OS Connect.

JSON Web Tokens are an open, industry standard for representing claims securely between two parties. The claims in a JSON Web Token (JWT) are encoded as a JSON object and are normally digitally signed with a Message Authentication Code (MAC) and (optionally) encrypted. The most common scenario for using a JWT is authentication. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access services that are permitted with that token

A JWT is similar to a Security Assertion Markup Language (SAML) token in that they both convey claims; however, because JSON is less verbose than XML, a JWT is more compact than a SAML token. This makes JWT a good choice to be passed in HTML and HTTP environments.

Some advantages of using JWTs are:

  • They are lightweight and easy to use by client applications (e.g mobile).
  • They are self-contained, reducing the need to query the database multiple times.
  • They can be symmetrically signed by a shared secret using the HMAC algorithm, or you can use a public/private key pair in the form of a X.509 certificate for signing.
  • They have a built-in expiry mechanism.
  • They can be transferred between different servers and security domains.
  • They can be extended to contain custom claims.

For more information on JWTs see https://jwt.io/introduction/.

1.1 OpenID Connect

Externalization of enterprise services through APIs drives a focus on simplicity, security, and compatibility with standards-based external systems. The enablement of open secure APIs is made possible by using standards such as OAuth, an open standard for authorization, and OpenID Connect, an identity protocol that is built on the OAuth 2.0 protocol. OpenID Connect enables client applications to rely on authentication that is performed by an OpenID Connect Provider. The client application retrieves an ID token (in the form of a JWT) from the OpenID Connect Provider that is then used to access a resource on behalf of the user (see Figure 1).

OpenID Connect, flow authorization code
Figure 1 OpenID Connect, flow authorization code

Figure 1 shows the following steps:

  1. The user makes a request to the client application.
  2. The client application redirects the request to the OpenID Provider (OP).
  3. The OP authenticates the user and obtains authorization.
  4. The OP sends a grant code to the client application.
  5. The grant code is exchanged for an ID token, and also access and refresh tokens.
  6. The client application makes the request to the Resource server with the ID token which is used for authenticating the user and authorizing access to the resource.
  7. The response is sent to the user.

Liberty z/OS supports OpenID Connect 1.0 and can play a role as a Client, OpenID Connect Provider or Resource Server. For more information on configuring support for OpenID Connect with Liberty, see Using OpenID Connect.

In this article, we show how you can configure z/OS Connect EE as a Resource server to accept a JWT as an authentication token.

1.2 Anatomy of a JWT

Figure 2 shows that a JWT consists of three parts: a header, payload and signature.

JWTFigure 2 JWT

The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm being used, such as HMAC SHA256 (HS256) or RSA SHA256 (RS256). It is Base64Url encoded to form the first part of the JWT.

The payload contains the claims. Claims are statements about an entity (typically, the user) and additional metadata. There is a set of predefined claims, for example: iss (issuer), exp (expiration time), sub (subject) and aud (audience). These are not mandatory but recommended. In example figure 2, only the recommended sub claim is set. The payload may also include additional attributes that define custom claims such as employee role, manager, or department. In figure 2, the additional attributes are name and admin. The payload is Base64Url encoded to form the second part of the JWT.

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed along the way.

A JWT can also be optionally encrypted using JSON Web Encryption (JWE). Alternatively, you can use HTTPS to encrypt the complete message.

2. Security scenario

We use a hypothetical scenario to illustrate how z/OS Connect EE can be configured to consume a JWT as an authentication token. We show how the subject contained within the JWT can be mapped to a RACF user ID so that the user can be authorized to mainframe resources.

In our scenario, the user of a REST API accesses a catalog that is stored in CICS. The CICS application is accessed by invoking the catalog API which is deployed in z/OS Connect EE. This API is managed by an API Gateway that allows the API to be secured and the lifecycle of the API to be controlled. The use of such a solution forces every API invocation request to go through an API Gateway. The goal of this scenario is to protect the catalog API with an open security token, a JWT. This scenario is shown in Figure 3.

Security scenario

                                                                                                                                                  
Figure 3 Security scenario

Note:
 We refer to the API managed by API Connect as the ‘managed API’, and we refer to the API deployed in z/OS Connect EE as the ‘system API’.

The security requirements are as follows:

  • To call the managed API the user must authenticate using a valid identity and password
  • The user’s credentials must be checked against an LDAP registry
  • Requests to the system API must be authenticated using a JWT
  • The user’s “distributed” identity must be mapped to a RACF user ID
  • The user must be authorized to invoke the system API using the mapped RACF user ID
  • The user must be authorized to run the CICS transaction using the mapped RACF user ID

Note: In this article, we focus on the use of JWT with z/OS Connect EE. For information on addressing other typical API security requirements refer to the article Securing an API: an example scenario.

3. Security solution design

Figure 4 shows a high-level overview of our scenario.

Security design
                                                                                                                                          
Figure 4 Security design

Figure 4 shows the following set of security controls that are implemented in our security design:

  1. The user authenticates with the managed API using a “distributed” identity and a password. The user credentials are sent with the API request in an HTTP authorization header over a secure connection to API Connect. API Connect generates a JWT and forwards the token with the request to z/OS Connect EE.
  2. LDAP is used as the user registry for distributed users and groups.
  3. z/OS Connect EE performs a number of security functions:
    • Validates the JWT ( signature, expiration, issuer and audience)
    • Calls RACF to map the distributed ID to a RACF user ID
    • Calls RACF to check that the user is authorized to invoke the API
    • Audits the request to record who invoked the API
    • Propagates the distributed user ID to CICS
  4. RACF is used for the mainframe user registry, mapping distributed IDs to RACF user IDs and for authorizing API calls
  5. CICS maps the distributed ID to a RACF ID and performs further authorization checks to make sure that the mapped RACF user ID is authorized to access CICS resources

In the remainder of this article we describe an implementation of this security design that uses the capabilities of IBM API Connect, z/OS Connect EE, z/OS, RACF and CICS. And then in Testing the Scenario we show a case where an authorized user successfully invokes the API, and we also show cases where unauthorized users are preventing from invoking the API.

4. Security configuration

In this section we show how security controls are configured for each of the components in the solution.

4.1 API Connect

API Connect handles API lifecycle, controls access to APIs (subscriptions, rate limits etc.) and enforces security. In this article we focus on user authentication configuration and JWT generation using the generate-jwt policy of the DataPower API Gateway.

User authentication

When an API is defined, you can require calling applications to identify themselves by passing a single Client ID or a combination of a Client ID and a Client Secret. You can also define that requesters must authenticate using Basic Authentication.
Figure 5 shows the security definition we defined for the managed catalog API. A security definition contains security settings that you enforce to define access control requirements for the operations in the API.

API Connect Security Definition for managed catalog API
Figure 5 API Connect Security Definition for managed catalog API

For further information about defining user registries for API Connect, see Working with user registries.

Signing certificate

The API gateway uses a private key to sign the JWT. In our scenario, a certificate containing a key pair is created using RACF. The certificate is signed by a certificate authority. Figure 6 shows the certificate hierarchy.
Certificate hierarchyFigure 6 Certificate hierarchy                                                                                                                              

Once generated, the keys need to be imported into the API Connect manager console. The easiest way to do this is to import the certificate as a “Present Certificate” in a new TLS profile (Figure 7). TLS profiles are used to define the certificates and encryption keys that are used to secure the transport of requests to and from the API Gateway.

TLS Profile
Figure 7 TLS Profile                                                                                                                                      

Note: This certificate will not be used for TLS processing; it’s only a means to import the keys into the API Gateway.

Once created, a new Crypto object is created in DataPower that defines the Crypto Key that will be used to sign the JWT (Figure 8).

DataPower Crypto Key

                                                                                                                                            
Figure 8 DataPower Crypto Key


Note:
 the ID of the Crypto Key is used in the next step when generating the JWT.

For more information on creating certificates with RACF, see RACDCERT GENCERT (Generate certificate).
For more information on creating TLS Profiles in API Connect, see TLS Profiles.

Generating JWT

In API Connect assembly flows are used to manipulate requests and responses, and to define security options and other settings. Figure 9 shows the assembly flow for the managed catalog API.

Managed catalog API assembly flow

 Figure 9 Managed catalog API assembly flow
Figure 9 shows the different actions performed in the flow:

  • JWT settings (see Example 1) is a custom gatewayscript that retrieves the authenticated username from the http Authorization header, and sets the issuer and audience parameters for the jwt-generate action.
Example 1 JWT settings gatewayscript
var setvar = require('local://isp/policy/apim.setvariable.impl.js'); var apic = require('local://isp/policy/apim.custom.js'); var auth = setvar.getvariable('request.headers.authorization'); var username = Buffer(auth.split(' ')[1],'base64').toString().split(':')[0]; setvar.setvariable('context.username', username, 'add'); setvar.setvariable('iss.claim','idg','add'); setvar.setvariable('aud.claim','zCEE','add');
  • jwt-generate is a built-in policy of API Connect that generates a JWT. The policy enables you to generate claims and specify the cryptographic material for both signing and encrypting the token. The JWT can then be assigned to the http Authorization header as a Bearer token. This policy uses variables that were set in the JWT settings gatewayscript and it also refers to the DataPower Crypto Key (see Signing certificate).
Figure 10 shows the jwt-generate policy that we configured.
jwt-generate configurationFigure 10 jwt-generate configuration
  • Custom message mapping is performed for specific operations (post/orders).
  • A proxy is the action that actually sends the request to the system API endpoint (in our scenario this is z/OS Connect EE).

Example 1 shows a generated JWT, after decoding.

Example 1 Generated JWT

{ "alg": "RS256" } { "jti": "cb05c3f1-b858-46da-8bb3-cdecf732ef83", "iss": "idg", "sub": "JeanLeclerc", "aud": "zCEE", "exp": 1486744112.473 } { //signature }

The payload contains the following claims:

  • jti is the JWT unique identifier
  • iss is the issuer
  • sub is the subject (the authenticated user)
  • aud is the audience (z/OS Connect EE)
  • exp is the expiration time (expired tokens should be rejected)

When using the API Connect built-in policy jwt-generate, consider the following points:

  • The issuer and audience claims will be validated by z/OS Connect EE; the assigned values must be consistent.
  • If using an LDAP registry, the subject claim can be set to the Distinguished Name or the uid, and the JWT consumer in z/OS Connect EE must be configured accordingly.
  • API Connect supports several signature algorithms but to configure JWTs for consumption with z/OS Connect EE you should use only RS256 or HS256 algorithms.
  • z/OS Connect EE does not support encrypted JWTs.

For more information on using the API Connect built-in policy jwt-generate, see Generate JWT (jwt-generate).

4.2 LDAP

Figure 11 shows the LDAP registry used in our scenario. The registry contains different groups for employees, customers and different partners. The full Distinguished Name of the sample user is UID=JeanLeclerc,OU=employees,O=mop,C=fr.
LDAP registryFigure 11 LDAP registry                                                                                                                

4.3 z/OS Connect EE

This section shows how z/OS Connect EE is configured to validate a JWT, map the user identity to a RACF user ID, authorize the user to the catalog system API, audit the request and flow the RACF user ID to CICS.

Validating a JWT

The user authenticates with the API gateway and the authenticated distributed user ID (without password) is passed to z/OS Connect EE in a JWT.
z/OS Connect EE performs user authentication using the support that is provided by the openidConnectClient-1.0 feature. The element is used to accept a JWT token as an authentication token, as shown in Example 2.

Example 2 JWT authentication

<openidConnectClient id="RS" clientId="RS-JWT-ZCEE" inboundPropagation="required" signatureAlgorithm="RS256" trustStoreRef="JWTTrustStore" trustAliasName="JWTapicSign" userIdentifier="sub" mapIdentityToRegistryUser="false" issuerIdentifier="idg" authnSessionDisabled="true" audiences="zCEE"/>

In Example 2:

  • id and clientId are element identifiers
  • inboundPropagation is set to required to allow z/OS Connect EE to use the received JWT as an authentication token
  • signatureAlgorithm specifies the algorithm to be used to verify the JWT signature
Note: z/OS Connect EE supports two algorithms, RS256 (asymmetric algorithm) and HS256 (symmetric algorithm)
  • trustStoreRef specifies the name of the keystore element that defines the location of the validating certificate
Note: This certificate contains the public key that is used to validate the signature created by the corresponding private key configured in API Connect (see Signing certificate).
  • trustAliasName gives the alias or label of the certificate to be used for signature validation
  • userIdentifier indicates the claim to use to create the user subject
  • mapIdentityToRegistryUser indicates whether to map the retrieved identity to the registry user
Note: We set mapIdentityToRegistryUser as false as we have not configured z/OS Connect to connect to the LDAP registry (see Figure 11). Instead we will map the distributed identity to a RACF user ID (see ‘Mapping the user identity’
  • issuerIdentifier defines the expected issuer
  • authnSessionDisabled indicates whether a WebSphere custom cookie should be generated for the session
  • audiences defines a list of target audiences (the audience in the JWT must match one of the defined audiences)

The <openidConnectClient> element can include an authFilter that represents conditions that are matched against the HTTP request. Authentication filters permit different security policies depending on the request. One example is to put a filter on the path, so that the openidConnectClient element will apply only to that specific path. Another example is to put a filter on the remoteAddress to allow the usage of different certificates to validate the signature of the JWT depending on the server that sends the request.

For more information on configuring JSON Web token authentication, see Configuring JSON Web Token authentication for OpenID Connect and OpenID Connect Client (openidConnectClient).

Mapping the user identity

The mapDistributedIdentities attribute on the <safCredentials/> element is used to configure the z/OS Connect EE server to map the distributed user ID to a RACF user ID. Mappings are controlled using RACF RACMAP commends (see RACF).

Authorizing the user and auditing the request

The use of SAF (System Access Facility) for authorization is configured using the <safCredentials> element in server.xml.

We enable the authorization and audit interceptors in order to control access to the catalog system API and audit requests. Interceptors defined as global apply to all the APIs defined to the instance of z/OS Connect (unless the global definition is overridden). Interceptors defined as API-level apply only to that API.

The authorization interceptor works on the principle of user membership in a group. If an administrator group is defined to an API, and a user is a member of that group, that user has administrator authority for that API. If an invoke group is defined to an API, and a user is a member of that group, that user has invoke authority for that API. Similar authorization checks apply for the z/OS Connect EE Operator and Reader roles. Example 3 shows how we configure the interceptors and authorization groups in server.xml.

Example 3 z/OS Connect authorization and audit interceptors

<zosconnect_zosConnectManager globalInterceptorsRef="interceptorList_g" globalAdminGroup="GMADMIN" globalInvokeGroup="GMINVOKE"/> <zosconnect_authorizationInterceptor id="auth"/> <zosconnect_auditInterceptor id="audit"/> <zosConnectAPI name="catalog" interceptorsRef="interceptorList_s" />

In Example 3 we define the globalAdminGroup as GMADMIN which is the group access required for Admin authority, and we define the globalInvokeGroup as GMINVOKE which is the group access required for Invoke authority. Note that we could also define similar groups for Reader and Operator authority.

The globalInterceptorsRef= element is set to the value “interceptorList_g” for the global interceptors which means that the authorization interceptor will run for all API requests. This means that the mapped RACF user ID EMPLOY1 must be in the GMINVOKE RACF group in order to be able to invoke the catalog API. In addition, the catalog API is defined with an interceptorsRef= element is set to the value “interceptorList_s” which means that the audit interceptor will also be run for catalog API invocations.

You can use sample JCL provided by z/OS Connect EE to format the SMF 123 subtype 1 records written by the audit interceptor. Example 4 shows a subset of the fields found in the SMF 123.1 records.

Example 4 z/OS Connect authorization and audit interceptors

SYSTEM JOBNAME ARRIVAL-DATE ARRIVAL-TIME TARGET-URI SERVICE-OR-API METHOD USER-NAME ZT01 MOPZCEP 2017/03/14 11:09:23 /catalogManager/items catalog GET JeanLeclerc

In Example 4 we see that the user JeanLeclerc invoked the catalog API on 14th March at 11h.

Propagating the user ID to CICS


Our scenario uses the CICS Service Provider which supports the propagation of the distributed ID to CICS. The advantage of this is that the distributed id is then available in the CICS task association data. CICS maps the distributed ID to a RACF ID and runs the task with the mapped ID.

In addition to propagating the user ID to CICS, we also want to set the name of the CICS transaction that runs in CICS. This is done in the service configuration when creating the service using the z/OS Connect EE API Toolkit (see Figure 12).
Service configurationFigure 12 Service configuration

In Figure 12 we set the CICS transaction ID to MZIC which allows us to control access to the transaction and monitor usage of requests.

More information on configuring security with z/OS Connect EE can be found in the Knowledge Center. See Securing z/OS Connect EE resources.

4.4 RACF

We use RACF to implement the z/OS Identity Propagation feature of z/OS. Example 5 hows how the distributed user ID for user Jean Leclerc is mapped to the RACF user ID EMPLOY1.

Example 5 Identity mapping

RACMAP ID(EMPLOY1) MAP + USERDIDFILTER(NAME('JeanLeclerc')) + REGISTRY(NAME('*')) + WITHLABEL('Test Mapping EMPLOY1')

Note: Example 5 shows a one-to-one mapping. z/OS Identity Propagation also supports many-to-one mappings. We use a many-to-one mapping to map all identities associated to a specific partner to the same RACF user ID.

4.5 CICS

To enable the CICS task to run with the mapped RACF ID, we define an IPCONN definition in CICS configured with USERAUTH=IDENTIFY.

5. Testing the scenario

Figure 13 shows a successful invocation of a Bluemix application by the distributed user JeanLeclerc. The catalog of items, including stock and price information, has been retrieved using the catalog API.

Successful invocation of catalog API
Figure 13 Successful invocation of catalog API

We can use the CICS Explorer to validate that the CICS transaction is run with the mapped RACF user ID EMPLOY1 (Figure 14).

CICS transactionFigure 14 CICS transaction

Security errors

The following examples show some of the security errors that can occur when authenticating a request in z/OS Connect EE using a JWT:

  • Request does not contain a JWT
  • JWT is malformed
  • JWT with invalid signature
  • JWT with invalid issuer
Request does not contain a JWT

Example 6 shows the z/OS Connect EE message that is issued when a request does not contain a JWT.
Example 6 Request without JWT

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.

JWT is malformed

Example 7 shows the z/OS Connect EE message that is issued when a JWT cannot be parsed.
Example 7 Malformed JWT

CWWKS1737E: The OpenID Connect client [RS_JWT_ZCEE] failed to validate the JSON Web Token. The cause of the error was: [Unable to parse JWT Claim Set JSON: {… }]

JWT with invalid signature

Example 8 shows the z/OS Connect EE message that is issued when a JWT signature is invalid.
Example 8 Invalid signature

CWWKS1776E: Validation failed for the token requested by [RS_JWT_ZCEE] using the [RS256] algorithm due to a signature verification failure: [JWS signature is invalid: JsonWebSignature{"alg":"RS256"}->eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJpZGciLCJzdWIiOiJ ....] CWWKS1737E: The OpenID Connect client [RS_JWT_ZCEE] failed to validate the JSON Web Token. The cause of the error was: [JWS signature is invalid: JsonWebSignature{"alg":"RS256"}->eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJpZGciLCJzdWIiOiJOaWNvbGFzQm9zcyIsImF1.....]

JWT with invalid issuer

Example 9 shows the z/OS Connect EE message that is issued when a JWT has an invalid issuer.
Example 9 Request with an invalid issuer

CWWKS1737E: The OpenID Connect client [RS_JWT_ZCEE] failed to validate the JSON Web Token. The cause of the error was: [CWWKS1780E: Validation failed for the token requested by [RS_JWT_ZCEE] because the (iss) issuer [idg] that is specified in the token does not match any of the trusted issuers [DataPower] that are specified by the [issuerIdentifier] attribute of the OpenID Connect client configuration.]

6. Summary

This article describes an example scenario that highlights how a JSON Web Token (JWT) can be used to authenticate z/OS Connect EE API requests, and how the token can be mapped to a user ID in the local RACF registry. This allows z/OS Connect EE to participate in and integrate with other OpenID Connect enabled sites.