DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Attribute Based Access Control for Mulesoft APIs
  • Authorizing the MuleSoft API Using AWS Cognito User Pool and Mule JWT Validation Policy
  • Generic and Dynamic API: MuleSoft
  • A Practical Guide to Securing NodeJS APIs With JWT

Trending

  • Advancing Robot Vision and Control
  • Simplifying Multi-LLM Integration With KubeMQ
  • The Perfection Trap: Rethinking Parkinson's Law for Modern Engineering Teams
  • Supervised Fine-Tuning (SFT) on VLMs: From Pre-trained Checkpoints To Tuned Models
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Enforcing MuleSoft JWT Validation Policy Using API Manager API

Enforcing MuleSoft JWT Validation Policy Using API Manager API

By 
Jitendra Bafna user avatar
Jitendra Bafna
DZone Core CORE ·
Apr. 07, 20 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
25.5K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between the two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

  • JWTs are stateless, making tokens easier to manage.
  • JWTs can be used to transfer claims securely between parties.
  • JWTs are scalable.
  • JWTs are decoupled in nature allowing authentication to happen on a different server.
    The tokens are compact. JSON format makes the token less verbose than XML. The smaller size allows easier transmission over HTTP.
  • JWTs are JSON-based and can be easily parsed by multiple receiving systems, especially mobiles. This enables industry-wide adoption.

The JWT Validation policy validates the signature of the token and asserts the values of the claims of all incoming requests by using a JWT with JWS format. The policy does not validate JWT that uses JWE.

Applying JWT policy

Applying JWT policy


JWT configuration

JWT configuration

Validating Claims

Claim validations enable you to choose the conditions under which a token received in the policy is rejected. The following registered claim validations are provided by default:

  • aud: The Audience validation specifies that a token must be rejected if it does not contain at least one of the values defined.
  • exp: The Expiration validation specifies that a token must be rejected if its date is past the validation date.
  • nbf: The Not before validation specifies that the token must be rejected if the validation time is before the time the token has.

In addition to these provided claims, you can also specify other claims to use in your validations. For all claims, Registered or Custom, you must provide the following details:

  • The name of the claim you want to validate. For example, for the issuer of the token.
  • The value used to test.

You can provide a simple literal value if you only need to verify it, or you can provide a DataWeave expression for more complex comparisons.

You can define each claim validation as mandatory or non-mandatory. If a claim is defined as mandatory and is not present in the incoming JWT, the policy rejects this token. If a claim is defined as non-mandatory and is not present in the incoming JWT, the policy does not reject the token for that specific validation.

For both cases, if a claim is present, the policy validates the token value. If the validation fails, the JWT will be rejected.

Element

Description

Example

JWT Origin

Specifies from where in the request the JWT will be extracted: * Bearer Authentication Header * Custom Expression

If you set it to Bearer Authentication Header, the JWT will be expected as Bearer.

If you set this field to Custom Expression, a DataWeave Expression returning the token must be provided.



Token Expression

If you set the JWT Origin to Custom Expression, type the DataWeave expression returning the JWT here.

#[attributes.headers['jwt']]

This expression searches the JWT in the header named ‘jwt’.

JWT Signing Method

Specify the signing method expected in the incoming JWT. The policy rejects the token if the JWT has a different signing method.

RSA, HMAC, None

JWT Signing Key Length

Specify the length of the key (in the case of the HMAC algorithm) or the algorithm (in the case of RSA) used for the signing method.

Ignore this field if you selected none as JWT Signing Method.


JWT Key Origin

Specifies where to obtain the key for the Signature validation.

You can provide the key in the policy selecting the Text option or obtain it from JWKS.

Ignore this field if you selected none as the JWT Signing Method.


JWT Key

This field appears if you select Text as JWT Key Origin.

Use this field to provide the key used to check the signature of the token.

Ignore this field if you selected none as the JWT Signing Method.

A 32, 48 or 64 characters long shared secret in case HMAC was the selected JWT Signing Method or the PEM Public Key without the header nor the footer in case of selecting RSA.

JWKS URL

This field appears if you selected the JWKS method as JWT Key Origin.

