Skip to content

integon/wso2-mi-jwt-validator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

107 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wso2-mi-jwt-validator

The wso2-mi-jwt-validator is a custom handler and mediator for the WSO2 Micro Integrator. This class validates JWT tokens against one or more JWKS endpoints and can be used as either a custom handler or a custom mediator.

Latest version: 1.4.0 on Maven Central Repository

Table of Contents

Setup

With pom.xml

Add the following dependencies to your pom.xml file:

<dependency>
  <groupId>io.integon.wso2mi.jwt</groupId>
  <artifactId>wso2-mi-jwt-validator</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>10.3</version>
</dependency>

The wso2-mi-jwt-validator relies on the nimbus-jose-jwt library for JWT validation.

Without pom.xml

Add these JAR files to the MI directory "/home/wso2carbon/wso2mi-{version}/lib":

  • wso2-mi-jwt-validator-1.4.0.jar (or latest version)
  • nimbus-jose-jwt-10.3.jar (or latest version)

Download links:

Usage

Available Properties (Custom Handler)

Parameter Name Description Examples
jwtHeader Header name containing the JWT Token. <property name="jwtHeader" value="Authorization"/>

<property name="jwtHeader" value="env:JWT_HEADER"/>
iatClaim Maximum token age in seconds. <property name="iatClaim" value="1800"/>

<property name="iatClaim" value="env:IAT_CLAIM"/>

<property name="iatClaim" value=""/>
issClaim Regex for issuer claim. Multiple values: ^(myiss1|myiss2|myiss3)$ <property name="issClaim" value="issuer"/>

<property name="issClaim" value="env:ISS_CLAIM"/>

<property name="issClaim" value=""/>
subClaim Expected subject claim. <property name="subClaim" value="subject"/>

<property name="subClaim" value="env:SUB_CLAIM"/>

<property name="subClaim" value=""/>
audClaim Expected audience claim. <property name="audClaim" value="audience"/>

<property name="audClaim" value="env:AUD_CLAIM"/>

<property name="audClaim" value=""/>
jtiClaim Set to "enabled" to verify token uniqueness using cache. <property name="jtiClaim" value="enabled"/>

<property name="jtiClaim" value="env:JTI_CLAIM"/>
customClaims Validate additional custom claims using a comma-separated list of key:regex pairs. Each claim must match its corresponding regular expression.
Format: claimName:regex,claimName2:regex2

Example for multiple allowed roles and locations: role:admin|manager,location:Zurich|Geneva|Bern
<property name="customClaims" value="role:admin|manager,location:Zurich|Geneva|Bern"/>

<property name="customClaims" value="env:CUSTOM_CLAIMS"/>
jwksEndpoint JWKS endpoint URL(s) or environment variable. Multiple endpoints use comma separation. <property name="jwksEndpoint" value="https://example.com/oauth2/jwks"/>

<property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
jwksTimeout Timeout in seconds for JWKS endpoint caching. <property name="jwksTimeout" value="30"/>

<property name="jwksTimeout" value="env:JWKS_TIMEOUT"/>
jwksRefreshTime Time in seconds after which the JWKS endpoint is refreshed. <property name="jwksRefreshTime" value="15"/>

<property name="jwksRefreshTime" value="env:JWKS_REFRESH_TIME"/>
forwardToken If 'true', decoded JWT payload is set as 'X-JWT' property. <property name="forwardToken" value="true"/>

<property name="forwardToken" value="env:FORWARD_TOKEN"/>

Note: All properties can be specified directly or via environment variables using the env: prefix.

Optional parameters:

  • All claim checks (iatClaim, issClaim, subClaim, audClaim, jtiClaim) - claims not specified will not be checked
  • jwksTimeout (default: 6000)
  • jwksRefreshTime (default: 3000)
  • forwardToken (default: false)

Available Properties (Custom Mediator)

Parameter Name Description Examples
jwtToken JWT token to validate. <property name="jwtToken" expression="$trp:Authorization"/>

<property name="jwtToken" expression="$ctx:jwt"/>
iatClaim Maximum token age in seconds. <property name="iatClaim" value="1800"/>

<property name="iatClaim" value="env:IAT_CLAIM"/>

<property name="iatClaim" value=""/>
issClaim Regex for issuer claim. Multiple values: ^(myiss1|myiss2|myiss3)$ <property name="issClaim" value="issuer"/>

<property name="issClaim" value="env:ISS_CLAIM"/>

<property name="issClaim" value=""/>
subClaim Expected subject claim. <property name="subClaim" value="subject"/>

<property name="subClaim" value="env:SUB_CLAIM"/>

<property name="subClaim" value=""/>
audClaim Expected audience claim. <property name="audClaim" value="audience"/>

<property name="audClaim" value="env:AUD_CLAIM"/>

