Skip to main content

Gate: OpenAPI Security

This plugin enforces security schemes defined in an OpenAPI specification. It supports all security schemes defined in the OpenAPI specification:

  • API keys
  • HTTP authorization
  • OAuth 2.0
  • OpenID Connect (OIDC)

OpenAPI specification files can be provided in either JSON or YAML format, and can be loaded from a local file or a remote URL.

ClientYour systemDestination endpointGateHTTP requestDestination endpointDestination endpointOpenAPISpecBearer token?API Key?OAuth2 token+ scopes?

Security Schemes

Each security scheme is validated as follows.

API Keys

components:
securitySchemes:
ApiKeyAuthHeader:
type: apiKey
in: header
name: API-Key
ApiKeyAuthCookie:
type: apiKey
in: cookie
name: ApiKey
ApiKeyAuthQuery:
type: apiKey
in: query
name: api_key

The plugin will use the name and in fields from the API key security scheme definition to confirm that an API key is present in the request, and in the correct part of the request (header, cookies, or query). The plugin will then call the validation URL provided in the plugin configuration to check that the API key is valid. The OpenAPI specification allows for a list of strings to be associated with an API key scheme, but their significance is not defined in OpenAPI and the plugin will ignore them.

HTTP

components:
securitySchemes:
BearerToken:
type: http
scheme: bearer
bearerFormat: JWT
BasicAuth:
type: http
scheme: basic

The OpenAPI HTTP security scheme can have one of various types, the most common being bearer and basic. For these types, the plugin will confirm that the Authorization header is present, that the header value has the correct prefix, and that the value is not empty. The plugin will then call the validation URL provided in the plugin configuration to check that content of the Authorization field is valid. For other types of HTTP security (for example, DPoP), the plugin will not perform any validation on the request itself, and will only call the provided validation URL. The OpenAPI specification allows for a list of strings to be associated with an HTTP scheme, but their significance is not defined in OpenAPI and the plugin will ignore them.

OAuth 2.0

components:
securitySchemes:
OAuth2:
type: oauth2
flows:
implicit:
authorizationUrl: "https://example.com/oauth2/authz"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information
admin: Administrative privileges
password:
tokenUrl: "https://example.com/oauth2/token"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information
admin: Administrative privileges
clientCredentials:
tokenUrl: "https://example.com/oauth2/token"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information
admin: Administrative privileges
authorizationCode:
authorizationUrl: "https://example.com/oauth2/authz"
tokenUrl: "https://example.com/oauth2/token"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information
admin: Administrative privileges

For OAuth 2.0 security schemes, the plugin will check that the request has a valid OAuth 2.0 access token, and that token has been granted at least the scope defined in the relevant operation's security. The plugin supports tokens in JWT and opaque formats. JWTs will be validated locally using the verification configuration. Opaque tokens will be validated using the issuer's token introspection endpoint. If the operation's security explicitly specifies no scopes, then the plugin will only check the token's validity.

OpenID Connect (OIDC)

components:
securitySchemes:
OIDC:
type: openIdConnect
openIdConnectUrl: https://example.com/.well-known/openid-configuration

OIDC providers may issue both access and ID tokens; access tokens may be either opaque or JWTs, while ID tokens are always JWTS. For access tokens, OIDC security schemes behave as for OAuth2 security schemes (see above) - in particular, the token format must be specified. For ID tokens, you should provide configuration as for OAuth2 JWT access tokens. In this case, any valid JWT with the correct scope is treated as valid (whether it is an ID or access token).

Other Considerations

Specification Validation

The OpenAPI specification file provided to the plugin will be validated when Gate starts. This includes:

  • standard validation of YAML/JSON syntax and OpenAPI-specific requirements (for example, checking for required fields)
  • ensuring that all security schemes named by each operation and in the top-level security field exist in the securitySchemes field under Components
  • checking that the relevant configuration values are present for each security scheme in the specification (for example, if the specification has an OAuth 2.0 security scheme, the relevant OAuth 2.0 configuration values must be present)

Default, Optional, and No Security

An OpenAPI specification may include a top-level list of security schemes. These schemes apply to operations where no other security is specified, and the plugin will enforce this.

An operation with no security field set and an operation with security set to an empty array will be treated equivalently by the plugin, and both will have the default security schemes applied. In order to disable security explicitly for an operation, security should be set to an array containing a single empty object (see the example below).

Security can be made optional by including an empty object in the list of security schemes, alongside named security schemes (see examples below). In this case, a request with no authorization information, or information that does not apply to the named scheme(s), will still be regarded as valid. However, if a request attempts to use the named security scheme(s) and fails validation, the request will be denied.

