Create Custom API Policy to validate Client Provider (OKTA) access token

Reading Time: 3 minutes

Overview

In this blog, I will try to showcase how you can create a custom API policy and its implementation.

Use-case:

We would like to validate the Bearer token acquired by other apps (e.g., Web Apps, Mobile Apps) using the OKTA server’s introspection URL.

Components used :

MuleSoft Anypoint Platform ( Maven, Anypoint Studio ) POSTMAN for REST API call.

Steps :

(1) Create Metadata yaml file which we will helpful to generate UI for API Policy rendering or display.

It will take three inputs from users. Ex: introspection Url, Client ID, Client Secret

  • Introspection url : Okta Token Validation/Introspection URL
  • Client ID/Secret: Okta server provides credentials for machine-to-machine call ( MuleSoft Anypoint Platform to Okta Server )

custom-okta-introspection-policy-metadata.yaml

(2) Create JSON Schema json file which we will helpful to validate input details from User.

custom-okta-introspection-policy-schema.json

(3) The API Policy application :

custom-okta-introspection-policy.yaml ( as below )

pom.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<project xmlns=”http://maven.apache.org/POM/4.0.0
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd“>
<modelVersion>4.0.0</modelVersion>

<groupId>com.yourcompany</groupId>
<artifactId>ap-custom-okta-introspection-policy</artifactId>
<version>1.0.10</version>

<name>ap-custom-okta-introspection-policy</name>
<description>ap-custom-okta-introspection-policy</description>

<packaging>mule-policy</packaging>

<properties>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
<exchange.url>https://maven.anypoint.mulesoft.com/api/v3/organizations/{project.groupId}/maven</exchange.url>
<http.policy.transform.extension>3.2.0</http.policy.transform.extension>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<execution>
<id>upload-template</id>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<repositoryId>anypoint-exchange-v3</repositoryId>
<url>${exchange.url}</url>
<file>${project.basedir}/${project.artifactId}.yaml</file>
<generatePom>false</generatePom>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>yaml</packaging>
<classifier>policy-definition</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>


<dependencies>
<! — This extension allows to easily update HTTP attributes from a policy →
<! — Full documentation: https://docs.mulesoft.com/api-manager/2.x/http-policy-transform →
<dependency>
<groupId>com.mulesoft.anypoint</groupId>
<artifactId>mule-http-policy-transform-extension</artifactId>
<version>${http.policy.transform.extension}</version>
<classifier>mule-plugin</classifier>
<! — HTTP Connector is excluded to avoid packaging it with the policy, since the application’s HTTP connector is used →
<exclusions>
<exclusion>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
</exclusion>
</exclusions>
</dependency>


<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-json-module</artifactId>
<version>2.5.0</version>
<classifier>mule-plugin</classifier>
</dependency>

<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>1.10.3</version>
<classifier>mule-plugin</classifier>
<! — <scope>provided</scope> →
</dependency>

</dependencies>

<repositories>
<repository>
<id>anypoint-exchange-v3</id>
<name>Anypoint Exchange</name>
<url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${project.groupId}/maven</url>
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-releases</id>
<name>MuleSoft Releases Repository</name>
<url>https://repository.mulesoft.org/releases/</url>
<layout>default</layout>
</repository>
</repositories>


<pluginRepositories>
<pluginRepository>
<id>mule-plugin</id>
<name>Mule Repository</name>
<url>https://repository.mulesoft.org/nexus/content/repositories/public/</url>
</pluginRepository>
</pluginRepositories>


<distributionManagement>
<repository>
<id>anypoint-exchange-v3</id>
<name>Exchange Repository</name>
<url>${exchange.url}</url>
<layout>default</layout>
</repository>
</distributionManagement>

</project>

mule-artifact.json [ This will support Mule Version 4.9.0 and JDK 17 ]

{
“minMuleVersion” : “4.9.0”,
“javaSpecificationVersions”: [“17”]
}

template.xml [ This is the implementation of the policy ]

Note:

It will make a RESTAPI call to Okta introspection url with provided client id/secret.

