Skip to main content

Authentication

Most APIs use authentication, and sometimes authorization. Specmatic reads authentication requirements from your OpenAPI specification and sends the required headers or parameters during contract tests. Specmatic supports these OpenAPI security schemes:

  • OAuth2
  • API Key
  • HTTP Bearer
  • HTTP Basic

Authentication can be provided in an example, configured globally for a specification, or handled by the application/test setup when authentication is being mocked or bypassed.

Authentication tokens for OpenAPI Security Schemes

When contract tests run against an environment that requires credentials, Specmatic needs real tokens or keys. You can provide them through environment properties or through specmatic.yaml security configuration, which can also read from environment variables.

Environment Properties per Security Scheme

The name you configure must match the security scheme name in components.securitySchemes.

For example, if your OpenAPI spec contains:

components:
securitySchemes:
oAuth2AuthCode:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://example.com/auth
tokenUrl: https://example.com/token
scopes: {}

Then the configured name must be oAuth2AuthCode.

Provide the raw credential value, not the full HTTP header. Specmatic will construct the correct header format automatically based on the security scheme type.

Examples:

  • OAuth2 / Bearer: provide only the token, without Bearer .
  • Basic: provide only the Base64 credential, without Basic .
  • API Key: provide only the key value.

Using Specmatic Configuration

You can configure auth values under the OpenAPI test configuration in specmatic.yaml.

specs:
- spec:
id: orderApiSpec
securitySchemes:
oAuth2AuthCode:
type: oauth2
token: ${OAUTH_TOKEN:OAUTH1234}
basicAuth:
type: basicAuth
token: ${BASIC_AUTH_TOKEN:dXNlcjpwYXNzd29yZA==}
apiKeyAuth:
type: apiKey
token: ${API_KEY:APIKEY1234}

This lets you:

  • Map each OpenAPI security scheme to a token/key.
  • Read values from environment variables.
  • Provide defaults for local testing.

Authentication within an Example

Use example-level authentication when you need a token for a specific test case, a fresh token for each test run, or when RBAC requires different auth credentials for different test cases.

You can put a value directly in the example, injecting a value into the example at runtime, or fetching a value just before the contract test runs.

Hard-coded Values

If static credentials are enough, which is usually the case for testing, you can put them directly into your examples. For example, let's say you have an OAuth2 security scheme defined in your spec:

openapi: 3.0.3
paths:
/orders:
GET:
security:
- oAuth2AuthCode: []
responses:
"200":
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: integer
productid:
type: integer
quantity:
type: integer
components:
securitySchemes:
oAuth2AuthCode:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://example.com/auth
tokenUrl: https://example.com/token
scopes: {}

The header used by OAuth2 and HTTP Bearer is Authorization. So the security token can go into an external example like this:

{
"http-request": {
"path": "/orders",
"headers": {
"Authorization": "Bearer <your bearer token>"
},
"method": "GET"
},
"http-response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"id": 10,
"productid": 1010,
"quantity": 1
}
]
}
}

You may then use that example for running contract tests, or for mocking the API out.

Injecting Tokens into Examples Commercial

You can inject auth tokens directly into examples using template expressions. This way you can use different auth tokens for different test cases.

Supposing the OpenAPI spec defines bearer auth like this:

components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer

security:
- BearerAuth: []

The external example can then read the token using a template value:

get_products.json
{
"http-request": {
"method": "GET",
"path": "/products",
"headers": {
"Authorization": "Bearer ${API_TOKEN:test-token}"
}
},
"http-response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"id": 10,
"name": "iPhone"
}
]
}
}

Here is what happens:

  • Specmatic looks up the environment variable or system property API_TOKEN before using the example.
  • If API_TOKEN is set, Specmatic uses that value.
  • If API_TOKEN is not set, Specmatic uses the default value test-token.
  • The contract test request is sent with Authorization: Bearer <resolved-token>.

In this example, API_TOKEN is looked up at runtime from an environment variable or system property, which can be provided in any of these ways:

docker run --rm \
-v "$(pwd):/usr/src/app" \
-e API_TOKEN=secret-token \
specmatic/enterprise test openapi.yaml --testBaseURL http://host.docker.internal:8080

Specmatic resolves the request header as:

Authorization: Bearer secret-token

If you have multiple examples for the same endpoint, you can use different template values for each example. For instance, you could have one example that uses ${API_TOKEN_200:valid-token}, like the example above, and another that uses ${API_TOKEN_401:invalid-token}:

{
"http-request": {
"method": "GET",
"path": "/products",
"headers": {
"Authorization": "Bearer ${API_TOKEN_401:invalid-token}"
}
},
"http-response": {
"status": 401,
"headers": {
"Content-Type": "application/json"
},
"body": {
"error": "Unauthorized"
}
}
}

