-
-
Notifications
You must be signed in to change notification settings - Fork 289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: unify all referencing mechanisms #852
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,6 @@ It means that the [application](#definitionsApplication) allows [consumers](#def | |
- [Reference Object](#referenceObject) | ||
- [Schema Object](#schemaObject) | ||
- [Security Scheme Object](#securitySchemeObject) | ||
- [Security Requirement Object](#security-requirement-object) | ||
- [OAuth Flows Object](#oauth-flows-object) | ||
- [OAuth Flow Object](#oauth-flow-object) | ||
- [Server Bindings Object](#serverBindingsObject) | ||
|
@@ -342,7 +341,7 @@ Field Pattern | Type | Description | |
|
||
```json | ||
{ | ||
"production": { | ||
"development": { | ||
"url": "development.gigantic-server.com", | ||
"description": "Development server", | ||
"protocol": "kafka", | ||
|
@@ -352,7 +351,7 @@ Field Pattern | Type | Description | |
``` | ||
|
||
```yaml | ||
production: | ||
development: | ||
url: development.gigantic-server.com | ||
description: Development server | ||
protocol: kafka | ||
|
@@ -373,7 +372,7 @@ Field Name | Type | Description | |
<a name="serverObjectProtocolVersion"></a>protocolVersion | `string` | The version of the protocol used for connection. For instance: AMQP `0.9.1`, HTTP `2.0`, Kafka `1.0.0`, etc. | ||
<a name="serverObjectDescription"></a>description | `string` | An optional string describing the host designated by the URL. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | ||
<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 URL template. | ||
<a name="serverObjectSecurity"></a>security | [[Security Requirement Object](#securityRequirementObject)] | A declaration of which security mechanisms can be used with this server. The list of values includes alternative security requirement objects that can be used. Only one of the security requirement objects need to be satisfied to authorize a connection or operation. | ||
<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="serverObjectTags"></a>tags | [Tags Object](#tagsObject) | A list of tags for logical grouping and categorization of servers. | ||
<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. | ||
|
||
|
@@ -399,128 +398,82 @@ protocol: kafka | |
protocolVersion: '1.0.0' | ||
``` | ||
|
||
The following shows how multiple servers can be described, for example, at the AsyncAPI Object's [`servers`](#A2SServers): | ||
Using server variables for dynamic URLs: | ||
|
||
```json | ||
{ | ||
"servers": { | ||
"development": { | ||
"url": "development.gigantic-server.com", | ||
"description": "Development server", | ||
"protocol": "amqp", | ||
"protocolVersion": "0.9.1", | ||
"tags": [ | ||
{ | ||
"name": "env:development", | ||
"description": "This environment is meant for developers to run their own tests" | ||
} | ||
] | ||
"url": "{username}.gigantic-server.com:{port}/{basePath}", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here I'm just removing context information in the example. Just to keep it the same as in the rest of the spec. |
||
"description": "The production API server", | ||
"protocol": "secure-mqtt", | ||
"variables": { | ||
"username": { | ||
"default": "demo", | ||
"description": "This value is assigned by the service provider, in this example `gigantic-server.com`" | ||
}, | ||
"staging": { | ||
"url": "staging.gigantic-server.com", | ||
"description": "Staging server", | ||
"protocol": "amqp", | ||
"protocolVersion": "0.9.1", | ||
"tags": [ | ||
{ | ||
"name": "env:staging", | ||
"description": "This environment is a replica of the production environment" | ||
} | ||
] | ||
"port": { | ||
"enum": [ | ||
"8883", | ||
"8884" | ||
], | ||
"default": "8883" | ||
}, | ||
"production": { | ||
"url": "api.gigantic-server.com", | ||
"description": "Production server", | ||
"protocol": "amqp", | ||
"protocolVersion": "0.9.1", | ||
"tags": [ | ||
{ | ||
"name": "env:production", | ||
"description": "This environment is the live environment available for final users" | ||
} | ||
] | ||
"basePath": { | ||
"default": "v2" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
```yaml | ||
servers: | ||
development: | ||
url: development.gigantic-server.com | ||
description: Development server | ||
protocol: amqp | ||
protocolVersion: 0.9.1 | ||
tags: | ||
- name: "env:development" | ||
description: "This environment is meant for developers to run their own tests" | ||
staging: | ||
url: staging.gigantic-server.com | ||
description: Staging server | ||
protocol: amqp | ||
protocolVersion: 0.9.1 | ||
tags: | ||
- name: "env:staging" | ||
description: "This environment is a replica of the production environment" | ||
production: | ||
url: api.gigantic-server.com | ||
description: Production server | ||
protocol: amqp | ||
protocolVersion: 0.9.1 | ||
tags: | ||
- name: "env:production" | ||
description: "This environment is the live environment available for final users" | ||
``` | ||
|
||
The following shows how variables can be used for a server configuration: | ||
url: '{username}.gigantic-server.com:{port}/{basePath}' | ||
description: The production API server | ||
protocol: secure-mqtt | ||
variables: | ||
username: | ||
# Note: no enum here means it is an open value. | ||
default: demo | ||
description: This value is assigned by the service provider, in this example `gigantic-server.com` | ||
port: | ||
enum: | ||
- '8883' | ||
- '8884' | ||
default: '8883' | ||
basePath: | ||
# Note: open meaning. There is the opportunity to use special base paths as assigned by the provider, default is `v2`. | ||
default: v2 | ||
``` | ||
|
||
Using security mechanisms: | ||
|
||
```json | ||
{ | ||
"servers": { | ||
"production": { | ||
"url": "{username}.gigantic-server.com:{port}/{basePath}", | ||
"description": "The production API server", | ||
"protocol": "secure-mqtt", | ||
"variables": { | ||
"username": { | ||
"default": "demo", | ||
"description": "This value is assigned by the service provider, in this example `gigantic-server.com`" | ||
}, | ||
"port": { | ||
"enum": [ | ||
"8883", | ||
"8884" | ||
], | ||
"default": "8883" | ||
}, | ||
"basePath": { | ||
"default": "v2" | ||
} | ||
} | ||
"url": "broker.company.com", | ||
"description": "Production MQTT broker", | ||
"protocol": "secure-mqtt", | ||
"protocolVersion": "5", | ||
"security": [ | ||
{ | ||
"type": "userPassword", | ||
"description": "Connect to the MQTT broker using basic authentication." | ||
}, | ||
{ | ||
"type": "X509", | ||
"description": "Connect to the MQTT broker using a X509 certificate." | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
```yaml | ||
servers: | ||
production: | ||
url: '{username}.gigantic-server.com:{port}/{basePath}' | ||
description: The production API server | ||
protocol: secure-mqtt | ||
variables: | ||
username: | ||
# note! no enum here means it is an open value | ||
default: demo | ||
description: This value is assigned by the service provider, in this example `gigantic-server.com` | ||
port: | ||
enum: | ||
- '8883' | ||
- '8884' | ||
default: '8883' | ||
basePath: | ||
# open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` | ||
default: v2 | ||
url: broker.company.com | ||
description: Production MQTT broker | ||
protocol: secure-mqtt | ||
protocolVersion: '5' | ||
security: | ||
- type: userPassword | ||
description: Connect to the MQTT broker using basic authentication. | ||
- type: X509 | ||
description: Connect to the MQTT broker using a X509 certificate. | ||
``` | ||
|
||
|
||
|
@@ -810,7 +763,7 @@ Field Name | Type | Description | |
<a name="operationObjectChannel"></a>channel | [Reference Object](#referenceObject) | **Required**. A `$ref` pointer to the definition of the channel in which this operation is performed. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. | ||
<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 Requirement Object](#securityRequirementObject)]| A declaration of which security mechanisms are associated with this operation. Only one of the security requirement objects MUST be satisfied to authorize an operation. In cases where Server Security also applies, it MUST also be satisfied. | ||
<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="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. | ||
|
@@ -890,7 +843,7 @@ Field Name | Type | Description | |
<a name="operationTraitObjectChannel"></a>channel | [Reference Object](#referenceObject) | A `$ref` pointer to the definition of the channel in which this operation is performed. Please note the `channel` property value MUST be a [Reference Object](#referenceObject) and, therefore, MUST NOT contain a [Channel Object](#channelObject). However, it is RECOMMENDED that parsers (or other software) dereference this property for a better development experience. | ||
<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 Requirement Object](#securityRequirementObject)]| A declaration of which security mechanisms are associated with this operation. Only one of the security requirement objects MUST be satisfied to authorize an operation. In cases where Server Security also applies, it MUST also be satisfied. | ||
<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="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. | ||
|
@@ -2278,6 +2231,7 @@ Field Name | Type | Applies To | Description | |
<a name="securitySchemeObjectBearerFormat"></a>bearerFormat | `string` | `http` (`"bearer"`) | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. | ||
<a name="securitySchemeFlows"></a>flows | [OAuth Flows Object](#oauthFlowsObject) | `oauth2` | **REQUIRED**. An object containing configuration information for the flow types supported. | ||
<a name="securitySchemeOpenIdConnectUrl"></a>openIdConnectUrl | `string` | `openIdConnect` | **REQUIRED**. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in the form of an absolute URL. | ||
<a name="securitySchemeScopes"></a>scopes | [`string`] | `oauth2` \| `openIdConnect` | List of the needed scope names. An empty array means no scopes are needed. | ||
fmvilas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
This object MAY be extended with [Specification Extensions](#specificationExtensions). | ||
|
||
|
@@ -2387,12 +2341,15 @@ bearerFormat: JWT | |
"flows": { | ||
"implicit": { | ||
"authorizationUrl": "https://example.com/api/oauth/dialog", | ||
"scopes": { | ||
"availableScopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
} | ||
} | ||
}, | ||
"scopes": [ | ||
"write:pets" | ||
] | ||
} | ||
``` | ||
|
||
|
@@ -2401,9 +2358,11 @@ type: oauth2 | |
flows: | ||
implicit: | ||
authorizationUrl: https://example.com/api/oauth/dialog | ||
scopes: | ||
availableScopes: | ||
write:pets: modify pets in your account | ||
read:pets: read your pets | ||
scopes: | ||
- 'write:pets' | ||
``` | ||
|
||
###### SASL Sample | ||
|
@@ -2442,106 +2401,32 @@ Field Name | Type | Applies To | Description | |
<a name="oauthFlowAuthorizationUrl"></a>authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of an absolute URL. | ||
<a name="oauthFlowTokenUrl"></a>tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of an absolute URL. | ||
<a name="oauthFlowRefreshUrl"></a>refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of an absolute URL. | ||
<a name="oauthFlowScopes"></a>scopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. | ||
<a name="oauthFlowScopes"></a>availableScopes | Map[`string`, `string`] | `oauth2` | **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Renaming the |
||
|
||
This object MAY be extended with [Specification Extensions](#specificationExtensions). | ||
|
||
##### OAuth Flow Object Examples | ||
|
||
```JSON | ||
{ | ||
"type": "oauth2", | ||
"flows": { | ||
"implicit": { | ||
"authorizationUrl": "https://example.com/api/oauth/dialog", | ||
"scopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
}, | ||
"authorizationCode": { | ||
"authorizationUrl": "https://example.com/api/oauth/dialog", | ||
"tokenUrl": "https://example.com/api/oauth/token", | ||
"scopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
} | ||
"authorizationUrl": "https://example.com/api/oauth/dialog", | ||
"tokenUrl": "https://example.com/api/oauth/token", | ||
"availableScopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
} | ||
``` | ||
|
||
```YAML | ||
type: oauth2 | ||
flows: | ||
implicit: | ||
authorizationUrl: https://example.com/api/oauth/dialog | ||
scopes: | ||
write:pets: modify pets in your account | ||
read:pets: read your pets | ||
authorizationCode: | ||
authorizationUrl: https://example.com/api/oauth/dialog | ||
tokenUrl: https://example.com/api/oauth/token | ||
scopes: | ||
write:pets: modify pets in your account | ||
read:pets: read your pets | ||
``` | ||
|
||
#### <a name="securityRequirementObject"></a>Security Requirement Object | ||
|
||
Lists the required security schemes to execute this operation. | ||
The name used for each property MUST correspond to a security scheme declared in the [Security Schemes](#componentsSecuritySchemes) under the [Components Object](#componentsObject). | ||
|
||
When a list of Security Requirement Objects is defined on a [Server object](#serverObject), only one of the Security Requirement Objects in the list needs to be satisfied to authorize the connection. | ||
|
||
##### Patterned Fields | ||
|
||
Field Pattern | Type | Description | ||
---|:---:|--- | ||
<a name="securityRequirementsName"></a>{name} | [`string`] | Each name MUST correspond to a security scheme which is declared in the [Security Schemes](#componentsSecuritySchemes) under the [Components Object](#componentsObject). If the security scheme is of type `"oauth2"` or `"openIdConnect"`, then the value is a list of scope names. Provide scopes that are required to establish successful connection with the server. If scopes are not needed, the list can be empty. For other security scheme types, the array MUST be empty. | ||
|
||
##### Security Requirement Object Examples | ||
|
||
###### User/Password Security Requirement | ||
|
||
```json | ||
{ | ||
"user_pass": [] | ||
} | ||
authorizationUrl: https://example.com/api/oauth/dialog | ||
tokenUrl: https://example.com/api/oauth/token | ||
availableScopes: | ||
write:pets: modify pets in your account | ||
read:pets: read your pets | ||
``` | ||
|
||
```yaml | ||
user_pass: [] | ||
``` | ||
|
||
###### API Key Security Requirement | ||
|
||
```json | ||
{ | ||
"api_key": [] | ||
} | ||
``` | ||
|
||
```yaml | ||
api_key: [] | ||
``` | ||
|
||
###### OAuth2 Security Requirement | ||
|
||
```json | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
``` | ||
|
||
```yaml | ||
petstore_auth: | ||
- write:pets | ||
- read:pets | ||
``` | ||
|
||
### <a name="correlationIdObject"></a>Correlation ID Object | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having a weird syntax like:
My proposal is that we do the following:
The array of the current syntax is just for OAuth2 and OpenIDConnect schemes so I created a new property called
scopes
in the Security Scheme Object. These will be the mandatory scopes needed to connect or perform an operation. It offers less reusability in thesecurity
property but you can anyway create as many Security Scheme Objects inside components so, yeah, not an issue.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider that in the security field we have 3 options:
defining one security (as in your case)
defining several security that must be met at once:
defining several security, for which only one security must be satisfied.
So as you can see, we have problem with second case (several securities have to met at once). We have even issue for that #828
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not to create security item shape as:
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should we? :) The proposed syntax looks much cleaner IMHO. It only has the problem of meeting multiple security schemes at once but I'm not sure it should be a requirement. Left a comment at #828 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@magicmatatjahu you raised it as thoughts here: #778 (comment)
I don't think it has been discussed anywhere else 🧐
It's not that we are planning not to support it, but we have not planned or had a discussion about whether that should be a feature I think 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. So maybe it's time to have it 😄 This could simplify life in cases like this. And tooling is already behaving this way, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is only because the tooling has bugs, it is not intended behavior... 🙂
Adding this functionality will definitely complicate it from a spec perspective, but yea simplify it in this case 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug or feature? 😛 To be honest, this is a thing I see many people doing/trying expecting it to work. But yeah, that's not a discussion for this thread sorry for the noise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly encourage folks to file thoughts around potential reference merging in AsyncAPI as issues at the unified referencing discussion repo, where we can consider them alongside, for example, the limited merging of
summary
anddescription
that OpenAPI 3.1 does outside of JSON Schema references.This wouldn't mean AsyncAPI is blocked from taking other action, but unified referencing will only be unified if we know what's going on with each project.