Ignore this field if you selected none as the JWT Signing Method.

The URL to the JWKS server.

JWKS Caching Time To Live

The URL to the JWKS server that contains the public keys for the signature validation.

Ignore this field if you selected none as the JWT Signing Method.

This field input is the amount of time, in minutes, during which the policy considers the JWKS valid.

Skip Client ID Validation

If you check this field, the policy does not verify that the client ID extracted from the JWT matches a valid client application of the API.

By default, the value will be extracted using the expression #[vars.claimSet.client_id]

Client ID Expression

If Skip Client Id Validation is not set, the client ID needs to be extracted from the token.


Validate Audience Claim

Indicates that the policy should check for the validity of the audience claim. You can set this "Mandatory" if you select Audience Claim Mandatory.


Validate Expiration Claim

Indicates that the policy should check for the validity of the expiration claim. You can set this claim as "Mandatory" by selecting Expiration Claim Mandatory.


Validate Not Before Claim

Indicates that the policy should check for the validity of the Not Before claim. You can set this claim as "Mandatory" by selecting Not Before Claim Mandatory


Validate Custom Claim

Enables the usage of custom validations in the policy. The JWT will be valid only if all DataWeave expressions are fulfilled.

The policy provides a claimSet variable that contains all the claims present in the incoming JWT. For example:

foo : #[vars.claimSet.foo == 'fooValue']


There are various attributes required to enforce a JWT validation policy. 

Applying the JWT Validation Policy Using API Manager API

First, we need to identify which API can be used to apply the policies. So, Mulesoft provided a developer portal that can be used to fetch details about the policies API.

https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/api-manager-api/minor/1.0/pages/Applying_a_policy/

Mulesoft API manager

Mulesoft API manager

Policies API URL

https://anypoint.mulesoft.com/apimanager/api/v1/organizations/{organizationId}/environments/{environmentId}/apis/{environmentApiId}/policies

We need to pass organizationId, environmentId, and apiId in the above URL as URI parameter.

Fetching Organization Id

To fetch Organization Id, Navigate to Access Management ⇒ Organization, click on your organization, and it will open a pop-up window that provides the Organization Id. This can be used in the URI parameter of the policies API.

Adding organization info

Adding organization info


Fetching Environment Id 

To fetch Environment Id, Navigate to Access Management ⇒ Environment, click on your environment (i.e. Sandbox), and it will open a pop-up window. From there, we can get the environment Id in URL, and it can be used in the URI parameter of the policies API.

Getting environment Id

Getting environment Id

Fetching API Id

For fetching API Id, Navigate to the API Manager in AnyPoint Platform and select the API for which you need to apply the policy, and you can see API Id.

Time Zone API

Time Zone API

Now, we have the organizationId, environmentId, and apiId that need to be passed to the policies API as URI parameters.

We will also need an access token that we'll be pass in the Authorization header of Policies API request.

Generating Access Token

MuleSoft provides a separate API for generating access token. To do that, you need to pass your username and password in the request body.

You can use curl to generate the token:

Plain Text
xxxxxxxxxx
1
 
1
$ curl -H "Content-Type: application/json" -X POST -d '{"username":"<<Anypoint_Username>>","password":"<<Anypoint_Password>>"}' https://anypoint.mulesoft.com/accounts/login


Response

JSON
xxxxxxxxxx
1
 
1
{
2
"access_token": "0cf70dc0-1982-42b5-8140-836048c15ce8",
3
"token_type": "bearer",
4
"redirectUrl": "/home/"
5
}


You can also use Postman to generate the token.

Generating token with Postman

Generating token with Postman

Applying the Policy Using API Manager API

First, we need to identify what attributes we need to pass for applying the JWT validation policy. Go to exchange and search for “JWT Validation Policy Template”.

https://anypoint.mulesoft.com/exchange/68ef9520-24e9-4cf2-b2f5-620025690913/jwt-validation/

Assets provided by MuleSoft

Assets provided by MuleSoft


Click on API Gateway JWT Validation Template. 

API Gateway JWT Validation template

API Gateway JWT Validation template

Now, download the Policy definition, which will give you a YAML file that will provide all attributes that we need to pass.

