Every API endpoint needs to be secured using OAuth 2.0. Please refer to the official Open API specification on how to specify security definitions in your API specification or take a look at the following example.
components:
securitySchemes:
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://identity.zalando.com/oauth2/token
scopes:
fulfillment-order-service.read: Access right needed to read from the fulfillment order service.
fulfillment-order-service.write: Access right needed to write to the fulfillment order service.
The example defines OAuth2 with client credentials flow as security standard used for authentication when accessing endpoints. Additionally, there are two API access rights (permissions) defined via the scopes section for later endpoint authorization usage (see next section).
It makes little sense specifying the flow to retrieve OAuth tokens in the
securitySchemes
section, as API endpoints should not care, how OAuth
tokens were created. Unfortunately the flow
field is mandatory and cannot
be omitted. API endpoints should always set flow: clientCredentials
and ignore
this information.
APIs must define permissions to protect their resources. Thus, at least one permission must be assigned to each endpoint. Permissions are defined as shown in the previous section.
The naming schema for permissions corresponds to the naming schema for hostnames and event type names. Please refer to {MUST} follow naming convention for permissions (scopes) for designing permission names.
APIs should stick to component specific permissions without resource extension to avoid governance complexity of too many fine grained permissions. For the majority of use cases, restricting access to specific API endpoints using read and write is sufficient for controlling access for client types like merchant or retailer business partners, customers or operational staff. However, in some situations, where the API serves different types of resources for different owners, resource specific scopes may make sense.
Some examples for standard and resource-specific permissions:
Application ID | Resource ID | Access Type | Example |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
After permission names are defined and the permission is declared in the security definition at the top of an API specification, it should be assigned to each API operation by specifying a security requirement like this:
paths:
/business-partners/{partner-id}:
get:
summary: Retrieves information about a business partner
security:
- oauth2:
- business-partner.read
In very rare cases a whole API or some selected endpoints may not require
specific access control. However, to make this explicit you should assign the
uid
pseudo permission in this case. It is the user id and always available
as OAuth2 default scope.
paths:
/public-information:
get:
summary: Provides public information about ...
Accessible by any user; no permissions needed.
security:
- oauth2:
- uid
Hint: you need not explicitly define the "Authorization" header; it is a standard header so to say implicitly defined via the security section.
As long as the functional naming is not supported for permissions, permission names in APIs must conform to the following naming pattern:
<permission> ::= <standard-permission> | -- should be sufficient for majority of use cases
<resource-permission> | -- for special security access differentiation use cases
<pseudo-permission> -- used to explicitly indicate that access is not restricted
<standard-permission> ::= <application-id>.<access-mode>
<resource-permission> ::= <application-id>.<resource-name>.<access-mode>
<pseudo-permission> ::= uid
<application-id> ::= [a-z][a-z0-9-]* -- application identifier
<resource-name> ::= [a-z][a-z0-9-]* -- free resource identifier
<access-mode> ::= read | write -- might be extended in future
This pattern is compatible with the previous definition.