Every API endpoint must be protected and armed with authentication and authorization.
As part of the API definition you must specify how you protect your API using
either the http
typed bearer
or oauth2
typed security schemes defined in the
OpenAPI Authentication Specification.
The majority of our APIs (especially the company internal APIs) are protected
using JWT tokens provided by the platform IAM token service. In these situations
you should use the http
typed
Bearer Authentication
security scheme — it is based on OAuth2.0 {RFC-6750}[RFC 6750] defining the standard header
Auhorization: Bearer <token>
.
The following code snippet shows how to define the bearer security scheme.
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
The bearer security schema can then be applied to all API endpoints, e.g. requiring
the token to have api-repository.read
scope for permission as follows (see
also {MUST} define and assign permissions (scopes)):
security:
- BearerAuth: [ api-repository.read ]
In other, more specific situations e.g. with customer and partner facing APIs you
may use other OAuth 2.0 authorization flows as defined by {RFC-6749}[RFC 6749].
Please consult the
OpenAPI OAuth 2.0 Authentication
section for details on how to define oauth2
typed security schemes correctly.
Note: Do not use OpenAPI oauth2
typed security scheme flows (e.g. implicit
)
if your service does not fully support it and implements a simple bearer token scheme,
because it exposes authentication server address details and may make use of redirection.
Endpoints must be equipped with permissions, if they require client authorization for protection
since e.g. data is exposed that is classified as orange
or red
according to Zalando’s
Data Classification Group Policy (internal link).
Please refer to {MUST} follow the naming convention for permissions (scopes) for designing permission names.
Some API endpoints may not require specific permissions for authorization e.g.
in case of (i) authorization is not needed for the endpoint since all
exposed data is classified as green
or yellow
,
or in case of (ii) the specific authorization is provided differently on
the individual object level. In these situations, however, you must make
it explicit by assigning the uid
pseudo permission, which is always
available as OAuth2 default scope for all clients in Zalando.
The defined permissions are assigned to each API endpoint based on the security schema (see example in previous section) by specifying the security requirement as follows:
paths:
/business-partners/{partner-id}:
get:
summary: Retrieves information about a business partner
security:
- BearerAuth: [ business-partner-service.read ]
Hint: Following a minimal API specification approach, the
Authorization
-header does not need to be defined on each API endpoint, since
it is required and so to say implicitly defined via the security section.
As long as the functional naming is not yet supported by our permission registry, 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
Note: This naming convention only applies to scopes for service-to-service communication using the Platform IAM tokens. For IAM systems with other naming rules (e.g. Zalando Partner IAM), the naming should be consistent with the existing conventions of those systems.
The permission naming schema corresponds to the naming schema for hostnames and event type names, and typical examples are:
Application ID | Resource ID | Access Type | Example |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note: APIs should stick to component specific permissions without resource extension to avoid the complexity of too many fine grained permissions. For the majority of use cases, restricting access for specific API endpoints using read or write is sufficient.