[Part 3/3] Securing APIs using JSON Web Token (JWT) in IBM API-Connect v10 using X.509 RSA key pair
Aditya Singh
Posted on September 25, 2024
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, ''));
- Drag jwt-validate
and fill the form
- JSON WebToken (JWT):
input-jwt
- Output Claims:
decoded.claims
- Issuer Claim:
apic
'for more than one claim, enter regrex pattern (PCRE)' - Audience Claim:
id1
- 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: ''
- 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
- Save and Publish the API to sandbox catalog
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
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
}
)
- First trigger GET /generate request first from Postman to fetch JWT in Authorization
- Now trigger GET /validate request from Postman and verify success 200 Ok with JWT payload details
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).
Scenario 2: Token Header is tampered
Scenario 3: Token payload is tampered
Scenario 4: Token signature is tampered
💖 💪 🙅 🚩
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.