[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
1). Select the API ‘JWT Generation and Validation’ and go to Gateway polices tab
2). Drag gatewayscript policy to operation-switch case 1
3). Copy-paste following code
1
2
3
4
var jwttoken = context.request.header.get('Authorization');
//remove Bearer from the token
context.set('input-jwt', jwttoken.replace(/^Bearer /g, ''));
4). 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
5). Drag ‘set-variable’ and copy the following yaml to source
1
2
3
4
5
6
7
8
9
- 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: ''
6). Create Catch policy for error handling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
7). Save and Publish the API to sandbox catalog
Testing (Success Scenario)
1). Add new GET Request in Postman
2). Add X-IBM-Client-Idin header
3). In Scripts section, copy paste following code to pre-request to GET /validate request:
1
2
3
4
5
6
7
8
var jwtToken = pm.globals.get("jwt_token");
pm.request.headers.add({
key: "Authorization",
value: jwtToken
}
)
4). First trigger GET /generate request first from Postman to fetch JWT in Authorization
postman screenshot - fetch jwt token
5). 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
API File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
— Keep Learning 😊
— Aditya Singh
If this article helped you in someway and want to support me, you can …
Comments powered by Disqus.