Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions examples/SECURITY_AND_LOGIC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Security Logic Examples

This document demonstrates the difference between OR logic (existing) and AND logic (new feature) in AsyncAPI 3.x security schemes.

## OR Logic (Single-Level Array) - Existing Behavior

When security is defined as a single-level array, **only ONE** of the security schemes needs to be satisfied:

```yaml
security:
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
- $ref: '#/components/securitySchemes/basicAuth'
```

**Meaning**: OAuth2 **OR** API Key **OR** Basic Auth

## AND Logic (Array of Arrays) - New Feature

When security is defined as an array of arrays, the **outer array represents OR** while **inner arrays represent AND**:

```yaml
security:
# Option 1: OAuth2 AND API Key (both required)
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
# OR Option 2: Client Certificate alone
-
- $ref: '#/components/securitySchemes/clientCertificate'
```

**Meaning**: (OAuth2 **AND** API Key) **OR** (Client Certificate)

## Real-World Use Cases

### Use Case 1: Defense in Depth

Require multiple authentication methods for sensitive operations:

```yaml
operations:
deleteUserData:
action: send
channel:
$ref: '#/channels/userDeletion'
security:
# Require BOTH OAuth2 token AND API key for deletion
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
```

### Use Case 2: Flexible Authentication with Fallback

Allow different authentication combinations:

```yaml
servers:
production:
host: api.example.com
protocol: https
security:
# Option 1: Modern auth - OAuth2 AND HMAC signature
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/hmacSignature'
# Option 2: Legacy auth - Basic auth AND API key
-
- $ref: '#/components/securitySchemes/basicAuth'
- $ref: '#/components/securitySchemes/apiKey'
# Option 3: High-security - mTLS alone
-
- $ref: '#/components/securitySchemes/clientCertificate'
```

**Meaning**:
- (OAuth2 **AND** HMAC)
- **OR** (Basic Auth **AND** API Key)
- **OR** (mTLS)

### Use Case 3: Request Signing with Authentication

Common in financial APIs where you need both identity and integrity:

```yaml
operations:
processPayment:
action: send
channel:
$ref: '#/channels/payments'
security:
# Require OAuth2 for identity AND HMAC for request integrity
-
- type: oauth2
flows:
clientCredentials:
tokenUrl: https://auth.example.com/token
scopes:
'payments:write': Process payments
- type: httpApiKey
name: X-Signature
in: header
description: HMAC signature of request body
```

## Backward Compatibility

The new AND logic syntax is **fully backward compatible**:

- **Existing specs** using single-level arrays continue to work with OR logic
- **New specs** can use array of arrays for AND logic
- **Validators** should support both formats

### Migration Example

**Before (OR logic only)**:
```yaml
security:
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
```
Meaning: OAuth2 **OR** API Key

**After (AND logic support)** - Same behavior:
```yaml
security:
-
- $ref: '#/components/securitySchemes/oauth2'
-
- $ref: '#/components/securitySchemes/apiKey'
```
Meaning: OAuth2 **OR** API Key

**After (AND logic)** - New requirement:
```yaml
security:
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
```
Meaning: OAuth2 **AND** API Key

## Validation Rules

Tools implementing this feature should enforce:

1. **Outer array**: Represents OR logic between security options
2. **Inner array**: Represents AND logic within each option
3. **All schemes in an inner array** MUST be satisfied simultaneously
4. **At least one inner array** MUST be fully satisfied for authorization
5. **Single-level arrays** continue to use OR logic for backward compatibility

## Complete Example

See [security-and-logic-asyncapi.yml](./security-and-logic-asyncapi.yml) for a complete working example.
94 changes: 94 additions & 0 deletions examples/security-and-logic-asyncapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
asyncapi: 3.0.0
info:
title: Security AND Logic Example
version: 1.0.0
description: |
This example demonstrates the use of AND logic for multiple security schemes.
The API requires BOTH OAuth2 AND API Key authentication simultaneously.

servers:
production:
host: api.example.com
protocol: https
description: Production server requiring both OAuth2 and API Key
security:
# Outer array for OR logic - only one group needs to be satisfied
# Inner array for AND logic - all schemes in the group must be satisfied
-
# This inner array requires BOTH OAuth2 AND API Key
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'

channels:
userEvents:
address: /users/events
messages:
userCreated:
$ref: '#/components/messages/UserCreated'

operations:
receiveUserEvents:
action: receive
channel:
$ref: '#/channels/userEvents'
security:
# Example 1: Require OAuth2 AND API Key together
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
messages:
- $ref: '#/channels/userEvents/messages/userCreated'

