Author: Sanket Kangle
In this article, we will look at how to enforce client_id and cleint_secret to an endpoint without
Having access to an API manager or any third-party application like OKATA.
The basic idea follows the following steps:
- Add client_id and clident_secret traits in your RAML
- Create an auth flow that will validate client id and secret
- Add a flow reference just after the listener component of the API interface
- Add expected client id and client secret in a properties file in an encrypted format
- Add the required global configurations and global properties in the config file.
Let us see the same with a demo now.
Step 1: Add client_id and clident_secret traits in your RAML
Add client_id and client_secret headers as traits in your RAML in the Design center, as shown in the exhibit below.
Step 2: Create an auth flow that will validate the client id and secret
We will add a choice router on canvas. In the when section, we will check the credentials provided by request with the required credentials. If it matches, we go ahead. If it does not match, we will raise an error stating credentials are invalid.
Create a flow as shown in the following exhibit
The component will have following Mule properties
The inline dataweave expression in above exhibit is listed below:
(attributes.headers.client_id == p(‘secure::client.id’)) and (attributes.headers.client_secret == p(‘secure::client.secret’)) |
In the default section, raise an error stating credentials are invalid.
XML for this flow is as following
<?xml version=”1.0″ encoding=”UTF-8″?> <mule xmlns=”http://www.mulesoft.org/schema/mule/core” xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd”> <flow name=”authFlow” doc:id=”66999bb6-4516-4e18-a9ce-9738747c45b4″ > <choice doc:name=”Choice” doc:id=”3cf2ff9c-f441-4481-b4b2-06fb2014273b” > <when expression=”#[(attributes.headers.client_id == p(‘secure::client.id’)) and (attributes.headers.client_secret == p(‘secure::client.secret’))]”> <logger level=”INFO” doc:name=”Logger” doc:id=”677d24c7-5a07-4b9d-9cab-b545bd82d282″ message=”Auth Success”/> </when> <otherwise > <set-payload value=”Credentials Incorrect” doc:name=”Set Payload” doc:id=”de7ba12f-a225-450f-b8c1-c227ad88c219″ /> <raise-error doc:name=”Raise error” doc:id=”29126520-209d-41f3-8280-4f43a8c8d865″ type=”ANY” description=”Credentials Incorrect”/> </otherwise> </choice> </flow></mule> |
Â
Step 3: Add a flow reference just after the listener component of the API interface
This flow reference will refer to the auth flow created in step 1 above. It should look something like the exhibit below.
Note: this api specification is created using Design Center and imported to the studio. If you are not having the api interface, you can add a listener in your implementation flow directly and add this flow reference just after that listener
This endpoint goes to a demo flow as shown in the exhibit below.
XML for the same is as below:
<?xml version=”1.0″ encoding=”UTF-8″?> <mule xmlns:http=”http://www.mulesoft.org/schema/mule/http” xmlns=”http://www.mulesoft.org/schema/mule/core” xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsdhttp://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd”> <flow name=”auth-demoFlow” doc:id=”d89f61f7-d868-4c61-8868-acf90f4fe5fa” > <logger level=”INFO” doc:name=”flow start” doc:id=”2798f992-9d6a-4ce0-af18-17a3c5fb0396″ message=’flow start’/> <set-payload value=”authentication successful” doc:name=”Set Payload” doc:id=”c2e55209-fa35-4ccd-82d4-97031885a06a” /> <logger level=”INFO” doc:name=”flow end” doc:id=”735a7028-28df-4d43-914c-fa45dc5afadf” message=”flow end”/> </flow></mule> |
Â
Step 3: Add expected client id and client secret in a properties file in encrypted format
Â
Step 4: Add the required global configurations and global properties in the config file
We need to add the following configurations for this demo to work.
Let’s have a look at detailed configuration properties of each element.
- Secure Properties Config
- Configuration properties:
- Global property-1
- Global property – 2
The XML for the same is as below:
<?xml version=”1.0″ encoding=”UTF-8″?> <mule xmlns:secure-properties=”http://www.mulesoft.org/schema/mule/secure-properties” xmlns:http=”http://www.mulesoft.org/schema/mule/http” xmlns=”http://www.mulesoft.org/schema/mule/core” xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsdhttp://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsdhttp://www.mulesoft.org/schema/mule/secure-properties http://www.mulesoft.org/schema/mule/secure-properties/current/mule-secure-properties.xsd”> <http:listener-config name=”HTTP_Listener_config” doc:name=”HTTP Listener config” doc:id=”32b89a43-9b73-4da8-8eb1-9cd9fc63aa0c” > <http:listener-connection host=”0.0.0.0″ port=”8081″ /> </http:listener-config> <secure-properties:config name=”Secure_Properties_Config” doc:name=”Secure Properties Config” doc:id=”66d180cd-dc92-4780-b82e-2fc6275974d0″ file=”properties/${env}.yaml” key=”${key}” /> <configuration-properties doc:name=”Configuration properties” doc:id=”6aa3c11c-0121-4a0c-a7a7-78a75faac0df” file=”properties/${env}.yaml” /> <global-property doc:name=”Global Property” doc:id=”7976c4c5-6419-4e82-9087-61c9391de508″ name=”env” value=”dev” /> <global-property doc:name=”Global Property” doc:id=”42b4f294-1ddf-4d37-bfd2-333f1e387322″ name=”key” value=”Apisero@12345678″ /></mule> |
Now we are ready with the client id and secret enforcing flows, let’s deploy the application and test it.
If an application is not getting deployed successfully, check the error and fix it. Once deployed, go ahead in postman and test the application.
The postman request should look something like below
In request, add actual values of client id and secret that you have encoded and put in the properties file. When you hit send, you should get a success message like below
You can also validate the following scenarios:
- When client_id or secrete not provided
- Wrong client_id or sectere provided
In both scenarios, you should get the following response
This is how you can enforce basic client id and secret without API managers and any third-party app.