<?xml version=”1.0″ encoding=”UTF-8″?>
<mule xmlns=”http://www.mulesoft.org/schema/mule/core
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance
xmlns:http=”http://www.mulesoft.org/schema/mule/http
xmlns:http-policy=”http://www.mulesoft.org/schema/mule/http-policy
xmlns:http-transform=”http://www.mulesoft.org/schema/mule/http-policy-transform
xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation
xsi:schemaLocation=”
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/http-policy http://www.mulesoft.org/schema/mule/http-policy/current/mule-http-policy.xsd
http://www.mulesoft.org/schema/mule/http-policy-transform http://www.mulesoft.org/schema/mule/http-policy-transform/current/mule-http-policy-transform.xsd“>

<http-policy:proxy name=”{{{policyId}}}-custom-policy”>
<http-policy:source>
<try>
<set-variable variableName=”access1Token” value=”#[ if(attributes.headers[‘Authorization’] != null) ( (attributes.headers[‘Authorization’]) replace ‘Bearer ‘ with ‘’ ) else ( ‘’ ) ]”/>
<set-variable variableName=”access1ClientId” value=”{{{clientId}}}” />
<set-variable variableName=”access1ClientSecret” value=”{{{clientSecret}}}” />

<set-variable variableName=”access1Authorization” value=”#[ ‘Basic ‘ ++ dw::core::Binaries::toBase64( (vars.access1ClientId ++ ‘:’ ++ vars.access1ClientSecret) as String as Binary {encoding: ‘UTF-8’} ) ]”/>
<set-payload value=”#[‘token=’ ++ (vars.access1Token default ‘’) ++ ‘&amp;token_type_hint=access_token’]” mimeType=”application/x-www-form-urlencoded” />

<! — Call Okta introspect endpoint →
<http:request method=”POST” doc:name=”Call Okta Introspect” url=”{{{introspectionUrl}}}” sendBodyMode=”ALWAYS”>

<http:headers ><![CDATA[#[output application/json — —
{
“Content-Type” : “application/x-www-form-urlencoded”,
“Authorization” : vars.access1Authorization
}]]]></http:headers>

</http:request>

<choice>
<when expression=”#[ (payload.active != true) ]” >
<http-transform:set-response statusCode=”401″>
<http-transform:body><![CDATA[#[output application/json — — {
“error”: “The access token is not valid or life is ended.”
}]]]></http-transform:body>
</http-transform:set-response>
</when>
<otherwise>
<http-policy:execute-next/>
</otherwise>
</choice>

<error-handler>
<on-error-continue logException=”true”>
<http-transform:set-response statusCode=”401″>
<http-transform:body><![CDATA[#[output application/json — — {
“error”: “The access token is not valid or life is ended.”
}]]]></http-transform:body>
</http-transform:set-response>
</on-error-continue>
</error-handler>

</try>
</http-policy:source>
</http-policy:proxy>
</mule>

Published API Policy in Exchange

Published version of custom API Policy

Upload the custom API JAR file — Implementation mule plugin for API

Note: The User can upload the artifacts manually from Anypoint Exchange, or the Mule Maven plug-in can be used to publish this policy into Exchange.

Go to the particular API where you would like to apply this custom policy.

Search the policy name or type (as this is a custom policy )

Search Custom Policy from API Manager for the particular API

Apply API Policy from API Manager

Validation:

  • Get access_token for your WebApp/Mobile App [ Client Grant Type: client_credentials or any other mechanism ]
  • That particular access_token will be passed as an Authorisation header with Bearer <<access_token>> tag for the particular endpoint that is being exposed from the Mule API.
  • Custom API policy will retrieve access_token from Authorisation and validate against the Okta Server, which will return active as true or false.
  • If false, then an error response will be returned with status Code 401 (Unauthorised)
  • If true, then an actual endpoint will be invoked, and that response will be returned.

Conclusion:

This will be useful when you want to publish a custom policy for your specific requirements, where you won’t find an OOTB policy.

Let’s get started.
Reach out to us
for a conversation!

Fill in the form below and we will get back to you

Don’t Miss Out!

Stay in the loop on the latest in the wild world of technology and AI. Subscribe for updates on our newest articles and exclusive events, it just Makes Sense!