{{announcement.body}}
{{announcement.title}}

Mule 4 - Client ID Enforcement

DZone 's Guide to

Mule 4 - Client ID Enforcement

In this article, we discuss how to implement client Id enforcement in a Mule application to better manage our API security.

· Integration Zone ·
Free Resource

Hello, everyone! Today, I will try to explain in detail how to implement Client Id Enforcement in Mule 4. The purpose of the Client ID Enforcement policy is to allow access only to authorized client applications.

The Client Id Enforcement policy is used to restrict access to a protected resource by allowing requests only from registered client applications. The policy ensures that each request, which contains valid client credentials is able to access protected resources.

The client application has to be registered on the AnyPoint platform to generate client credentials (client_Id  and  client_secret). After client application registration, all subsequent requests have to pass client_id and client_secret, as part of the request while invoking an API.

There are some policies which internally enforce client application credentials. Those are:

  • Rate Limiting - SLA-Based Policies.
  • OAuth 2.0 Access Token Enforcement. 
  • JWT Validation

Before a client application is allowed to consume an API protected by a Client ID Enforcement policy, the client application must request access to the API. After an approved contract exists between the client application and the API, every request must include the client application credentials, according to how the policy is configured.

For example, if the policy is configured to expect a client ID and client secret as headers, the application must send those credentials in the request, using the corresponding headers:

You may also like: Four Ways to Keep Kubernetes’ Secrets Secret.

Obtaining Credentials Using HTTP Headers

#[attributes.headers.['client_id']]

#[attributes.headers.['client_secret']]

In this example, the policy is configured to expect two headers: client_id and client_secret, with the pair of credentials. The policy is flexible to allow other types of headers also. This is the default configuration for the policy.

Obtaining Credentials Using HTTP Query Parameters

#[attributes.queryParams.'client_id']

#[attributes.queryParams.'client_secret']

The requester must send the two specified query parameters with the request. Although this is a supported configuration, it poses possible security risks. The recommended method is to use headers.

Obtaining Credentials Using HTTP Request Payload

#[payload.client_id]

#[payload.client_secret]

Although you can configure the policy to obtain the credentials from the request payload, this option is not recommended because it is harder to reflect in the API specification.

Client ID based policies by default expect to obtain the client ID and secret as headers. To enforce this in the API definition a trait can be defined in RAML as shown below.

traits:
  client-id-required:
    headers:
      client_id:
        type: string
      client_secret:
        type: string
    responses:
      401:
        description: Unauthorized or invalid client application credentials
      500:
        description: Bad response from authorization server, or WSDL SOAP Fault error

This trait must then be applied to the resource or methods using the is RAML attribute.

/products:
  get:
    is: [client-id-required]
    description: Gets a list of all the inventory products.

 

 

The following are the steps we will take to create the project and apply our policy: 

Design API using RAML

YAML
 




x
47


 
1
#%RAML 1.0
2
title: product-service
3
version: v1
4
description: Product Service 
5
protocols: [HTTP, HTTPS]
6
documentation:
7
  - title: Product Detail Service API
8
    content: Product DetailAPI Content
9
 
          
10
traits:
11
  client-id-required:
12
    headers:
13
      client_id:
14
        type: string
15
        description: client Id provided by API Manager
16
        required: true
17
      client_secret:
18
        type: string
19
        required: true
20
        description: The Client secret key provided by the API Manager
21
    responses:
22
      401:
23
        description: Unauthorized or invalid client application credentials
24
      500:
25
        description: Bad response from authorization server, or WSDL SOAP Fault error
26
 
          
27
types:
28
  ProductDetail:
29
    type: object
30
    properties:
31
      productId?: number
32
      productName?: string
33
      productPrice?: number
34
 
          
35
 
          
36
/products:
37
  description: Retrieve All Orders
38
  post:
39
    is: 
40
      - client-id-required
41
    description: Get Order Information by CLient Id
42
    responses:
43
      200:
44
        body:
45
          application/json:
46
            type: ProductDetail []
47
            example: !include examples/all-products.json



all-products.json

JSON
 




xxxxxxxxxx
1
17


 
1
[
2
  {
3
    "productId": 1001,
4
    "productName": "Apple",
5
    "productPrice" : 300
6
  },
7
  {
8
    "productId": 1002,
9
    "productName": "Google",
10
    "productPrice" : 1000
11
  },
12
  {
13
    "productId": 1003,
14
    "productName": "Samsung",
15
    "productPrice" : 100
16
  }
17
]



Publish API in exchange

In the Anypoint platform, we publish API to the exchange.

Create an API specification project in API Manager using published API in exchange (make note of API id)

After the API is published in Anypoint, create an API Specification Project

Click Manage API from Exchange

Managing API

Managing API

Applying Client Id

Applying Client Id

Select API (I have create product service API- product-service) and save it. Once we save the API specification project, it will create an API Instance Id; please make note of it.

Getting API instance Id

Getting API instance Id

Now, check your client policies on policies -> Apply New Policy than select Client Id Enforcement policy. After you select Client Id Enforcement Policy, click on Configure Policy.

Selecting policy

Selecting policy

Do take note of how are we passing client_id and client_secret, and click the apply button.

Getting client Id and secret

Getting client Id and secret

Create a new mule project in AnyPoint Studio using API specification from exchange

Now, right-click on the project explorer canvas and click create a new mule project and select API specification from the exchange. Select API and click the finish button to create a Mule project.

Creating a Mule project

Creating a Mule project

This will create a default Mule flow using the API Kit router. Now, run the project in local Mule runtime.

Test the application using Postman or an equivalent testing tool.

Testing with Postman

Testing with Postman

As per API specification, client_id and client_secret must be passed through a request header. So, we are getting an error here. Once we start passing client credentials, we get a successful response; however, we have not applied our client id enforcement policy yet.

Testing with Postman

Testing with Postman

Using API discovery, apply API ID to the project

Click on Global Elements -> create and search for API Autodiscovery

Enter API ID (from Mule Anypoint platform policy application created in the previous step) and select the main flow and click on the ok button. Save the project.

API autodiscovery

API autodiscovery

Deploy the project on CloudHub.

Deploying the project on GitHub

Deploying the project on CloudHub

After we deploy the application and run it from Postman, we get the following error, as client id enforcement policy has been applied, and we are not passing the correct value of client_id and client_secret.

Invalid client Id

Invalid client Id

So, we have to create a proxy application and create client_id and client_secret from that. Here are the steps for the same.

In the API Manager, click on the policy version and then click on "View API in exchange" on right hand side.

View API

View API

Here, click on three vertical dots and request access.

Requesting access

Requesting access

Create an application, select the API version, and click on Request Access. It will give you a popup with client_id and client_secret.

Requesting access

Requesting access

Make note of those client_id and client_secret values and pass them as part of the Http header.

Passing secret and id as headers

Passing secret and id as headers

Once we pass the correct values of client_id and client_secret, we are able to receive a successful response.


Further Reading

Topics:
api ,authorization ,client id ,client secret ,mule 4 ,secret management ,security

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}