<property name="audClaim" value=""/>
jtiClaim Set to "enabled" to verify token uniqueness using cache. <property name="jtiClaim" value="enabled"/>

<property name="jtiClaim" value="env:JTI_CLAIM"/>
customClaims Validate additional custom claims using a comma-separated list of key:regex pairs. Each claim must match its corresponding regular expression.
Format: claimName:regex,claimName2:regex2

Example for multiple allowed roles and locations: role:admin|manager,location:Zurich|Geneva|Bern
<property name="customClaims" value="role:admin|manager,location:Zurich|Geneva|Bern"/>

<property name="customClaims" value="env:CUSTOM_CLAIMS"/>
jwksEndpoint JWKS endpoint URL(s) or environment variable. Multiple endpoints use comma separation. <property name="jwksEndpoint" value="https://example.com/oauth2/jwks"/>

<property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
jwksTimeout Timeout in seconds for JWKS endpoint caching. <property name="jwksTimeout" value="30"/>

<property name="jwksTimeout" value="env:JWKS_TIMEOUT"/>
jwksRefreshTime Time in seconds after which the JWKS endpoint is refreshed. <property name="jwksRefreshTime" value="15"/>

<property name="jwksRefreshTime" value="env:JWKS_REFRESH_TIME"/>
forwardToken If 'true', decoded JWT payload is set as 'X-JWT' property. <property name="forwardToken" value="true"/>

<property name="forwardToken" value="env:FORWARD_TOKEN"/>
respond If 'true', mediator responds without triggering faultSequence. <property name="respond" value="true"/>

<property name="respond" value="env:RESPOND"/>

Note: All properties can be specified directly or via environment variables using the env: prefix.

Optional parameters:

  • All claim checks (iatClaim, issClaim, subClaim, audClaim, jtiClaim) - claims not specified will not be checked
  • jwksTimeout (default: 6000)
  • jwksRefreshTime (default: 3000)
  • forwardToken (default: false)
  • respond (default: false)

Examples

Engage JWT Handler for MI APIs

Basic JWKS URL Configuration

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="Authorization"/>
                  <property name="jwksEndpoint" value="https://apim.ch/oauth2/jwks"/>
            </handler>
      </handlers>
</api>

Environment Variable Configuration

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="env:JWT_HEADER"/>
                  <property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
            </handler>
      </handlers>
</api>

With Cache Configuration

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="Authorization"/>
                  <property name="jwksEndpoint" value="https://apim.ch/oauth2/jwks"/>
                  <property name="jwksTimeout" value="30"/>
                  <property name="jwksRefreshTime" value="15"/>
            </handler>
      </handlers>
</api>

With Claim Validation

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="Authorization"/>
                  <property name="jwksEndpoint" value="https://apim.ch/oauth2/jwks"/>
                  <property name="iatClaim" value="1800"/>
                  <property name="issClaim" value="issuer"/>
                  <property name="subClaim" value="subject"/>
                  <property name="audClaim" value="audience"/>
                  <property name="jtiClaim" value="enabled"/>
            </handler>
      </handlers>
</api>

With Claim Validation Using Environment Variables

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="Authorization"/>
                  <property name="jwksEndpoint" value="https://apim.ch/oauth2/jwks"/>
                  <property name="iatClaim" value="env:IAT_MAX_AGE"/>
                  <property name="issClaim" value="env:EXPECTED_ISSUER"/>
                  <property name="subClaim" value="env:EXPECTED_SUBJECT"/>
                  <property name="audClaim" value="env:EXPECTED_AUDIENCE"/>
                  <property name="jtiClaim" value="env:JTI_CHECK"/>
            </handler>
      </handlers>
</api>

Multiple JWKS Endpoints

<api context="/jwtHealth" name="jwt-health-api" xmlns="http://ws.apache.org/ns/synapse">
      <resource methods="GET" uri-template="/">
            ...
      </resource>
      <handlers>
            <handler class="io.integon.JwtAuthHandler">
                  <property name="jwtHeader" value="Authorization"/>
                  <property name="jwksEndpoint" value="https://apim.ch/oauth2/jwks,https://apim-test.ch/oauth2/jwks"/>
            </handler>
      </handlers>
</api>

Engage JWT Mediator for Micro Integrator

Basic Configuration

