You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Most APIs have some form of security (authentication and authorization). Specmatic reads [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.0.1#security-scheme-object) in your API Specifications to come up with appropriate request parameters.
7
-
Specmatic supports the following security schemes:
8
+
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.
9
+
10
+
Specmatic supports these OpenAPI security schemes:
11
+
8
12
-**OAuth2**
9
13
-**API Key**
10
-
-**Bearer**
14
+
-**HTTP Bearer**
15
+
-**HTTP Basic**
16
+
17
+
## How Specmatic chooses authentication for a request
18
+
19
+
Specmatic reads the OpenAPI `security` requirement for each operation.
20
+
21
+
OpenAPI allows authentication to be defined at two levels:
22
+
23
+
-**Global level**: top-level `security` (applies to all operations by default)
24
+
-**Operation level**: `security` inside a specific endpoint/method (applies only to that operation)
25
+
26
+
### Precedence rule
27
+
28
+
If both are present, **Specmatic gives preference to the operation-level security scheme**.
29
+
30
+
This is useful when most endpoints use one auth scheme, but some endpoints use a different one.
31
+
32
+
### Example: Global security with operation-level override
33
+
34
+
```yaml
35
+
openapi: 3.0.1
36
+
37
+
security:
38
+
- BearerAuth: [] # Global default
39
+
40
+
paths:
41
+
/products:
42
+
get:
43
+
security:
44
+
- basicAuth: [] # Overrides global for GET /products
## Providing real auth credentials for contract tests
56
+
57
+
When contract tests run against an environment that requires valid credentials, Specmatic needs real tokens or keys.
58
+
59
+
You can provide them in two ways:
60
+
61
+
- **Environment variables**
62
+
- **`specmatic.yaml` security configuration** (recommended; can read from environment variables)
63
+
64
+
### Important: Security scheme names must match the OpenAPI spec
65
+
66
+
The name you configure must match the security scheme name in `components.securitySchemes`.
67
+
68
+
For example, if your OpenAPI spec contains:
69
+
70
+
```yaml
71
+
components:
72
+
securitySchemes:
73
+
oAuth2AuthCode:
74
+
type: oauth2
75
+
flows:
76
+
authorizationCode:
77
+
authorizationUrl: https://example.com/auth
78
+
tokenUrl: https://example.com/token
79
+
scopes: {}
80
+
```
81
+
82
+
Then the configured name must be `oAuth2AuthCode`.
83
+
84
+
## Recommended: Configure auth in `specmatic.yaml`
85
+
86
+
You can configure auth values under the OpenAPI test configuration in `specmatic.yaml`.
87
+
88
+
```yaml
89
+
specs:
90
+
- spec:
91
+
id: orderApiSpec
92
+
securitySchemes:
93
+
oAuth2AuthCode:
94
+
type: oauth2
95
+
token: ${OAUTH_TOKEN:OAUTH1234}
96
+
basicAuth:
97
+
type: basicAuth
98
+
token: ${BASIC_AUTH_TOKEN:dXNlcjpwYXNzd29yZA==}
99
+
apiKeyAuth:
100
+
type: apiKey
101
+
token: ${API_KEY:APIKEY1234}
102
+
```
103
+
104
+
This lets you:
105
+
106
+
- Map each OpenAPI security scheme to a token/key
107
+
- Read values from environment variables
108
+
- Provide defaults for local testing
109
+
110
+
## Environment variable values: what to provide
11
111
12
-
## Testing with real auth
13
-
To run contract tests in environments which require a valid security token present in the request, we can define environment variables which hold these valid tokens/api keys.
112
+
Provide the **raw credential value**, not the full HTTP header.
14
113
15
-
The environment variable should match the name of the security scheme defined in the open api specification.
114
+
Specmatic will construct the correct header format automatically based on the security scheme type.
16
115
17
-
When contract tests are executed, Specmatic will look for an environment variable with the same name as that of the security scheme. If such an environment variable exists, Specmatic will use it appropriately (based on the security scheme) while making an HTTP request.
116
+
Examples:
117
+
118
+
- **OAuth2 / Bearer**: provide only the token (without `Bearer `)
119
+
- **Basic**: provide only the Base64 credential (without `Basic `)
120
+
- **API Key**: provide only the key value
121
+
122
+
## Security scheme examples
18
123
19
124
### OAuth2
20
-
Here's an example of an OAuth2 security scheme in the open api specification:
125
+
126
+
OpenAPI example:
21
127
22
128
```yaml
23
129
components:
24
130
securitySchemes:
25
131
oAuth2AuthCode:
26
132
type: oauth2
27
-
description: For more information, see https://example.com/docs/oauth
To use a real OAuth2 token in contract tests, an environment variable with the name of the security scheme needs to be defined.
141
+
Configure:
142
+
143
+
- Security scheme name: `oAuth2AuthCode`
144
+
- Token value: `abc123`(not `Bearer abc123`)
42
145
43
-
For example, in the above case, we would define an environment variable named `oAuth2AuthCode`. Assuming that Authorization header value has to be `Bearer abc123`, set the value of this environment variable to `abc123` (leaving out the `Bearer ` prefix).
146
+
Specmatic sends:
147
+
148
+
- `Authorization: Bearer abc123`
44
149
45
150
### API Key
46
-
Here's an example of a Bearer security scheme in the open api specification:
151
+
152
+
OpenAPI example:
47
153
48
154
```yaml
49
155
components:
50
156
securitySchemes:
51
-
ApiKeyAuthHeader:
52
-
type: apiKey
53
-
in: header
54
-
name: X-API-KEY
157
+
ApiKeyAuthHeader:
158
+
type: apiKey
159
+
in: header
160
+
name: X-API-KEY
55
161
```
56
162
57
-
To use a real API key header in contract tests, an environment variable with the name of the security scheme needs to be defined.
163
+
Configure:
164
+
165
+
- Security scheme name: `ApiKeyAuthHeader`
166
+
- Token value: `my-api-key-abc123`
58
167
59
-
For the above example, define an environment variable named `ApiKeyAuthHeader` having the API key as its value.
168
+
Specmatic sends:
60
169
61
-
For example, in the above case, we would define an environment variable named `ApiKeyAuthHeader`. Assuming that Authorization header value has to be `my-api-key-abc123`, set the value of this environment variable to `my-api-key-abc123`.
170
+
- `X-API-KEY: my-api-key-abc123`
62
171
63
-
### Bearer
64
-
Here's an example of a Bearer security scheme in the open api specification:
172
+
### HTTP Bearer
173
+
174
+
OpenAPI example:
65
175
66
176
```yaml
67
177
components:
@@ -71,13 +181,18 @@ components:
71
181
scheme: bearer
72
182
```
73
183
74
-
To use a real bearer auth token in contract tests, an environment variable with the name of the security scheme needs to be defined.
184
+
Configure:
185
+
186
+
- Security scheme name: `BearerAuth`
187
+
- Token value: `abc123`(not `Bearer abc123`)
188
+
189
+
Specmatic sends:
75
190
76
-
For example, in the above case, we would define an environment variable named `BearerAuth`. Assuming that Authorization header value has to be `Bearer abc123`, set the value of this environment variable to `abc123` (leaving out the `Bearer ` prefix).
191
+
- `Authorization: Bearer abc123`
77
192
78
-
### Basic Authentication
193
+
### HTTP Basic
79
194
80
-
Here's an example of a Bearer security scheme in the open api specification:
195
+
OpenAPI example:
81
196
82
197
```yaml
83
198
components:
@@ -87,45 +202,57 @@ components:
87
202
scheme: basic
88
203
```
89
204
90
-
To use a real basic auth token in contract tests, an environment variable with the name of the security scheme needs to be defined.
205
+
Configure:
91
206
92
-
For example, in the above case, we would define an environment variable named `BasicAuth`. Assuming that Authorization header value has to be `Basic abc123`, set the value of this environment variable to `abc123` (leaving out the `Basic ` prefix).
207
+
- Security scheme name: `BasicAuth`
208
+
- Token value: Base64 of `username:password`
209
+
- Example: `dXNlcjpwYXNzd29yZA==`(`user:password` in Base64)
93
210
211
+
Specmatic sends:
94
212
95
-
## Testing with mock auth
213
+
- `Authorization: Basic dXNlcjpwYXNzd29yZA==`
96
214
97
-
While Specmatic supports testing with real authentication as seen above, in a component / contract test like setup, it is recommended to isolate the SUT (System Under Test) which is your service from other dependencies such as auth providers. So at a contract / component test level it is sufficient to validate if an API implementation / service accepts the security parameters it is advertising in its API Specification. However, it is not necessary to validate if the security itself is working. That is for later stages of tests where you can hook up a security service dependency such as DB, OAuth provider, etc.
215
+
## Testing with mock auth (recommended for contract/component tests)
98
216
99
-
So for Contract Tests we recommend having a “Test Security Configuration” where you are still exercise your security plumbing, however not actually fetching real user information. This is similar to running an in-memory DB in test setup instead of running a real DB in CI. Below are some examples of the same.
217
+
For contract tests, it is usually best to isolate your application from real auth providers (OAuth servers, DB-backed auth, identity services).
100
218
101
-
### OAuth2
219
+
At this stage, the main objective is to validate that:
220
+
221
+
- Your API advertises the correct auth requirements in the OpenAPI spec
222
+
- Your application accepts the expected auth headers/parameters
223
+
- Your service behavior matches the contract
224
+
225
+
You usually do **not** need to validate real token issuance/verification in contract tests. That is better covered in higher-level integration or end-to-end tests.
102
226
103
-
Please refer to this [sample API](https://github.com/specmatic/specmatic-order-contracts/blob/main/io/specmatic/examples/store/openapi/api_order_with_oauth_v3.yaml) specification which leverages [OAuth2](https://spec.openapis.org/oas/v3.0.1#implicit-oauth2-sample) to protect all endpoints that add, modify or delete data.
227
+
### Recommended approach
104
228
105
-
#### Wiring up dummy / mock authentication
229
+
Use a test security setup that:
106
230
107
-

231
+
- Checks header presence and format
232
+
- Optionally creates a dummy authenticated principal/user
233
+
- Avoids calling real auth dependencies
108
234
109
-
Please refer to [sample springboot application](https://github.com/specmatic/specmatic-order-api-java-with-oauth) that implements the [API](https://github.com/specmatic/specmatic-order-contracts/blob/main/io/specmatic/examples/store/openapi/api_order_with_oauth_v3.yaml) we saw above.
235
+
This is similar to using an in-memory database in tests instead of a production database.
110
236
111
-
### API Key Authentication
237
+
## Example: Different auth schemes per operation
112
238
113
-
Please refer to this [sample API](https://github.com/specmatic/specmatic-order-contracts/blob/main/io/specmatic/examples/store/openapi/api_order_v3.yaml) specification which leverages [ApiKeyAuth](https://spec.openapis.org/oas/v3.0.1#api-key-sample) to protect all endpoints that add, modify or delete data.
239
+
Specmatic supports different auth schemes for different endpoints in the same OpenAPI specification.
114
240
115
-
#### Wiring up dummy / mock authentication
241
+
Example use case:
116
242
117
-
Please refer to [sample springboot application](https://github.com/specmatic/specmatic-order-api-java) that implements the [API](https://github.com/specmatic/specmatic-order-contracts/blob/main/io/specmatic/examples/store/openapi/api_order_v3.yaml) we saw above.
243
+
- `POST`endpoints use **OAuth2**
244
+
- `GET`endpoints use **Basic Auth**
245
+
- `DELETE`endpoints use **API Key**
118
246
119
-
This has two API security configurations
120
-
* [Production Security Config](https://github.com/specmatic/specmatic-order-api-java/blob/main/src/main/java/com/store/config/SecurityConfig.kt) - This fetches user from the DB based on api token in request header
121
-
* [Test Security Config](https://github.com/specmatic/specmatic-order-api-java/blob/main/src/test/java/com/store/config/TestSecurityConfig.kt) - This always returns a dummy user principal. However, rest of the code such as reading the authentication token from header etc. are still tested.
247
+
Specmatic reads the operation-level `security` entries and sends the appropriate auth header for each request.
122
248
123
-
So when you run the [ContractTest](https://github.com/specmatic/specmatic-order-api-java/blob/main/src/test/java/com/store/ContractTest.java) it will still exercise your security plumbing (does the application accept the proper header name, datatype, etc.).
This is just an example of how we can wire up security configurations for test and production environments. Even in SpringBoot you can leverage other techniques such as [Spring Profiles](https://docs.spring.io/spring-boot/docs/1.2.0.M1/reference/html/boot-features-profiles.html) to achieve the same effect.
252
+
## Tips
126
253
127
-
The same can be achieved in almost any programming language and stack.
128
-
* Dot Net - Register a custom [AuthenticationHandler](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.authenticationhandler-1?view=aspnetcore-7.0) for mock authentication in tests
129
-
* Node.js - Switch auth middleware based on ```process.env.NODE_ENV```
254
+
- Security scheme names in `specmatic.yaml` must match names in `components.securitySchemes`.
255
+
- If an operation defines `security`, it overrides global `security`.
256
+
- Use environment variables in `specmatic.yaml` to switch credentials across local, CI, and test environments.
257
+
- For contract tests, prefer mock/dummy auth unless your test specifically needs real auth.
130
258
131
-
In general the overall idea is to inject a mock authentication mechanism while running Specmatic Contract Tests
0 commit comments