YAML
 




xxxxxxxxxx
1
215


 
1
id: jwt-validation
2
name: JWT Validation
3
supportedPoliciesVersions: '>=v1'
4
description: |
5
  All calls to the API must include a Json Web Token (JWT) to use the API.
6

          
7
  This policy will require updates to the RAML definition in order to function.
8
category: Security
9
type: system
10
encryptionSupported: true
11
violationCategory: authentication
12
resourceLevelSupported: true
13
standalone: true
14
requiredCharacteristics: []
15
providedCharacteristics:
16
  - JWT Validation
17
configuration:
18
  - propertyName: jwtOrigin
19
    name: JWT origin
20
    description: Origin of the JWT.
21
    options:
22
    - name: HTTP Bearer Authentication Header
23
      value: httpBearerAuthenticationHeader
24
    - name: Custom Expression
25
      value: customExpression
26
    type: radio
27
    defaultValue: httpBearerAuthenticationHeader
28
    optional: false
29
    sensitive: false
30
    allowMultiple: false
31
  - propertyName: jwtExpression
32
    name: Token Expression
33
    description: Mule Expression to be used to extract the JWT from API requests
34
    type: expression
35
    defaultValue: "#[attributes.headers['jwt']]"
36
    optional: false
37
    sensitive: false
38
    allowMultiple: false
39
    dependsOnKey: jwtOrigin
40
    dependsOnValue: customExpression
41
    dependsOnUnfulfilledDefaultValue: "#[attributes.headers['jwt']]"
42

          
43
  - propertyName: signingMethod
44
    name: JWT Signing Method
45
    description: Specifies the method to be used by the policy to decode the JWT.
46
    options:
47
    - name: RSA
48
      value: rsa
49
    - name: HMAC
50
      value: hmac
51
    - name: None
52
      value: none
53
    type: radio
54
    optional: false
55
    defaultValue: rsa
56
    sensitive: false
57
    allowMultiple: false
58
  - propertyName: signingKeyLength
59
    name: JWT Signing Key Length
60
    description: |
61
      Specifies the length of the key to be in the signing method for HMAC, or the SHA algorithm used for RSA.
62
      Ignore this field if the JWT Signing Method was set to None.
63
    options:
64
    - name: 256
65
      value: 256
66
    - name: 384
67
      value: 384
68
    - name: 512
69
      value: 512
70
    type: radio
71
    optional: false
72
    defaultValue: 256
73
    sensitive: false
74
    allowMultiple: false
75

          
76
  - propertyName: jwtKeyOrigin
77
    name: JWT Key origin
78
    description: |
79
      Origin of the JWT Key.
80
      The JWKS option is only supported if the JWT Signing Method was set to RSA.
81
      Ignore this field if the JWT Signing Method was set to None.
82
    options:
83
    - name: Text
84
      value: text
85
    - name: JWKS
86
      value: jwks
87
    type: radio
88
    defaultValue: text
89
    optional: false
90
    sensitive: false
91
    allowMultiple: false
92
  - propertyName: textKey
93
    description: |
94
      The shared secret in case the JWT Signing Method is set to HMAC.
95
      Include the public PEM key without -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- for RSA signing.
96
      Ignore this field if the JWT Signing Method was set to None.
97
    name: JWT Key
98
    type: string
99
    sensitive: true
100
    optional: false
101
    defaultValue: your-(256|384|512)-bit-secret/your-public-pem-certificate
102
    dependsOnKey: jwtKeyOrigin
103
    dependsOnValue: text
104
    dependsOnUnfulfilledDefaultValue: your-(256|384|512)-bit-secret
105
  - propertyName: jwksUrl
106
    name: JWKS Url
107
    description: |
108
      The Url to the JWKS server that contains the public keys for the signature validation.
109
      Ignore this field if the JWT Signing Method was set to None.
110
    type: string
111
    optional: false
112
    defaultValue: http://your-jwks-service.example:80/base/path
113
    dependsOnKey: jwtKeyOrigin
114
    dependsOnValue: jwks
115
    dependsOnUnfulfilledDefaultValue: http://your-jwks-service.example:80/base/path