Multiple Security Schemes

An OpenAPI operation can name multiple security schemes (as can the top-level security field). If any one of these is fulfilled by a request, the request will be regarded as valid.

Allow/Deny Unmatched Requests

The plugin can be configured to allow or deny requests that do not match any operation defined in the provided OpenAPI specification. By default, request are denied.

Configuration Recommendations

As the provided OpenAPI specification contains per-path security rules, there is usually no need to provide per-URL parameters for this plugin, and the plugin can be enabled by default. The exception to this may be to disable the plugin for specific URLs. For example, if Gate is protecting a specific endpoint that is not described in the OpenAPI specification, you may disable the OpenAPI plugin for that URL only. This ensures that other URLs remain protected according to the rules in the specification, and there is no need to allow unmatched requests.

Examples

openapi: 3.0.1

info:
title: Example API
version: "1.0"

servers:
- url: "https://example.local"

components:
securitySchemes:
BearerToken:
type: http
scheme: bearer
bearerFormat: JWT
ApiKeyAuthHeader:
type: apiKey
in: header
name: API-Key
OAuth2AccessToken:
type: oauth2
flows:
clientCredentials:
tokenUrl: "https://example.com/oauth2/token"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information
authorizationCode:
authorizationUrl: "https://example.com/oauth2/authz"
tokenUrl: "https://example.com/oauth2/token"
refreshUrl: "https://example.com/oauth2/refresh"
scopes:
read:user: Read a user's profile
write:user: Write information to a user's profile
read:contacts: Read contact information
write:contacts: Write contact information

paths:
/default:
post:
# `security` field not set, uses defaults
responses:
"200":
description: OK

/none:
post:
security:
- {} # explicitly no security, all requests allowed
responses:
"200":
description: OK

/optional:
post:
security:
- ApiKeyAuthHeader: []
- {} # makes security optional
responses:
"200":
description: OK

security:
- BearerToken: []
- OAuth2AccessToken: [read:user, read:contacts]

The plugin using this specification would behave as follows:

  • A request to /default would be allowed only if:
    • it contained a valid bearer token, or
    • it contained a valid OAuth2 access token that has been granted both the read:user and read:contacts scope
  • A request to /none would always be allowed
  • A request to /optional would be allowed if it contained a valid API key in the API-Key header (defined security attempted and was valid)
  • A request to /optional would be denied if it contained an invalid API key in the API-Key header (defined security attempted and was invalid)
  • A request to /optional would be allowed if the API-Key was absent, regardless of the rest of the request (defined security not attempted, security optional)
note

Requests with the OPTIONS method are not validated.

Configuring Gate

GATE_PLUGINS_<PLUGIN NUMBER>_TYPE=enforce-openapi-security

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OPENAPI_SPEC_URL=<OpenAPI specification file URL>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OPENAPI_SPEC_FORMAT=<OpenAPI specification format>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ALLOW_REQUESTS_NOT_IN_SPEC=<Whether to allow requests with no matching operation>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_VALIDATE_URL=<Request validation URL>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_TOKEN_FORMAT=<Format of the OAuth2/OIDC access token>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_HEADER_WITH_OAUTH2_TOKEN=<Header with OAuth2/OIDC token>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_COOKIE_WITH_OAUTH2_TOKEN=<Cookie with OAuth2/OIDC token>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_JWKS_URL=<Custom JSON Web Key Sets URL for OAuth2/OIDC tokens>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_JWKS_REFRESH_INTERVAL=<JSON Web Key Sets refresh interval for OAuth2/OIDC tokens>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_JWT_ALLOWED_ALGORITHMS=<Allowed JWT signing algorithms for OAuth2/OIDC tokens>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_JWT_EXPECTED_ISSUER=<JWT expected issuer for OAuth2/OIDC tokens>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_JWT_EXPECTED_AUDIENCE=<JWT expected audience for OAuth2/OIDC tokens>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_TOKEN_INTROSPECTION_URL=<OAuth2/OIDC access token introspection URL>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_TOKEN_INTROSPECTION_CLIENT_ID=<Client ID for authorizing OAuth2/OIDC access token introspection>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_TOKEN_INTROSPECTION_CLIENT_SECRET=<Client secret for authorizing OAuth2/OIDC access token introspection>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_OAUTH2_TOKEN_INTROSPECTION_BEARER_TOKEN=<Bearer token for authorizing OAuth2/OIDC access token introspection>

GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_INCLUDE_REQUIRED_SCOPES_IN_OAUTH2_INTROSPECTION_REQUEST=<Include required scopes in OAuth2/Access introspection request>

In the Environment variables configuration, <PLUGIN NUMBER> defines plugin execution order.

Where:

  • <OpenAPI specification file URL> is the file path or URL from which to retrieve the OpenAPI file
  • <OpenAPI specification format> is the format of the OpenAPI specification, either yaml or json
  • <Whether to allow requests with no matching operation> whether requests with no matching operation in the OpenAPI specification should be allowed (defaults to false)
  • <Request validation URL> is the URL of the request validation endpoint for non-OAuth2/OIDC schemes
  • <Format of the OAuth2/OIDC access token> is the format of the OAuth2/OIDC access token, either jwt or opaque
  • <Header with OAuth2/OIDC token> is the request header containing the token. This option and <Cookie with OAuth2/OIDC token> are mutually exclusive. If neither are provided, the plugin will attempt to retrieve the token from the Authorization header and strip the Bearer token.
  • <Cookie with OAuth2/OIDC token> is the cookie containing the token. This option and <Header with OAuth2/OIDC token> are mutually exclusive. If neither are provided, the plugin will attempt to retrieve the token from the Authorization header and strip the Bearer token.
  • <Custom JSON Web Key Sets URL for OAuth2/OIDC tokens> is the URL for retrieving keysets for JWT validation. Required if <Format of the OAuth2/OIDC access token> is set to jwt.
  • <JSON Web Key Sets refresh interval for OAuth2/OIDC tokens> is the interval for refreshing keysets for JWT validation. By default, 15m.
  • <Allowed JWT signing algorithms for OAuth2/OIDC tokens> is the list of allowed signing algorithms for JWTs. At least one algorithm must be provided. Only JWTs with one of these algorithms in the alg field will be accepted. Requests with JWTs using another algorithm will be rejected. In environment variables, multiple algorithms should be separated by a comma. For example: ES256,ES512. In HCL, JSON, TOML and YAML, multiple algorithms should be provided as a list. For example: ["ES256", "ES512"]. This plugin supports the following algorithms: ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512. Required if <Format of the OAuth2/OIDC access token> is set to jwt.
  • <JWT expected issuer for OAuth2/OIDC tokens> is the expected issuer of the OAuth2/OIDC JWT token. Required if <Format of the OAuth2/OIDC access token> is set to jwt
  • <JWT expected audience for OAuth2/OIDC tokens> is the expected audience of the OAuth2/OIDC JWT token. Required if <Format of the OAuth2/OIDC access token> is set to jwt.
  • <OAuth2/OIDC access token introspection URL> is the URL for introspecting the access token. Required if <Format of the OAuth2/OIDC access token> is set to opaque.
  • <Client ID for authorizing OAuth2/OIDC access token introspection> the client ID used to request the OAuth2/OIDC access token, which will be used to authorize the token introspection request. This is mutually exclusive with <Bearer token for authorizing OAuth2/OIDC token introspection>. At least one is required if <Format of the OAuth2/OIDC access token> is set to opaque.
  • <Client secret for authorizing OAuth2/OIDC access token introspection> is the client secret used to request the OAuth2/OIDC access token, which will be used to authorize the token introspection request. This is required with <Client ID for authorizing OAuth2/OIDC token introspection>.
  • <Bearer token for authorizing OAuth2/OIDC access token introspection> the bearer token from the OAuth2/OIDC authorization server, which will be used to authorize the token introspection request. This is mutually exclusive with <Client ID for authorizing OAuth2/OIDC token introspection>. At least one is required if <Format of the OAuth2/OIDC access token> is set to opaque.
  • <Include required scopes in OAuth2/Access introspection request> whether to include the specified required scopes in the OAuth2/OIDC access token introspection request. Some authorization servers will check scopes server-side and return a response body with active: false if the token does not have the requested scopes. This is only accepted if <Format of the OAuth2/OIDC access token> is set to opaque.

To learn more about configuring Gate, please visit configuration page and plugins section.

info

The order of plugins in configuration determines their execution order.

Disabling plugin for specific URLs

You can enable or disable this plugin for specific URLs by using the enabled option in the URLs configuration.

GATE_URLS_0_PATTERN=svc-example.com/*
GATE_URLS_0_TARGET=http://example:8080

GATE_URLS_1_PATTERN=svc-another-example.com/
GATE_URLS_1_TARGET=https://another-example:8080