Just-in-time Tokens via Fixtures Commercial

For contract tests, you can fetch an auth token before the test runs and use it in the main request using substitution. This is useful when your application expects an auth token, such as an Authorization header, but you do not want to hard-code a token in every example or need a fresh token. Perhaps the token is valid for only a short time.

Supposing the OpenAPI spec defines bearer auth like this:

components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer

security:
- BearerAuth: []

In the external example, use a before fixture to call a token endpoint and capture the token from its response.

get_products.json
{
"before": [
{
"type": "http",
"http-request": {
"method": "POST",
"path": "/auth/token",
"baseUrl": "http://localhost:9000",
"headers": {
"Content-Type": "application/json"
},
"body": {
"clientId": "contract-tests",
"clientSecret": "secret"
}
},
"http-response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"accessToken": "(ACCESS_TOKEN:string)"
}
}
}
],
"partial": {
"http-request": {
"method": "GET",
"path": "/products",
"headers": {
"Authorization": "Bearer $(ACCESS_TOKEN)"
}
},
"http-response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": [
{
"id": 10,
"name": "iPhone"
}
]
}
}
}

Here is what happens:

  • Specmatic calls /auth/token before running the contract test.
  • The token response captures accessToken as (ACCESS_TOKEN:string).
  • The main request uses it as $(ACCESS_TOKEN).
  • Specmatic sends the request with Authorization: Bearer <captured-token>.

Mocking / Bypassing Authentication

For local contract tests within the project, such as junit tests, you can isolate your application from real auth providers, such as OAuth servers, DB-backed auth, or identity services.

At this stage, the main objective is to validate that:

  • Your API advertises the correct auth requirements in the OpenAPI spec.
  • Your application accepts the expected auth headers/parameters.
  • Your service behavior matches the contract.

You do not need to validate real token issuance/verification in every contract test. That can also be covered in higher-level integration or end-to-end tests. A test security setup can:

  • Check header presence and format.
  • Optionally create a dummy authenticated principal/user.
  • Avoid calling real auth dependencies.

This is similar to using an in-memory database in tests instead of a production database.

Security Scheme Precedence

OpenAPI allows authentication to be defined at two levels:

  • Global level: top-level security, which applies to all operations by default.
  • Operation level: security inside a specific endpoint/method, which applies only to that operation.

Specmatic reads the OpenAPI security requirement for each operation. If both are present, Specmatic gives preference to the operation-level security scheme. This is useful when most endpoints use one auth scheme, but some endpoints use a different one.

Example: Global security with operation-level override

openapi: 3.0.1

security:
- BearerAuth: [] # Global default

paths:
/products:
get:
security:
- basicAuth: [] # Overrides global for GET /products
responses:
"200":
description: OK

In this example:

  • Most endpoints use BearerAuth globally.
  • GET /products uses basicAuth through an operation-level override.

Patterns, Examples & FAQs

Security Scheme Examples

OAuth2

OpenAPI example:

components:
securitySchemes:
oAuth2AuthCode:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://api.example.com/oauth/authorize
tokenUrl: https://api.example.com/oauth/token
scopes:
users:read: Read user information

Configure:

  • Security scheme name: oAuth2AuthCode.
  • Token value: abc123, not Bearer abc123.

Specmatic sends:

  • Authorization: Bearer abc123

API Key

OpenAPI example:

components:
securitySchemes:
ApiKeyAuthHeader:
type: apiKey
in: header
name: X-API-KEY

Configure:

  • Security scheme name: ApiKeyAuthHeader.
  • Token value: my-api-key-abc123.

Specmatic sends:

  • X-API-KEY: my-api-key-abc123

HTTP Bearer

OpenAPI example:

components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer

Configure:

  • Security scheme name: BearerAuth.
  • Token value: abc123, not Bearer abc123.

Specmatic sends:

  • Authorization: Bearer abc123

HTTP Basic

OpenAPI example:

components:
securitySchemes:
BasicAuth:
type: http
scheme: basic

Configure:

  • Security scheme name: BasicAuth.
  • Token value: Base64 of username:password.
  • Example: dXNlcjpwYXNzd29yZA==, which is user:password in Base64.

Specmatic sends:

  • Authorization: Basic dXNlcjpwYXNzd29yZA==

Different auth schemes per operation

Specmatic supports different auth schemes for different endpoints in the same OpenAPI specification. Example use case:

  • POST endpoints use OAuth2.
  • GET endpoints use Basic Auth.
  • DELETE endpoints use API Key.

Specmatic reads the operation-level security entries and sends the appropriate auth header for each request.

Sample project:

Tips

  • If an operation defines security, it overrides global security.
  • Security scheme names in specmatic.yaml must match names in components.securitySchemes.
  • Use environment variables in specmatic.yaml to switch credentials across local, CI, and test environments.