116
  - propertyName: jwksServiceTimeToLive
117
    name: JWKS Caching TTL (minutes)
118
    description: |
119
      The amount of time, in minutes, that the JWKS will be considered valid. Once the JWKS has expired,
120
      it will have to be retrieved again. Default value is 1 hour.
121
      Ignore this field if the JWT Signing Method was set to None.
122
    type: int
123
    optional: true
124
    defaultValue: 60
125
    minimumValue: 0
126
    maximumValue: 2147483647
127
    dependsOnKey: jwtKeyOrigin
128
    dependsOnValue: jwks
129
    dependsOnUnfulfilledDefaultValue: 60
130

          
131
  - propertyName: skipClientIdValidation
132
    name: Skip Client Id Validation
133
    description: Skips client application's API contract validation.
134
    type: boolean
135
    optional: false
136
    defaultValue: false
137
    allowMultiple: false
138
  - propertyName: clientIdExpression
139
    name: Client ID Expression
140
    description: Expression to obtain the Client ID from the request in order to validate it.
141
    type: expression
142
    optional: false
143
    defaultValue: '#[vars.claimSet.client_id]'
144
    allowMultiple: false
145
    dependsOnKey: skipClientIdValidation
146
    dependsOnValue: false
147
    dependsOnUnfulfilledDefaultValue: '#[vars.claimSet.client_id]'
148

          
149
  - propertyName: validateAudClaim
150
    name: Validate Audience Claim
151
    description: The JWT will be valid only if the aud claim contains at least one audiences value defined here.
152
    type: boolean
153
    optional: false
154
    defaultValue: false
155
  - propertyName: mandatoryAudClaim
156
    description: If a claim is marked as mandatory, and this claim is not present in the incoming JWT, the request will fail.
157
    name: Audience Claim Mandatory
158
    type: boolean
159
    optional: false
160
    defaultValue: false
161
    dependsOnKey: validateAudClaim
162
    dependsOnValue: true
163
    dependsOnUnfulfilledDefaultValue: false
164
  - propertyName: supportedAudiences
165
    name: Audience Claim Values
166
    description: Comma separated list of supported audience values.
167
    type: string
168
    optional: false
169
    defaultValue: aud.example.com
170
    dependsOnKey: validateAudClaim
171
    dependsOnValue: true
172
    dependsOnUnfulfilledDefaultValue: aud.example.com
173

          
174
  - propertyName: mandatoryExpClaim
175
    name: Expiration Claim Mandatory
176
    description: If a claim is marked as mandatory, and this claim is not present in the incoming JWT, the request will fail.
177
    type: boolean
178
    optional: false
179
    defaultValue: false
180

          
181
  - propertyName: mandatoryNbfClaim
182
    name: Not Before Claim Mandatory
183
    description: If a claim is marked as mandatory, and this claim is not present in the incoming JWT, the request will fail.
184
    type: boolean
185
    optional: false
186
    defaultValue: false
187

          
188
  - propertyName: validateCustomClaim
189
    description: The JWT will be valid only if all DataWeave expressions defined here are valid.
190
    name: Validate Custom Claim
191
    type: boolean
192
    optional: false
193
    defaultValue: false
194
  - propertyName: mandatoryCustomClaims
195
    name: Mandatory Custom Claim Validations
196
    description: |
197
      Specify the Claim Name and the literal to validate the value of a claim E.g foo : fooValue
198
      If more complex validations must be made or the claim value is an array or an object, provide Claim Name and DataWeave expression to validate the value of a claim. E.g. foo : #[vars.claimSet.foo == 'fooValue']
199
      If a claim is marked as mandatory and this claim is not present in the incoming jwt, the request will fail.
200
    type: keyvalues
201
    optional: true
202
    allowMultiple: true
203
    dependsOnKey: validateCustomClaim
204
    dependsOnValue: true
205
  - propertyName: nonMandatoryCustomClaims
206
    name: Non Mandatory Custom Claim Validations
207
    description: |
208
      Specify the Claim Name and the literal to validate the value of a claim E.g foo : fooValue