<proxy xmlns="http://ws.apache.org/ns/synapse" name="jwt-auth-mi" transports="http https" startOnLoad="true">
      <description>JWT Mediator Test Proxy</description>
      <target>
            <inSequence>
            <propertyGroup name="jwt-auth-mi">
                  <property name="jwtToken" expression="$trp:Authorization"/>
                  <property name="jwksEndpoint" value="https://apim-dev.ch/oauth2/jwks"/>
            </propertyGroup>
            <class name="io.integon.JwtAuthMediator"/>
            <!-- Your sequence continues here -->
            </inSequence>
            <faultSequence>
                  <log level="custom" category="ERROR">
                        <property name="jwt-auth-mi" value="faultSequence" />
                        <property name="ERROR_CODE" expression="$ctx:ERROR_CODE"/>
                        <property name="ERROR_MESSAGE" expression="$ctx:ERROR_MESSAGE"/>
                  </log>
            <property name="HTTP_SC" expression="$ctx:ERROR_CODE" scope="axis2"/>
                  <respond/>	
            </faultSequence>
      </target>
</proxy>

With Environment Variables

<proxy xmlns="http://ws.apache.org/ns/synapse" name="jwt-auth-mi" transports="http https" startOnLoad="true">
      <description>JWT Mediator Test Proxy</description>
      <target>
            <inSequence>
            <propertyGroup name="jwt-auth-mi">
                  <property name="jwtToken" expression="$trp:Authorization"/>
                  <property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
                  <property name="iatClaim" value="env:IAT_MAX_AGE" />
                  <property name="issClaim" value="env:EXPECTED_ISSUER" />
                  <property name="subClaim" value="env:EXPECTED_SUBJECT" />
                  <property name="audClaim" value="env:EXPECTED_AUDIENCE" />
                  <property name="jtiClaim" value="env:JTI_CHECK" />
            </propertyGroup>
            <class name="io.integon.JwtAuthMediator"/>
            <!-- Your sequence continues here -->
            </inSequence>
            <faultSequence>
                  <!-- Error handling -->
            </faultSequence>
      </target>
</proxy>

With Cache Configuration

<proxy xmlns="http://ws.apache.org/ns/synapse" name="jwt-auth-mi" transports="http https" startOnLoad="true">
      <description>JWT Mediator Test Proxy</description>
      <target>
            <inSequence>
            <propertyGroup name="jwt-auth-mi">
                  <property name="jwtToken" expression="$trp:Authorization"/>
                  <property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
                  <property name="jwksTimeout" value="3000"/>
                  <property name="jwksRefreshTime" value="1000"/>
            </propertyGroup>
            <class name="io.integon.JwtAuthMediator"/>
            <!-- Your sequence continues here -->
            </inSequence>
            <faultSequence>
                  <!-- Error handling -->
            </faultSequence>
      </target>
</proxy>

With Claim Validation

<proxy xmlns="http://ws.apache.org/ns/synapse" name="jwt-auth-mi" transports="http https" startOnLoad="true">
      <description>JWT Mediator Test Proxy</description>
      <target>
            <inSequence>
            <propertyGroup name="jwt-auth-mi">
                  <property name="jwtToken" expression="$trp:Authorization"/>
                  <property name="iatClaim" expression="$trp:test" />
                  <property name="issClaim" value="https://apim-dev.integon.ch:443/oauth2/token" />
                  <property name="subClaim" value="admin" />
                  <property name="audClaim" value="Y3wBS2AsdgHW6z2GfEfUpairc_Ma" />
                  <property name="jtiClaim" value="enabled" />
                  <property name="jwksEndpoint" value="env:JWKS_ENDPOINT"/>
            </propertyGroup>
            <class name="io.integon.JwtAuthMediator"/>
            <!-- Your sequence continues here -->
            </inSequence>
            <faultSequence>
                  <!-- Error handling -->
            </faultSequence>
      </target>
</proxy>

Multiple JWKS Endpoints

<proxy xmlns="http://ws.apache.org/ns/synapse" name="jwt-auth-mi" transports="http https" startOnLoad="true">
      <description>JWT Mediator Test Proxy</description>
      <target>
            <inSequence>
            <propertyGroup name="jwt-auth-mi">
                  <property name="jwtToken" expression="$trp:Authorization"/>
                  <property name="jwksEndpoint" value="https://apim-dev.ch/oauth2/jwks,https://apim-test.ch/oauth2/jwks"/>
            </propertyGroup>
            <class name="io.integon.JwtAuthMediator"/>
            <!-- Your sequence continues here -->
            </inSequence>
            <faultSequence>
                  <!-- Error handling -->
            </faultSequence>
      </target>
</proxy>

Enable Debug Logs

To enable debugging for the JWT validator, add the following to "../mi-home/conf/log4j2.properties":

logger.JwtAuthMediator.name = io.integon.JwtAuthMediator
logger.JwtAuthMediator.level = DEBUG

logger.JwtAuthHandler.name = io.integon.JwtAuthHandler
logger.JwtAuthHandler.level = DEBUG

Then add these loggers to the list of loggers:

loggers = ..., ..., ..., JwtAuthMediator, JwtAuthHandler

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Contributors

Languages