[Part 3/3] Securing APIs using JSON Web Token (JWT) in IBM API-Connect v10 using X.509 RSA key pair

aditya_singh001

Aditya Singh

Posted on September 25, 2024

[Part 3/3] Securing APIs using JSON Web Token (JWT) in IBM API-Connect v10 using X.509 RSA key pair

Hello Tech Enthusiasts,

Refer previous parts of this series Part 1 and Part 2.

This is final article of our series focusses on the validation of JWT tokens using the APIC v10 jwt-validate policy.

Update API to Validate JWT token

- Select the API ‘JWT Generation and Validation’ and go to Gateway polices tab.

- Drag gatewayscript policy to operation-switch case 1.

- Copy-paste following code

var jwttoken = context.request.header.get('Authorization');

//remove Bearer from the token
context.set('input-jwt', jwttoken.replace(/^Bearer /g, ''));
Enter fullscreen mode Exit fullscreen mode

- Drag jwt-validate and fill the form

  1. JSON WebToken (JWT): input-jwt
  2. Output Claims: decoded.claims
  3. Issuer Claim: apic'for more than one claim, enter regrex pattern (PCRE)'
  4. Audience Claim: id1
  5. Verify Crypto Object: personal_sandbox_tlsp-jwt-keyprofileV1.0.0-ca-0

- Drag ‘set-variable’ and copy the following yaml to source

                - jwt-validate:
                    version: 2.0.0
                    title: jwt-validate
                    jwt: input-jwt
                    output-claims: decoded.claims
                    iss-claim: apic
                    aud-claim: id1
                    jws-crypto: personal_sandbox_tlsp-jwt-keyprofileV1.0.0-ca-0
                    jwe-crypto: ''
Enter fullscreen mode Exit fullscreen mode

- Create Catch policy for error handling

    catch:
      - errors:
          - RuntimeError
        execute:
          - set-variable:
              version: 2.0.0
              title: set-variable
              actions:
                - set: message.status.code
                  value: 400
                  type: number
                - set: message.status.reason
                  value: Bad Request
                  type: string
                - set: message.body
                  value: $(jwt-validate.error-message)
                  type: string
Enter fullscreen mode Exit fullscreen mode

- Save and Publish the API to sandbox catalog

api assembly

API file

swagger: '2.0'
info:
  title: JWT Generation and Validation
  x-ibm-name: jwt-generation-and-validation
  version: 1.0.0
  description: >
    This API has two parts 

    1. Generate JWT: The generate operation takes care of generating jwt token
    and setting that to response payload Authorization header

    2. 
x-ibm-configuration:
  cors:
    enabled: true
  gateway: datapower-api-gateway
  type: rest
  phase: realized
  enforced: true
  testable: true
  assembly:
    execute:
      - operation-switch:
          version: 2.0.0
          title: operation-switch
          case:
            - operations:
                - verb: get
                  path: /generate
              execute:
                - jwt-generate:
                    version: 2.0.0
                    title: jwt-generate
                    jwt: ''
                    iss-claim: request.headers.iss-claim
                    exp-claim: 60
                    description: //This policy is to generate JWT token for client request.
                    jws-alg: RS256
                    jws-crypto: personal_sandbox_tlsp-jwt-keyprofileV1.0.0-key
                    jti-claim: true
                    aud-claim: request.headers.aud-claim
            - operations:
                - verb: get
                  path: /validate
              execute:
                - gatewayscript:
                    version: 2.0.0
                    title: gatewayscript
                    source: >-
                      var jwttoken =
                      context.request.header.get('Authorization');


                      context.set('input-jwt', jwttoken.replace(/^Bearer /g,
                      ''));
                - jwt-validate:
                    version: 2.0.0
                    title: jwt-validate
                    jwt: input-jwt
                    output-claims: decoded.claims
                    iss-claim: apic
                    aud-claim: id1
                    jws-crypto: personal_sandbox_tlsp-jwt-keyprofileV1.0.0-ca-0
                    jwe-crypto: ''
                - set-variable:
                    version: 2.0.0
                    title: set-variable
                    actions:
                      - set: message.body
                        value: $(decoded.claims)
                        type: string
                      - set: message.headers.Content-Type
                        value: application/json
                        type: string
                    description: >-
                      This policy is setting response body from the extracted
                      jwt verification
          otherwise: []
    catch:
      - errors:
          - RuntimeError
        execute:
          - set-variable:
              version: 2.0.0
              title: set-variable
              actions:
                - set: message.status.code
                  value: 400
                  type: number
                - set: message.status.reason
                  value: Bad Request
                  type: string
                - set: message.body
                  value: $(jwt-validate.error-message)
                  type: string
  properties:
    target-url:
      value: http://example.com/operation-name
      description: The URL of the target service
      encoded: false
  activity-log:
    enabled: true
    success-content: activity
    error-content: payload
basePath: /securetoken
paths:
  /generate:
    get:
      responses:
        '200':
          description: success
          schema:
            type: string
  /validate:
    get:
      responses:
        '200':
          description: success
          schema:
            type: string
securityDefinitions:
  clientID:
    type: apiKey
    in: header
    name: X-IBM-Client-Id
security:
  - clientID: []
schemes:
  - https
Enter fullscreen mode Exit fullscreen mode

Testing (Success Scenario)

- Add new GET Request in Postman

- Add X-IBM-Client-Idin header

- In Scripts section, copy paste following code to pre-request to GET /validate request:

var jwtToken = pm.globals.get("jwt_token");

pm.request.headers.add({
    key: "Authorization",
    value: jwtToken

}
)
Enter fullscreen mode Exit fullscreen mode

- First trigger GET /generate request first from Postman to fetch JWT in Authorization

postman screenshot - fetch jwt token

- Now trigger GET /validate request from Postman and verify success 200 Ok with JWT payload details

postman screenshot - successful scenario

Testing (Failure Scenario)

Scenario 1: Token is expired

Response received:
JWT validation failed, because the JWT has expired at Sun Sep 08 2024 21:52:31 GMT+0100 (British Summer Time).

postman screenshot - failure scenario 1

Scenario 2: Token Header is tampered

postman screenshot - failure scenario 2

Scenario 3: Token payload is tampered

postman screenshot - failure scenario 3

Scenario 4: Token signature is tampered

postman screenshot - failure scenario 4

💖 💪 🙅 🚩
aditya_singh001
Aditya Singh

Posted on September 25, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related