Use Respect powered by Arazzo workflows to test API endpoints that require OAuth2 authorization. Learn how to define reusable workflows in separate files, pass values between workflows, and use those values to authorize API requests.
You are going to:
- Create reusable workflows with exposed outputs.
- Authorize API requests with OAuth2.
- Use the
x-securityRespect extension with a protected API operation.
In the Test API contracts using Respect tutorial, you learned how to execute an API contract test with Redocly Respect. Let's create a more realistic workflow: calling protected API endpoints.
Real APIs are rarely open to public access. They usually require an authentication or authorization flow before clients can read or change protected resources. To test those endpoints with Respect, the workflow must first obtain credentials or an access token, then use that authorization data in later steps.
Respect supports this use case with the x-security extension, which lets a workflow provide security values for protected operations.
- Familiarity with the
x-securityextension. - An API described with OpenAPI. The examples use a modified version of the Redocly Cafe API description.
Open redocly-cafe-api.yaml in the right panel. The walkthrough focuses on three pieces: the protected POST /menu operation, the OAuth2 security scheme, and the dynamic client registration endpoint.
Protected POST /menu operation
POST /menu creates a menu item. The operation declares OAuth2 with the menu:write scope under security, which means callers must present a valid OAuth2 access token with that scope.
The plain GET /menu operation, by contrast, leaves security empty and is publicly accessible.
POST /oauth2/register
The API supports dynamic client registration through POST /oauth2/register. This endpoint is itself unauthenticated (security: []) and returns a new clientId and clientSecret that we can use to obtain an access token.
This flow follows the Dynamic Client Registration Protocol (RFC 7591).
OAuth2 security scheme
The OAuth2 security scheme defines two flows: authorizationCode and clientCredentials. Both publish a tokenUrl and the menu:read and menu:write scopes.
This walkthrough uses these endpoints (and scopes) to obtain an access token and call the protected POST /menu operation.
Because client registration is useful in more than one workflow, describe it in its own Arazzo file and reuse it later. Keeping the authorization details in a dedicated workflow keeps the protected-operation tests focused on the operation under test.
Switch to register-oauth2-client.arazzo.yaml in the right panel.
Reference the OpenAPI description
The workflow declares a single OpenAPI source. Operations in that source are accessible through $sourceDescriptions.redocly-cafe-api.<operationId>.
Define the registration workflow
The file declares one workflow, register-oauth2-client-workflow that registers a new client and exposes its credentials as workflow-level outputs.
A single registration step
The workflow has just one step, register-oauth2-client, which calls the registration operation.
Connect the step to the operation
The step targets the registerOAuth2Client operation from the connected OpenAPI source. Because the step is connected to a documented operation, Respect can automatically validate the response status, content type, and body schema.
Supply the request body
Because this is a POST request, the step provides a requestBody.payload with the client metadata. Here we request only the client_credentials grant type and ask for both menu scopes.
Assert the response shape
The step asserts a 201 status code and the presence of clientId and clientSecret in the response body.
Capture step outputs
The step extracts clientId and clientSecret from the response body and stores them as step outputs. Other steps in the same workflow can reference them through $steps.register-oauth2-client.outputs.<name>.
Expose workflow outputs
To make these values available to other Arazzo files that reuse this workflow, the same values are also exposed as workflow-level outputs. This promotion is the bridge between a reusable workflow and the workflows that consume it.
Execute the file with Redocly CLI to inspect the API response and confirm which values are mapped to workflow outputs:
npx @redocly/cli respect register-oauth2-client.arazzo.yaml --verboseSwitch to authorization.arazzo.yaml in the right panel. This workflow exchanges the registered client for an access token in two steps:
- Reuse
register-oauth2-client-workflowto get aclientIdandclientSecret. - Call the token endpoint and expose the returned access token as a workflow output.
Multiple source descriptions
This file declares two sources: the OpenAPI description (redocly-cafe-api) and the previous Arazzo file (register-oauth2).
Arazzo source descriptions are not limited to OpenAPI - another Arazzo document is a valid source too.
Reusable Arazzo source
Adding the registration file as a source with type: arazzo is what enables reuse. A step can now reference the registration workflow by id, just like operations reference OpenAPI operationIds.
Call the reusable workflow
The first step uses workflowId (not operationId) to call the registration workflow from the other Arazzo file.
Its outputs mirror the workflow-level outputs we exposed earlier (clientId, clientSecret), which makes them available locally as $steps.register-oauth2-client.outputs.*.
Call the token endpoint
The second step, authorize-with-client_credentials, calls /oauth2/token using the credentials returned by the previous step.
This walkthrough uses the client credentials grant, a machine-to-machine flow where the client authenticates itself directly with client_id and client_secret. There is no user-agent or browser involved, so no redirect_uri or /callback is needed - the token is returned directly in the response to this single request.
x-operation extension
/oauth2/token is not described as an operationId in the OpenAPI file, so the step uses the x-operation Respect extension to declare the request URL and method inline.
Use x-operation whenever you need to call a URL that is not part of the OpenAPI description.
Token request body
The token request body follows the OAuth2 spec: grant_type, client_id, and client_secret. The credentials are read from the previous step's outputs using $steps.register-oauth2-client.outputs.*.
Capture the access token
The step extracts access_token from the response body so the next workflow can use it to authorize protected requests.
Expose the authorization outputs
Just like the registration workflow, the authorization workflow exposes its outputs at the workflow level so any consumer Arazzo file can read access_token_with_client_credentials and client_id.
Execute this file:
npx @redocly/cli respect authorization.arazzo.yaml --verboseInspect the response body of the last step. It contains the access_token used by the final workflow:
Response Body:
{
"access_token": "********",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "menu:read menu:write"
}
✓ success criteria check - $statusCode == 200
✓ success criteria check - $response.body#/access_token != nullSwitch to redocly-cafe-api.arazzo.yaml in the right panel. This is the workflow you run in CI:
- The
authorizestep calls the reusable authorization workflow. - The
create-menu-itemstep readsaccess_tokenandclient_idfrom theauthorizestep outputs. - The
x-securityextension automatically constructs the appropriate authorization headers, query parameters, or cookies for the protectedcreateMenuItemoperation.
Combine the OpenAPI and authorization sources
The final file references two sources: the OpenAPI description for the operations under test, and the authorization Arazzo file for the access token.
Reuse the authorization workflow
The first step calls authorize-with-client_credentials from the authorization file and stores the access token and client id locally.
This reuse pattern is exactly the same as the one inside authorization.arazzo.yaml, but now applied one level higher.
Create a menu item
The create-menu-item step calls the protected createMenuItem operation. It uses $faker.string.uuid() to generate a unique name so the test is repeatable.
Provide credentials with x-security
The x-security extension tells Respect which security scheme to satisfy and how.
Here the workflow passes the accessToken and clientId it received from the authorize step. Respect reads the security scheme from the OpenAPI description and adds the right headers automatically - you do not need to construct Authorization: Bearer ... yourself.
The protected operation
This is the operation the step targets back in redocly-cafe-api.yaml. Note the security block listing OAuth2 with the menu:write scope - that is exactly what the x-security block satisfies.
Send a multipart/form-data body
createMenuItem accepts multipart/form-data, so the step declares contentType explicitly and supplies the form fields as payload.
Verify the menu item
The final step lists menu items and asserts that the item created in the previous step exists. This step uses outputs from create-menu-item directly in a request parameter and in a success criterion.
Run the workflow to confirm that the authorization step, the protected POST request, and the verification step all pass:
npx @redocly/cli respect redocly-cafe-api.arazzo.yaml --verboseRespect extensions make it possible to describe authorized API requests as part of an Arazzo workflow.
By splitting the process into smaller workflows with outputs, you can reuse authentication and authorization steps across multiple API contract tests. Reuse keeps complex workflows easier to maintain while still testing realistic protected API behavior.
arazzo: 1.0.1
info:
title: Redocly Cafe API - Products
version: 1.0.0
description: This is the API workflow for the Redocly Cafe Products.
sourceDescriptions:
- name: redocly-cafe-api
type: openapi
url: redocly-cafe-api.yaml
- name: authorization
type: arazzo
url: authorization.arazzo.yaml
workflows:
- workflowId: menu-items-workflow
summary: Menu Items Workflow
steps:
- stepId: authorize
workflowId: $sourceDescriptions.authorization.workflows.authorize-with-client_credentials
outputs:
access_token: $outputs.access_token_with_client_credentials
client_id: $outputs.client_id
- stepId: create-menu-item
operationId: $sourceDescriptions.redocly-cafe-api.createMenuItem
description: This step creates a new menu item.
x-security:
- schemeName: OAuth2
values:
accessToken: $steps.authorize.outputs.access_token
clientId: $steps.authorize.outputs.client_id
requestBody:
contentType: multipart/form-data
payload:
name: $faker.string.uuid()
price: 4000
calories: 8000
category: 'dessert'
photoTextDescription: 'this is a tiramisu'
successCriteria:
- condition: $statusCode == 201
- condition: $response.body#/id != null
outputs:
menuItemId: $response.body#/id
name: $response.body#/name
- stepId: verify-menu-item
operationId: $sourceDescriptions.redocly-cafe-api.listMenuItems
description: Verifies the created menu item
parameters:
- in: query
name: filter
value: 'name:{$steps.create-menu-item.outputs.name}'
successCriteria:
- condition: $statusCode == 200
- condition: $response.body#/items/0/name == $steps.create-menu-item.outputs.name