spec icon indicating copy to clipboard operation
spec copied to clipboard

Support AND logic for multiple security schemes in AsyncAPI 3.x

Open rahmathm1 opened this issue 2 months ago • 2 comments

Problem

Currently, AsyncAPI 3.x only allows expressing OR semantics between multiple security schemes using the security array:

security:
  - $ref: '#/components/securitySchemes/saslScram'
  - $ref: '#/components/securitySchemes/mtls'

This means either SASL/SCRAM or mTLS can authorize a connection. However, in many real-world scenarios, a server or operation may require multiple authentication schemes simultaneously (logical AND), for example: SASL/SCRAM and a valid client certificate (mTLS) for a Kafka broker

Currently, there is no spec-compliant way to enforce both requirements in AsyncAPI 3.x without using a vendor extension (x- fields) or describing it only in prose. This limitation prevents full machine-readable documentation and automated validation of multi-factor authentication requirements.

Current workarounds

  1. Use only one $ref and describe the second requirement in description Pros: Spec-compliant Cons: Not machine-enforceable, tooling cannot validate
  2. Vendor extension Pros: Documents AND requirement Cons: Non-standard, tooling may ignore it Neither approach is ideal for consistent, spec-compliant multi-scheme security modeling.

Proposal

Introduce a native, spec-supported syntax to express AND logic between multiple security schemes in a single security requirement object. Possible approaches:

  1. Array of $refs array.
security:
  - - $ref: '#/components/securitySchemes/saslScram'
    - $ref: '#/components/securitySchemes/mtls'
  1. Named keys with logical AND semantics (similar to v2):
security:
  - saslScram: []
    mtls: []

Requirements for tooling: Studio, CLI validator, and generators should enforce that all schemes in a single requirement object are required.

rahmathm1 avatar Oct 23 '25 11:10 rahmathm1

Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our contributors guide and the instructions about a basic recommended setup useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.

github-actions[bot] avatar Oct 23 '25 11:10 github-actions[bot]

The approaches shared above are still in a preliminary state and shouldn’t be considered formal proposals. I don’t have a finalized approach yet, but I'm actively working on it and will provide an update here soon.

rahmathm1 avatar Oct 24 '25 10:10 rahmathm1

Hi everybody,

Some of my thoughts after research:

We haven't had this problem in AsyncAPI 2.x. We had a Security Requirement Object which was creating implicit connection with Security Scheme Objects. This naturally allowed logical disjunctions (OR) and conjunctions (AND). This was aligned with how OpenAPI works (discussion about it in this issue).

In AsyncAPI 3.0, Security Requirement Object was dropped and replaced by union of Security Scheme | Reference Object. I'm not sure about the reason, but this change made the logical disjunctions the only allowed mechanism. I assume the motivation might have been to remove implicit connection and make the connection explicit? Or make everything referencable? I can only guess...

Now the question is if we want to return back to Security Requirement object, which is well known, established and battle tested concept, or continue with explicit union of Security Scheme | Reference Object and use nested arrays to express logical groupings.

We have couple of options:

  1. Getting back the Security Requirement Object in backward compatible way into AsyncAPI 3.x would be tooling a nightmare. We'd end up with Security Scheme | Reference Object | Security Requirement Object mixing implicit and explicit connections. Keys in components.securitySchemes will become significant again. We have to guarantee there is no ambiguity between Security Scheme and Security Requirement objects. I like this option the most, but only in context that we'd like to replace Security Scheme | Reference Object | Security Requirement Object by Security Requirement Object in future.

  2. Continuing Security Scheme | Reference Object and using nested array to express logical groupings. I might be appropriate to break [Security Scheme Object | Reference Object] | [[Security Scheme Object | Reference Object]] into sub-types for people to be able to make sense of it:

Securities = [Security Scheme Object | Reference Object]

security: Securities | [Securities]

Also noting that YAML syntax looks unnatural (even though it's completely valid):

security:
  - - $ref: '#/components/securitySchemes/saslScram'
    - $ref: '#/components/securitySchemes/mtls'

I'd go for flow style here (to describe this in examples) which is equivalent with above but more comprehendable:

security:
  - [$ref: '#/components/securitySchemes/saslScram', $ref: '#/components/securitySchemes/mtls']
  1. Do nothing, wait for 4.x and re-introduce Security Requirement Object in 4.x (when it comes)

char0n avatar Dec 11 '25 21:12 char0n

This is a real limitation I’ve run into when trying to model production setups, especially for Kafka-based systems where brokers commonly require multiple authentication mechanisms simultaneously (e.g., mTLS for transport identity + SASL/SCRAM for client auth).

Today the security array only allows OR semantics, which makes these configurations either:

under-specified (described only in prose), or

vendor-specific (via x-* extensions), both of which reduce tooling usefulness.

I’m generally in favor of introducing explicit AND semantics at the spec level. Between the options discussed, the nested array approach feels the most explicit and least ambiguous:

security:

- $ref: '#/components/securitySchemes/saslScram'
- $ref: '#/components/securitySchemes/mtls'

This preserves backward compatibility, makes OR vs AND visually obvious, and aligns well with how tooling already treats the outer array as a disjunction.

One question I have is around mixed logic clarity — e.g., multiple AND-groups combined with OR:

security:

  • [saslScram, mtls]
  • [oauth2]

If this interpretation is intended (“(SASL AND mTLS) OR OAuth2”), it might be worth explicitly documenting this precedence to avoid confusion for tooling implementers.

Happy to help further by drafting schema changes, examples, or validator updates once a direction is agreed.

RUTUPARNk avatar Dec 18 '25 20:12 RUTUPARNk

@derberg what do you think???

RUTUPARNk avatar Dec 19 '25 00:12 RUTUPARNk