OAuth 2.0 support

The custom logic client supports fetching an authentication token using an OAuth 2.0 client (RFC 6749  ).

It currently supports client credentials authorization grant (RFC 6749, section 1.3.4  and section 4.4  ), using client and password authentication (RFC 6749, section 2.3.1  ), either with HTTP Basic authentication (RFC 2617  ) or using the request body.

Once retrieved, the “bearer” authorization token is then passed as an “Authorization” HTTP header to every request to the webhook (RFC 6750  ). If the token expires, the client automatically fetches a new token. If the custom logic client finds that the token expires soon (in the shortest of either 5 minutes or half the lifetime duration of the token), then the client automatically refreshes the token in the background, while concurrent calls to the webhook keep using the current token.

If a refresh token is returned with the authorization token, then the client prefers refreshing it over fetching a new token, by using the refresh_token value of grant_type (RFC 6749, section 6  ).

The client expects a fast response from the OAuth 2.0 endpoint, since any overhead from fetching a new token must fall within the overall webhook timeout configuration (timeoutMs or callStartTimeoutMs). It also has a timeout of 2 seconds to establish the HTTPS connection with the endpoint, and 3 seconds to retrieve its HTTP body.

The client expects the OAuth 2.0 endpoints to use Transport Layer Security (TLS) on port 443. If the webhook configuration specifies trustedCACerts or clientCerts, then they’re also used when establishing the connection to the endpoints.

Enabling OAuth 2.0 simply requires adding the oauth2 section to the configuration.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["tokenEndpoint", "scopes"],
  "properties": {
    "tokenEndpoint": {
      "type": "string",
      "format": "uri"
    },
    "refreshEndpoint": {
      "type": "string",
      "format": "uri"
    },
    "clientId": {
      "type": "string"
    },
    "clientSecret": {
      "type": "string"
    },
    "scopes": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string"
      }
    },
    "clientAuthType": {
      "type": "string",
      "default": "basic",
      "enum": ["basic", "post", "jwt", "jwtValue"]
    },
    "customParams": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            }
          }
        ]
      }
    },
    "jwtValue": {
      "type": "string"
    },
    "jwt": {
      "type": "object",
      "required": ["issuer", "audience", "subject", "key", "algorithm", "expirationMs"],
      "properties": {
        "type": {
          "type": "string",
          "examples": ["JWT"]
        },
        "algorithm": {
          "type": "string",
          "enum": ["RS256"]
        },
        "audience": {
          "type": "string"
        },
        "issuer": {
          "type": "string"
        },
        "subject": {
          "type": "string"
        },
        "keyId": {
          "type": "string"
        },
        "jwtTokenId": {
          "type": "string"
        },
        "expirationMs": {
          "type": "integer",
          "minimum": 1
        },
        "key": {
          "type": "string",
          "contentMediaType": "application/pkcs8",
          "contentEncoding": "base64"
        },
        "certificates": {
          "type": "array",
          "items": {
            "type": "string",
            "contentMediaType": "application/x-x509-ca-cert",
            "contentEncoding": "base64"
          }
        },
        "other": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    }
  }
}

The following is the description of each JSON property:

  • clientAuthType: The authentication method to use. By default, basic is used.
    • basic: Use HTTP Basic authentication (RFC 2617  ).
    • post: Use form-based authentication (RFC 6749, section 2.3.1  ).
    • jwtValue: Use the JWT value specified in the jwtValue as the JWT Profile for OAuth 2.0 (RFC 7523  ). This is used for testing or if the OAuth 2.0 server can accept as valid JWT with long expiration times (months or years).
    • jwt: Use the JWT Profile for OAuth 2.0 (RFC 7523  ) by generating a signed JWT as a “client assertion”. The jwt object must contain the information required to create that signed JWT.
  • tokenEndpoint: Required. The URI of the token endpoint (RFC 6749, section 3.2  ). The client uses a grant_type set to client_credentials. The protocol must be https. Ports other than 443 (the default for https) aren’t supported. Specifying a username and password in the URI isn’t supported. Instead, you must use the basic or post authentication types.
  • scopes: Required. The list of scope names.
  • refreshEndpoint: The URI to use to refresh a token, by using grant_type set to refresh_token. If not set, the tokenEndpoint URI is used for both grant_type values client_credentials and refresh_token.
  • customParams: Additional parameters to include in the token request. Each parameter can be a single string value or an array of strings. For example, when you use basic or post authentication types, you might need to specify an audience parameter that some identity providers require.

If clientAuthType is set to basic or post:

  • clientId: Required. The client_id to use as authentication (see RFC 6749, section 2.3.1  ).
  • clientSecret: The client_secret to use as authentication (see RFC 6749, section 2.3.1  ).

If clientAuthType is set to jwtValue:

  • jwtValue: Required. The JWT to use for the JWT Profile for OAuth 2.0 (RFC 7523  ). It’s given to the OAuth 2.0 server in the client_assertion parameter (RFC 7523, section 2.2  ).

If clientAuthType is set to jwt, the jwt property must be an object with the following properties:

  • issuer: Required. The value of the issuer (“iss”) claim.
  • subject: Required. The subject (“sub”) claim. Often the same as the issuer.
  • audience: Required. The audience (“aud”) claim. Typically set to the token endpoint URL.
  • expirationMs: Required. When the token expires from generation, in milliseconds. This sets the expiration (“exp”) claim.
  • algorithm: Required. The algorithm (“alg”) header. This must be set to RS256.
  • key: Required. The private key to sign the token. Only RSA keys are supported. It should be the base64 value of the key in PKCS#8 format, as a single line of text, by removing its header and footer. The shell script mentioned in Encoding of Certificate Values can also be used to extract the base64 contents of a PKCS#8 file.
  • jwtTokenIdPrefix: A prefix to use for the randomly generated JWT ID (“jti”) claim.
  • type: The type (“typ”) header. Defaults to JWT.
  • keyId: The key ID (“kid”) header.
  • certificates: A list of X509 certificates, in base64. See Encoding of Certificate Values. These are added to the x5c JWT header in a format that matches RFC 7517, section 4.7  . At least one of the certificates’ subject field should match the JWT subject claim (the subject property) and the public key (the key property).
  • other: A JSON object with additional claims to add to the JWT. Each property is added to the JWT payload to sign.