209
      If more complex validations must be made or the claim value is an array or an object, provide Claim Name and DataWeave expression to validate the value of a claim. E.g. foo : #[vars.claimSet.foo == 'fooValue']
210
      If a claim is marked as non-mandatory and this claim is not present in the incoming jwt, the request will not fail.
211
    type: keyvalues
212
    optional: true
213
    allowMultiple: true
214
    dependsOnKey: validateCustomClaim
215
    dependsOnValue: true



Now, you can use CURL to apply a policy by calling policies API.

Plain Text
 




xxxxxxxxxx
1
29


 
1
curl -X POST \
2
  https://anypoint.mulesoft.com/apimanager/api/v1/organizations/:organizationId/environments/:environmentId/apis/:apiInstanceId/policies \
3
  -H 'authorization: Bearer 0cf70dc0-1982-42b5-8140-836048c15ce8 \
4
  -H 'content-type: application/json' \
5
  -d '{
6
   "configurationData":{
7
     "jwtOrigin":"httpBearerAuthenticationHeader",
8
     "jwtExpression":"#[attributes.headers['jwt']]",
9
     "signingMethod":"rsa",
10
     "signingKeyLength":"256",
11
     "jwtKeyOrigin":"jwks",
12
     "textKey":"Text Data",
13
     "jwksUrl":"https://example.okta.com/oauth2/default/v1/keys",
14
     "jwksServiceTimeToLive":60,
15
     "skipClientIdValidation":true,
16
     "clientIdExpression":"#[vars.claimSet.client_id]",
17
     "validateAudClaim":false,
18
     "mandatoryAudClaim":false,
19
     "supportedAudiences":"aud.example.com",
20
     "mandatoryExpClaim":false,
21
     "mandatoryNbfClaim":false,
22
     "validateCustomClaim":true,
23
     "mandatoryCustomClaims":[{"key":"scope","value":"#[vars.claimSet.scope='API_READ']"}]
24
     },
25
   "policyTemplateId":"jwt-validation",
26
   "assetId":"jwt-validation",
27
   "assetVersion":"1.1.2",
28
   "groupId":"68ef9520-24e9-4cf2-b2f5-620025690913"
29
}'



You need to pass organizationId, environmentId and apiId that we have fetched above. Currently, we have a placeholder in the above call to the policies API.

You can also use Postman also to call the policies API.

Calling policies API with Postman

Calling policies API with Postman


JSON
 




xxxxxxxxxx
1
25


 
1
{
2
   "configurationData":{
3
     "jwtOrigin":"httpBearerAuthenticationHeader",
4
     "jwtExpression":"#[attributes.headers['jwt']]",
5
     "signingMethod":"rsa",
6
     "signingKeyLength":"256",
7
     "jwtKeyOrigin":"jwks",
8
     "textKey":"Text Data",
9
     "jwksUrl":"https://example.okta.com/oauth2/default/v1/keys",
10
     "jwksServiceTimeToLive":60,
11
     "skipClientIdValidation":true,
12
     "clientIdExpression":"#[vars.claimSet.client_id]",
13
     "validateAudClaim":false,
14
     "mandatoryAudClaim":false,
15
     "supportedAudiences":"aud.example.com",
16
     "mandatoryExpClaim":false,
17
     "mandatoryNbfClaim":false,
18
     "validateCustomClaim":true,
19
     "mandatoryCustomClaims":[{"key":"scope","value":"#[vars.claimSet.scope='API_READ']"}]
20
     },
21
   "policyTemplateId":"jwt-validation",
22
   "assetId":"jwt-validation",
23
   "assetVersion":"1.1.2",
24
   "groupId":"68ef9520-24e9-4cf2-b2f5-620025690913"
25
}



This is a very useful utility when you need to apply policies via CI/CD, and now, you know how to apply JWT validation policy using the API Manager API.

API JWT (JSON Web Token) MuleSoft

Opinions expressed by DZone contributors are their own.

Related

  • Attribute Based Access Control for Mulesoft APIs
  • Authorizing the MuleSoft API Using AWS Cognito User Pool and Mule JWT Validation Policy
  • Generic and Dynamic API: MuleSoft
  • A Practical Guide to Securing NodeJS APIs With JWT

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!