GuidesConceptsAuthenticated Input Specifications

Authenticated input specifications

Sometimes you want to generate using a URL as the input, but the URL requires some kind of authentication header to be passed.

A good example is Google cloud platforms IAP proxy, which was the original motivation for supporting this, where we must pass a Proxy-Authorization header. Or from private github repositories, where a Authorization header should be supplied.

This can be achieved using the environment variable (preferred)) OPENAPI_REMOTE_SPEC_REQUEST_HEADERS, also available as the --remote-spec-request-headers cli flag.

Format

The format of the value is a JSON object keyed by URI, with values being either an object, or array of {name, value} pairs.

For example:

{
  "https://example.com": [
    {"name": "X-Client-Id", "value": "my-client-id"},
    {"name": "X-Client-Secret", "value": "some-secret-value"}
  ],
  "https://example.org/some/path": {"name": "Proxy-Authorization", "value": "some token"}
}

As a typescript type:

type OPENAPI_REMOTE_SPEC_REQUEST_HEADERS = {
  [uri: string]: { name: string, value: string }[] | { name: string, value: string }
}

Hostname matching

You should set the uris to the least specific uris you’re happy for the header to be sent to - a full match on the provided uri is required for the headers to be sent.

Eg: given a uri of https://exmaple.com:8080/openapi.yaml the headers would not be sent for requests to other ports, resource paths, or protocols, but a less specific uri like https://example.com will send headers on any (https) request to that domain, such as https://exmaple.com/some/path/openapi.yaml

Tips for generating the JSON

Unfortunately it is a little annoying to formulate in shell scripts, so here’s some examples to get you started.

Typically, in any real use cases the secret values would be coming from other shell variables, eg: storing a short-lived access token, etc.

Use jq

Using jq:

OPENAPI_REMOTE_SPEC_REQUEST_HEADERS=$(jq --null-input --compact-output \
  --arg domain "https://example.com" \
  --arg name "proxy-authorization" \
  --arg value "some secret value" '{$domain: {$name, $value}}')
echo $OPENAPI_REMOTE_SPEC_REQUEST_HEADERS

Outputs:

{"https://example.com":{"name":"proxy-authorization","value":"some secret value"}}

Use node

Using nodejs:

OPENAPI_REMOTE_SPEC_REQUEST_HEADERS=$(node -p 'JSON.stringify({[process.argv[1]]: {name: process.argv[2], value: process.argv[3]}})' \
  https://example.com \
  proxy-authorization \
  'some secret value')
echo $OPENAPI_REMOTE_SPEC_REQUEST_HEADERS

Outputs:

{"https://example.com":{"name":"proxy-authorization","value":"some secret value"}}

Why JSON

Why JSON you ask? Simply put it has very well-defined semantics, and is easy to parse without fear of jumbling the pieces together.

I started by trying to come up with a more ergonomic format, and then felt like I was re-inventing JSON when it came to dealing with all the edge cases correctly.