sendUserNotification:
action: send
channel:
$ref: '#/channels/userEvents'
security:
# Example 2: Multiple options with AND logic
# Option 1: OAuth2 AND API Key
# OR
# Option 2: mTLS (client certificate)
-
- $ref: '#/components/securitySchemes/oauth2'
- $ref: '#/components/securitySchemes/apiKey'
-
- $ref: '#/components/securitySchemes/clientCertificate'
messages:
- $ref: '#/channels/userEvents/messages/userCreated'

components:
messages:
UserCreated:
payload:
type: object
properties:
userId:
type: string
description: Unique identifier for the user
email:
type: string
format: email
timestamp:
type: string
format: date-time

securitySchemes:
oauth2:
type: oauth2
description: OAuth 2.0 authentication
flows:
clientCredentials:
tokenUrl: https://auth.example.com/oauth/token
scopes:
'read:users': Read user information
'write:users': Create and update users

apiKey:
type: httpApiKey
name: X-API-Key
in: header
description: API Key for request validation

clientCertificate:
type: X509
description: Client certificate (mTLS) authentication
6 changes: 3 additions & 3 deletions spec/asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ Field Name | Type | Description
<a name="serverObjectTitle"></a>title | `string` | A human-friendly title for the server.
<a name="serverObjectSummary"></a>summary | `string` | A short summary of the server.
<a name="serverObjectVariables"></a>variables | Map[`string`, [Server Variable Object](#serverVariableObject) \| [Reference Object](#referenceObject)]] | A map between a variable name and its value. The value is used for substitution in the server's `host` and `pathname` template.
<a name="serverObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] | A declaration of which security schemes can be used with this server. The list of values includes alternative [security scheme objects](#securitySchemeObject) that can be used. Only one of the security scheme objects need to be satisfied to authorize a connection or operation.
<a name="serverObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] \| [[[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]] | A declaration of which security schemes can be used with this server. When a single-level array is used, only one of the security scheme objects need to be satisfied to authorize a connection or operation (OR logic). When an array of arrays is used, the outer array represents OR logic while each inner array represents AND logic, meaning all security schemes in an inner array MUST be satisfied together.
<a name="serverObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of servers.
<a name="serverObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this server.
<a name="serverObjectBindings"></a>bindings | [Server Bindings Object](#serverBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the server.
Expand Down Expand Up @@ -841,7 +841,7 @@ Field Name | Type | Description
<a name="operationObjectTitle"></a>title | `string` | A human-friendly title for the operation.
<a name="operationObjectSummary"></a>summary | `string` | A short summary of what the operation is about.
<a name="operationObjectDescription"></a>description | `string` | A verbose explanation of the operation. [CommonMark syntax](http://spec.commonmark.org/) can be used for rich text representation.
<a name="operationObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] \| [[[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]]| A declaration of which security schemes are associated with this operation. When a single-level array is used, only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation (OR logic). When an array of arrays is used, the outer array represents OR logic while each inner array represents AND logic, meaning all security schemes in an inner array MUST be satisfied together. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations.
<a name="operationObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation.
<a name="operationObjectBindings"></a>bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.
Expand Down Expand Up @@ -968,7 +968,7 @@ Field Name | Type | Description
<a name="operationTraitObjectTitle"></a>title | `string` | A human-friendly title for the operation.
<a name="operationTraitObjectSummary"></a>summary | `string` | A short summary of what the operation is about.
<a name="operationTraitObjectDescription"></a>description | `string` | A verbose explanation of the operation. [CommonMark syntax](https://spec.commonmark.org/) can be used for rich text representation.
<a name="operationTraitObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]| A declaration of which security schemes are associated with this operation. Only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationTraitObjectSecurity"></a>security | [[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)] \| [[[Security Scheme Object](#securitySchemeObject) \| [Reference Object](#referenceObject)]]| A declaration of which security schemes are associated with this operation. When a single-level array is used, only one of the [security scheme objects](#securitySchemeObject) MUST be satisfied to authorize an operation (OR logic). When an array of arrays is used, the outer array represents OR logic while each inner array represents AND logic, meaning all security schemes in an inner array MUST be satisfied together. In cases where [Server Security](#serverObjectSecurity) also applies, it MUST also be satisfied.
<a name="operationTraitObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of operations.
<a name="operationTraitObjectExternalDocs"></a>externalDocs | [External Documentation Object](#externalDocumentationObject) \| [Reference Object](#referenceObject) | Additional external documentation for this operation.
<a name="operationTraitObjectBindings"></a>bindings | [Operation Bindings Object](#operationBindingsObject) \| [Reference Object](#referenceObject) | A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the operation.
Expand Down
Loading