From 307b7dbab9f1333d221d5a0d748ce1eda3573fac Mon Sep 17 00:00:00 2001 From: Matheus Cruz Date: Tue, 9 Jun 2026 14:43:51 -0300 Subject: [PATCH 1/2] Fix a typo Signed-off-by: Matheus Cruz --- adr/v1.0-adr-openapi-auth-auto-resolution.md | 215 +++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 adr/v1.0-adr-openapi-auth-auto-resolution.md diff --git a/adr/v1.0-adr-openapi-auth-auto-resolution.md b/adr/v1.0-adr-openapi-auth-auto-resolution.md new file mode 100644 index 00000000..ac1a4ac9 --- /dev/null +++ b/adr/v1.0-adr-openapi-auth-auto-resolution.md @@ -0,0 +1,215 @@ +# ADR: Automatic Authentication Resolution from OpenAPI Security Schemes + +## Status + +Proposed + +## Related Issue + +TBD + +## Context + +The Serverless Workflow specification currently supports OpenAPI as a first-class call type (`call: openapi`), allowing workflows to interact with external services described by OpenAPI documents. These documents already contain rich security metadata through the `securitySchemes` and `security` sections defined by the [OpenAPI Specification](https://swagger.io/docs/specification/v3_0/authentication/), including the authentication type, grant flows, scopes, and how credentials should be transmitted. + +However, today, when a workflow author uses `call: openapi`, they must manually define the `authentication` property on the call, essentially **duplicating** information that the OpenAPI document already provides. This creates several issues: + +- **Redundancy**: The workflow author must re-declare auth schemes (e.g. OAuth2 client credentials, bearer token) that are already described in the OpenAPI document they are referencing +- **Drift risk**: If the API provider updates their security requirements (e.g. adds new scopes, changes the token endpoint), the workflow definition can fall out of sync with the actual API contract +- **Friction for adoption**: Users coming from the OpenAPI ecosystem expect security schemes to "just work" when they point to an OpenAPI document - having to manually map them is unexpected and error-prone +- **Inconsistency with the A2A call**: The [A2A call type](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#a2a-call) already acknowledges that the AgentCard's `security` and `securitySchemes` fields contain authentication requirements - but we do not apply the same reasoning to OpenAPI documents + +Consider the following scenario: an OpenAPI document defines an operation `findPetsByStatus` that requires OAuth2 with `client_credentials` grant and `read:pets` scope. Today, the workflow author must write: + +```yaml +do: + - findPets: + call: openapi + with: + document: + endpoint: https://petstore.swagger.io/v3/openapi.json + operationId: findPetsByStatus + parameters: + status: available + authentication: + oauth2: + authority: https://petstore.swagger.io/oauth/authorize + grant: client_credentials + client: + id: my-client-id + secret: my-client-secret + scopes: + - read:pets +``` + +The authority URL, grant type, and scopes are all already present in the OpenAPI document. The only pieces the workflow author actually needs to provide are the **credentials** (client ID and secret), since these are deployment-specific and should never live inside an API specification. + +## Decision + +We propose extending the behavior of the `call: openapi` task to support **automatic resolution of authentication schemes** from the referenced OpenAPI document's `securitySchemes` definitions. + +### How It Works + +When a runtime processes a `call: openapi` task: + +1. **Parse the OpenAPI document** referenced in the `document` property +2. **Resolve the security requirement** for the target `operationId` - either the operation-level `security` or the global `security` if no operation-level override exists +3. **Look up the corresponding `securitySchemes`** entry under `components/securitySchemes` +4. **Map the OpenAPI security scheme to the Serverless Workflow authentication policy** (see mapping table below) +5. **Merge with workflow-provided credentials** - the workflow author provides only what cannot be derived from the OpenAPI document (secrets, tokens, client credentials) + +If the workflow explicitly defines `authentication` on the call, it takes precedence and no automatic resolution is performed. This preserves backward compatibility and gives authors full control when needed. + +### OpenAPI to Serverless Workflow Authentication Mapping + +| OpenAPI Security Scheme | Serverless Workflow Auth | Resolved From OpenAPI | Provided By Workflow | +|:--|:--|:--|:--| +| `type: http`, `scheme: basic` | `basic` | Scheme type | `username`, `password` (or secret reference) | +| `type: http`, `scheme: bearer` | `bearer` | Scheme type, `bearerFormat` | `token` (or secret reference) | +| `type: oauth2` | `oauth2` | `flows` (grant type), `authorizationUrl`, `tokenUrl`, `scopes` | `client.id`, `client.secret` (or secret reference) | +| `type: openIdConnect` | `oidc` | `openIdConnectUrl` (maps to `authority`) | `client.id`, `client.secret` (or secret reference) | +| `type: apiKey` | *See notes below* | `in` (header/query/cookie), `name` | The API key value (or secret reference) | + +### API Key Handling + +OpenAPI's `apiKey` type does not have a direct equivalent in the current Serverless Workflow authentication schemes. API keys are transmitted as headers, query parameters, or cookies - which is a transport-level concern rather than an authentication protocol. + +We propose two options: + +1. **Header/query injection (preferred)**: When the runtime resolves an `apiKey` security scheme, it automatically injects the key into the appropriate location (header, query, or cookie) based on the `in` and `name` fields from the OpenAPI document. The workflow author provides only the key value via a secret reference. + +2. **Map to bearer**: For `apiKey` schemes transmitted via the `Authorization` header, treat them as bearer tokens. + +### OAuth2 Flow Mapping + +OpenAPI defines four OAuth2 flow types that map to the existing Serverless Workflow `grant` values: + +| OpenAPI OAuth2 Flow | Serverless Workflow `grant` | +|:--|:--| +| `clientCredentials` | `client_credentials` | +| `authorizationCode` | `authorization_code` | +| `password` | `password` | +| `implicit` | *Not supported - runtime should emit a warning* | + +The `tokenUrl` from the OpenAPI flow maps to the `authority` (or can be used to derive the token endpoint), and the `scopes` defined at the operation level in the `security` requirement are automatically applied. + +### Credential Provision + +Since credentials are deployment-specific and should not live in OpenAPI documents, the workflow author still needs to provide them. We propose a lightweight `credentials` property as an alternative to the full `authentication` block when using auto-resolution: + +```yaml +do: + - findPets: + call: openapi + with: + document: + endpoint: https://petstore.swagger.io/v3/openapi.json + operationId: findPetsByStatus + parameters: + status: available + credentials: + use: petStoreCredentials +``` + +Where `petStoreCredentials` is a secret containing the client ID, client secret, token, API key, or username/password pair - depending on the resolved scheme. + +Alternatively, the workflow can still use the existing `authentication` property to provide only the credential portion, and the runtime merges it with the resolved scheme: + +```yaml +do: + - findPets: + call: openapi + with: + document: + endpoint: https://petstore.swagger.io/v3/openapi.json + operationId: findPetsByStatus + parameters: + status: available + authentication: + oauth2: + client: + id: my-client-id + secret: my-client-secret +``` + +In this case, the runtime fills in `authority`, `grant`, and `scopes` from the OpenAPI document while using the client credentials from the workflow definition. + +### Multiple Security Requirements + +OpenAPI supports combining multiple security schemes using logical OR and AND: + +- **OR** (array items): `[SchemeA, SchemeB]` - either scheme is acceptable +- **AND** (combined in one object): `[{SchemeA, SchemeB}]` - both are required simultaneously + +For **OR** scenarios, the runtime should attempt to resolve the first scheme for which the workflow has provided valid credentials. For **AND** scenarios, the runtime must resolve and apply all required schemes. + +### Resolution Behavior Summary + +| Scenario | Behavior | +|:--|:--| +| `authentication` explicitly set | Use it as-is, no auto-resolution | +| `authentication` partially set (e.g. only credentials) | Merge with resolved OpenAPI scheme | +| `credentials` set, no `authentication` | Fully resolve from OpenAPI, apply credentials | +| Neither `authentication` nor `credentials` set | Resolve from OpenAPI; if operation requires auth and no credentials found, raise an error | +| OpenAPI operation has no security requirement | No authentication applied | +| OpenAPI operation has `security: []` (explicitly unsecured) | No authentication applied | + +## Consequences + +### Positive + +- **Reduces boilerplate**: Workflow authors no longer need to duplicate security scheme details that the OpenAPI document already provides +- **Keeps workflows in sync with API contracts**: Auth configuration is derived from the source of truth (the OpenAPI document) at runtime, so changes to the API's security requirements are automatically picked up +- **Lowers the entry barrier**: Users familiar with OpenAPI expect security schemes to be honored - this makes the Serverless Workflow specification behave as expected +- **Aligns with A2A precedent**: The A2A call type already acknowledges the security metadata in the AgentCard - this brings parity to the OpenAPI call type +- **Backward compatible**: Explicit `authentication` on the call still takes precedence, no existing workflow definitions break + +### Trade-Offs + +- **Runtime complexity**: Runtimes must implement OpenAPI document parsing and security scheme resolution, which adds implementation effort +- **Network dependency**: The runtime must fetch and parse the OpenAPI document before it can resolve the security scheme (though it likely already does this to resolve the `operationId`) +- **API Key gap**: The `apiKey` scheme type has no direct authentication equivalent in the current spec and requires special handling +- **Implicit vs explicit**: Auto-resolution makes the auth behavior less visible in the workflow definition itself - debugging may require inspecting the OpenAPI document to understand which auth scheme is being used +- **OpenAPI version support**: The runtime must handle differences between OpenAPI 3.0 and 3.1 security scheme definitions (though these are minimal) + +## Open Questions + +1. **Should this extend to other call types?** The AsyncAPI specification also defines security schemes. Should we apply the same auto-resolution pattern to `call: asyncapi`? + +2. **Caching**: Should runtimes cache the parsed OpenAPI document's security schemes, or re-resolve on each invocation? Caching improves performance but may miss security changes. + +3. **`apiKey` support**: Should we add a new `apiKey` authentication scheme to the Serverless Workflow specification to fully support this OpenAPI type, or is header/query injection sufficient? + +4. **`credentials` property**: Is a new `credentials` property worth the added surface area, or should we rely on the existing `authentication` property with partial definitions and merge semantics? + +## Milestones + +### Milestone 1 (Target: TBD) - Specification Changes + +- Define the auto-resolution behavior in the DSL specification +- Update the OpenAPI call documentation with the new behavior and examples +- Define the resolution precedence rules (explicit > partial merge > auto-resolve) +- Decide on the `credentials` property vs. merge-based approach +- Update the JSON schema to reflect any new properties + +### Milestone 2 (Target: TBD) - Reference Implementation + +- Implement OpenAPI security scheme parsing in at least one reference runtime +- Support `http` (basic/bearer), `oauth2`, and `openIdConnect` scheme resolution +- Implement credential merging logic +- Handle `apiKey` scheme (header/query injection) +- Add conformance tests for the auto-resolution behavior + +### Milestone 3 (Target: TBD) - Extended Protocol Support + +- Evaluate and implement the same pattern for AsyncAPI security schemes +- Document best practices and migration guide for existing workflows +- Collect community feedback and iterate on the design + +## References + +- [OpenAPI 3.0 Authentication](https://swagger.io/docs/specification/v3_0/authentication/) +- [OpenAPI 3.0 Security Scheme Object](https://swagger.io/specification/v3/#security-scheme-object) +- [Serverless Workflow DSL - Authentication](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#authentication) +- [Serverless Workflow DSL - OpenAPI Call](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#openapi-call) +- [Serverless Workflow DSL - A2A Call](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#a2a-call) From 20d54aa25e108a4901c0a67acec5e8d002a9f094 Mon Sep 17 00:00:00 2001 From: Matheus Cruz Date: Mon, 3 Aug 2026 12:06:49 -0300 Subject: [PATCH 2/2] Remove ADR Signed-off-by: Matheus Cruz --- adr/v1.0-adr-openapi-auth-auto-resolution.md | 215 ------------------- 1 file changed, 215 deletions(-) delete mode 100644 adr/v1.0-adr-openapi-auth-auto-resolution.md diff --git a/adr/v1.0-adr-openapi-auth-auto-resolution.md b/adr/v1.0-adr-openapi-auth-auto-resolution.md deleted file mode 100644 index ac1a4ac9..00000000 --- a/adr/v1.0-adr-openapi-auth-auto-resolution.md +++ /dev/null @@ -1,215 +0,0 @@ -# ADR: Automatic Authentication Resolution from OpenAPI Security Schemes - -## Status - -Proposed - -## Related Issue - -TBD - -## Context - -The Serverless Workflow specification currently supports OpenAPI as a first-class call type (`call: openapi`), allowing workflows to interact with external services described by OpenAPI documents. These documents already contain rich security metadata through the `securitySchemes` and `security` sections defined by the [OpenAPI Specification](https://swagger.io/docs/specification/v3_0/authentication/), including the authentication type, grant flows, scopes, and how credentials should be transmitted. - -However, today, when a workflow author uses `call: openapi`, they must manually define the `authentication` property on the call, essentially **duplicating** information that the OpenAPI document already provides. This creates several issues: - -- **Redundancy**: The workflow author must re-declare auth schemes (e.g. OAuth2 client credentials, bearer token) that are already described in the OpenAPI document they are referencing -- **Drift risk**: If the API provider updates their security requirements (e.g. adds new scopes, changes the token endpoint), the workflow definition can fall out of sync with the actual API contract -- **Friction for adoption**: Users coming from the OpenAPI ecosystem expect security schemes to "just work" when they point to an OpenAPI document - having to manually map them is unexpected and error-prone -- **Inconsistency with the A2A call**: The [A2A call type](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#a2a-call) already acknowledges that the AgentCard's `security` and `securitySchemes` fields contain authentication requirements - but we do not apply the same reasoning to OpenAPI documents - -Consider the following scenario: an OpenAPI document defines an operation `findPetsByStatus` that requires OAuth2 with `client_credentials` grant and `read:pets` scope. Today, the workflow author must write: - -```yaml -do: - - findPets: - call: openapi - with: - document: - endpoint: https://petstore.swagger.io/v3/openapi.json - operationId: findPetsByStatus - parameters: - status: available - authentication: - oauth2: - authority: https://petstore.swagger.io/oauth/authorize - grant: client_credentials - client: - id: my-client-id - secret: my-client-secret - scopes: - - read:pets -``` - -The authority URL, grant type, and scopes are all already present in the OpenAPI document. The only pieces the workflow author actually needs to provide are the **credentials** (client ID and secret), since these are deployment-specific and should never live inside an API specification. - -## Decision - -We propose extending the behavior of the `call: openapi` task to support **automatic resolution of authentication schemes** from the referenced OpenAPI document's `securitySchemes` definitions. - -### How It Works - -When a runtime processes a `call: openapi` task: - -1. **Parse the OpenAPI document** referenced in the `document` property -2. **Resolve the security requirement** for the target `operationId` - either the operation-level `security` or the global `security` if no operation-level override exists -3. **Look up the corresponding `securitySchemes`** entry under `components/securitySchemes` -4. **Map the OpenAPI security scheme to the Serverless Workflow authentication policy** (see mapping table below) -5. **Merge with workflow-provided credentials** - the workflow author provides only what cannot be derived from the OpenAPI document (secrets, tokens, client credentials) - -If the workflow explicitly defines `authentication` on the call, it takes precedence and no automatic resolution is performed. This preserves backward compatibility and gives authors full control when needed. - -### OpenAPI to Serverless Workflow Authentication Mapping - -| OpenAPI Security Scheme | Serverless Workflow Auth | Resolved From OpenAPI | Provided By Workflow | -|:--|:--|:--|:--| -| `type: http`, `scheme: basic` | `basic` | Scheme type | `username`, `password` (or secret reference) | -| `type: http`, `scheme: bearer` | `bearer` | Scheme type, `bearerFormat` | `token` (or secret reference) | -| `type: oauth2` | `oauth2` | `flows` (grant type), `authorizationUrl`, `tokenUrl`, `scopes` | `client.id`, `client.secret` (or secret reference) | -| `type: openIdConnect` | `oidc` | `openIdConnectUrl` (maps to `authority`) | `client.id`, `client.secret` (or secret reference) | -| `type: apiKey` | *See notes below* | `in` (header/query/cookie), `name` | The API key value (or secret reference) | - -### API Key Handling - -OpenAPI's `apiKey` type does not have a direct equivalent in the current Serverless Workflow authentication schemes. API keys are transmitted as headers, query parameters, or cookies - which is a transport-level concern rather than an authentication protocol. - -We propose two options: - -1. **Header/query injection (preferred)**: When the runtime resolves an `apiKey` security scheme, it automatically injects the key into the appropriate location (header, query, or cookie) based on the `in` and `name` fields from the OpenAPI document. The workflow author provides only the key value via a secret reference. - -2. **Map to bearer**: For `apiKey` schemes transmitted via the `Authorization` header, treat them as bearer tokens. - -### OAuth2 Flow Mapping - -OpenAPI defines four OAuth2 flow types that map to the existing Serverless Workflow `grant` values: - -| OpenAPI OAuth2 Flow | Serverless Workflow `grant` | -|:--|:--| -| `clientCredentials` | `client_credentials` | -| `authorizationCode` | `authorization_code` | -| `password` | `password` | -| `implicit` | *Not supported - runtime should emit a warning* | - -The `tokenUrl` from the OpenAPI flow maps to the `authority` (or can be used to derive the token endpoint), and the `scopes` defined at the operation level in the `security` requirement are automatically applied. - -### Credential Provision - -Since credentials are deployment-specific and should not live in OpenAPI documents, the workflow author still needs to provide them. We propose a lightweight `credentials` property as an alternative to the full `authentication` block when using auto-resolution: - -```yaml -do: - - findPets: - call: openapi - with: - document: - endpoint: https://petstore.swagger.io/v3/openapi.json - operationId: findPetsByStatus - parameters: - status: available - credentials: - use: petStoreCredentials -``` - -Where `petStoreCredentials` is a secret containing the client ID, client secret, token, API key, or username/password pair - depending on the resolved scheme. - -Alternatively, the workflow can still use the existing `authentication` property to provide only the credential portion, and the runtime merges it with the resolved scheme: - -```yaml -do: - - findPets: - call: openapi - with: - document: - endpoint: https://petstore.swagger.io/v3/openapi.json - operationId: findPetsByStatus - parameters: - status: available - authentication: - oauth2: - client: - id: my-client-id - secret: my-client-secret -``` - -In this case, the runtime fills in `authority`, `grant`, and `scopes` from the OpenAPI document while using the client credentials from the workflow definition. - -### Multiple Security Requirements - -OpenAPI supports combining multiple security schemes using logical OR and AND: - -- **OR** (array items): `[SchemeA, SchemeB]` - either scheme is acceptable -- **AND** (combined in one object): `[{SchemeA, SchemeB}]` - both are required simultaneously - -For **OR** scenarios, the runtime should attempt to resolve the first scheme for which the workflow has provided valid credentials. For **AND** scenarios, the runtime must resolve and apply all required schemes. - -### Resolution Behavior Summary - -| Scenario | Behavior | -|:--|:--| -| `authentication` explicitly set | Use it as-is, no auto-resolution | -| `authentication` partially set (e.g. only credentials) | Merge with resolved OpenAPI scheme | -| `credentials` set, no `authentication` | Fully resolve from OpenAPI, apply credentials | -| Neither `authentication` nor `credentials` set | Resolve from OpenAPI; if operation requires auth and no credentials found, raise an error | -| OpenAPI operation has no security requirement | No authentication applied | -| OpenAPI operation has `security: []` (explicitly unsecured) | No authentication applied | - -## Consequences - -### Positive - -- **Reduces boilerplate**: Workflow authors no longer need to duplicate security scheme details that the OpenAPI document already provides -- **Keeps workflows in sync with API contracts**: Auth configuration is derived from the source of truth (the OpenAPI document) at runtime, so changes to the API's security requirements are automatically picked up -- **Lowers the entry barrier**: Users familiar with OpenAPI expect security schemes to be honored - this makes the Serverless Workflow specification behave as expected -- **Aligns with A2A precedent**: The A2A call type already acknowledges the security metadata in the AgentCard - this brings parity to the OpenAPI call type -- **Backward compatible**: Explicit `authentication` on the call still takes precedence, no existing workflow definitions break - -### Trade-Offs - -- **Runtime complexity**: Runtimes must implement OpenAPI document parsing and security scheme resolution, which adds implementation effort -- **Network dependency**: The runtime must fetch and parse the OpenAPI document before it can resolve the security scheme (though it likely already does this to resolve the `operationId`) -- **API Key gap**: The `apiKey` scheme type has no direct authentication equivalent in the current spec and requires special handling -- **Implicit vs explicit**: Auto-resolution makes the auth behavior less visible in the workflow definition itself - debugging may require inspecting the OpenAPI document to understand which auth scheme is being used -- **OpenAPI version support**: The runtime must handle differences between OpenAPI 3.0 and 3.1 security scheme definitions (though these are minimal) - -## Open Questions - -1. **Should this extend to other call types?** The AsyncAPI specification also defines security schemes. Should we apply the same auto-resolution pattern to `call: asyncapi`? - -2. **Caching**: Should runtimes cache the parsed OpenAPI document's security schemes, or re-resolve on each invocation? Caching improves performance but may miss security changes. - -3. **`apiKey` support**: Should we add a new `apiKey` authentication scheme to the Serverless Workflow specification to fully support this OpenAPI type, or is header/query injection sufficient? - -4. **`credentials` property**: Is a new `credentials` property worth the added surface area, or should we rely on the existing `authentication` property with partial definitions and merge semantics? - -## Milestones - -### Milestone 1 (Target: TBD) - Specification Changes - -- Define the auto-resolution behavior in the DSL specification -- Update the OpenAPI call documentation with the new behavior and examples -- Define the resolution precedence rules (explicit > partial merge > auto-resolve) -- Decide on the `credentials` property vs. merge-based approach -- Update the JSON schema to reflect any new properties - -### Milestone 2 (Target: TBD) - Reference Implementation - -- Implement OpenAPI security scheme parsing in at least one reference runtime -- Support `http` (basic/bearer), `oauth2`, and `openIdConnect` scheme resolution -- Implement credential merging logic -- Handle `apiKey` scheme (header/query injection) -- Add conformance tests for the auto-resolution behavior - -### Milestone 3 (Target: TBD) - Extended Protocol Support - -- Evaluate and implement the same pattern for AsyncAPI security schemes -- Document best practices and migration guide for existing workflows -- Collect community feedback and iterate on the design - -## References - -- [OpenAPI 3.0 Authentication](https://swagger.io/docs/specification/v3_0/authentication/) -- [OpenAPI 3.0 Security Scheme Object](https://swagger.io/specification/v3/#security-scheme-object) -- [Serverless Workflow DSL - Authentication](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#authentication) -- [Serverless Workflow DSL - OpenAPI Call](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#openapi-call) -- [Serverless Workflow DSL - A2A Call](https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#a2a-call)