Implement a Trigger Connection Definition With JWT Signatures Security Policy

This procedure gives an overview of how to implement a trigger connection definition that uses JWT signature security policy.

Prerequisite:

Check the webhook producer documentation on how the webhook is signed. Collect information on the following:

  • Where the JWT token is sent as part of the request
  • If there are any custom claims to validate
  • Whether to use HMAC or RSA signatures
  • Signature keys
  • Override subject claim
  1. Open the adapter definition document in Visual Studio Code Editor.
  2. Navigate to the connection code section of the document and set the scope to TRIGGER.
  3. Set the value of the security properties according to the information you collected in the prerequisites.

    Here is code sample 1 where:

    • JWT Token is extracted from authorization header (.request.headers.authorization|split(\" \")|.[1] ).
    • Signature key is added in securityProperty signKey part of same policy and referred in jwtVerify function (.securityProperties.signKey). This key resolved to alias JWK URL of JWT issuer for example, "https://www.demosvc.com/oauth2/v3/certs".
    • No custom claims to validate.
    • Default subject claim (no overrides).
    {
     "connection": {
         
        "securityPolicies": [
           {
                "type": "managed",
                "policy": "JWT_VALIDATION",
                "securityProperties": [
                    {
                        "name": "jwtToken",
                        "displayName": "JWT Token",
                        "hidden": true,
                        "required": true,
                        "default": "${.request.headers.authorization|split(\" \")|.[1]}"
                    },
                    {
                        "name": "signatureKey",
                        "displayName": "JWK URL",
                        "hidden": true,
                        "required": true,
                        "default": "https://www.demosvc.com/oauth2/v3/certs"
                    },
                     {
                        "name": "subjectClaim",
                        "displayName": "Subject claim Override",
                        "hidden": true,
                        "required": false,
                        "default": ""
                    },
                    {
                        "name": "customClaimsValidation",
                        "displayName": "Custom Claims Validation",
                        "hidden": true,
                        "required": false,
                        "default": ""
                    }
                ]
            }
        ]
      }
    }

    Here is code sample 2 where:

    • JWT Token is extracted from authorization header (.request.headers.authorization|split(\" \")|.[1] )
    • Signature key is added in securityProperty signKey part of same policy and referred in jwtVerify function (.securityProperties.signKey). This key resolved to alias JWK URL of JWT issuer for example, "https://www.dummysvc.com/oauth2/v3/certs"
    • Email is the subject claim
    • Custom claims issuer validation
    {
     "connection": {
         
        "securityPolicies": [
           {
                "type": "managed",
                "policy": "JWT_VALIDATION",
                "securityProperties": [
                    {
                        "name": "jwtToken",
                        "displayName": "JWT Token",
                        "hidden": true,
                        "required": true,
                        "default": "${.request.headers.authorization|split(\" \")|.[1]}"
                    },
                    {
                        "name": "signatureKey",
                        "displayName": "JWK URL",
                        "hidden": true,
                        "required": true,
                        "default": "https://www.dummysvc.com/oauth2/v3/certs"
                    },
                     {
                        "name": "subjectClaim",
                        "displayName": "Subject claim Override",
                        "hidden": true,
                        "required": false,
                        "default": "email"
                    },
                    {
                        "name": "customClaimsValidation",
                        "displayName": "Custom Claims Validation",
                        "hidden": true,
                        "required": false,
                        "default": "${{\"iss\": \"https://dummyIssuer\"}}"
                    }
                ]
            }
        ]
      }
    }

    Here is code sample 3 where the flow:

    • Contains token, signkey, custom claims and subject claim.
    • Fetches signature key.
    • Uses a jq function.
    {
     "connection": {
         
        "securityPolicies": [
           {
                "type": "managed",
                "policy": "JWT_VALIDATION",
                "securityProperties": [
                    {
                        "name": "jwtToken",
                        "displayName": "JWT Token",
                        "hidden": true,
                        "required": true,
                        "default": "${.request.headers.authorization|split(\" \")|.[1]}"
                    },
                    {
                        "name": "signatureKey",
                        "displayName": "JWK URL",
                        "hidden": true,
                        "required": true,
                        "default": "flow:getCerts"
                    },
                     {
                        "name": "subjectClaim",
                        "displayName": "Subject claim Override",
                        "hidden": true,
                        "required": false,
                        "default": "email"
                    },
                    {
                        "name": "customClaimsValidation",
                        "displayName": "Custom Claims Validation",
                        "hidden": true,
                        "required": false,
                        "default": ""
                    }
                ]
            }
        ]
      }
    } 
     
       "flows": {
        "getCerts": {
          "id": "getCerts",
          "description": "getCerts",
          "specVersion": "0.8",
          "version": "0.1",
          "start": "startState",
          "functions": [
            {
              "name": "getCertificate",
              "type": "expression",
              "operation": "{\"certificates\":[\"-----BEGIN CERTIFICATE-----\\nMIIbTAe\\nFw0GVy\\nYX\/wQCMAAw\nIYX\\n-----END CERTIFICATE-----\"]}"
            }
          ],
          "states":[
            {
              "name":"startState",
              "type":"operation",
              "actions":[
                {
                  "functionRef": "getCertificate",
                  "actionDataFilter": {
                    "results": "${.certificates}"
                    "toStateData": "${ .output }"
                  }
                }
              ]
              "end": true
            }
          ]
        }
      } }