This document is licensed under
Creative Commons Attribution 4.0 International Public License
Dit betreft een technische module is die een aantal eisen invult op het gebied van transport security & http security.
This is the definitive version of this document. Edits resulting from consultations have been applied.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST, MUST NOT, NOT RECOMMENDED, RECOMMENDED, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This section is non-normative.
More and more governmental organizations offer REST APIs (henceforth abbreviated as APIs), in addition to existing interfaces like SOAP and WFS. These APIs aim to be developer-friendly and easy to implement. While this is a commendable aim, it does not shield a developer from a steep learning curve getting to know every new API, in particular when every individual API is designed using different patterns and conventions.
This document aims to describe a widely applicable set of design rules for the unambiguous provisioning of REST APIs. The primary goal is to offer guidance for organizations designing new APIs, with the purpose of increasing developer experience (DX) and interoperability between APIs. Hopefully, many organizations will adopt these design rules in their corporate API strategies and provide feedback about exceptions and additions to subsequently improve these design rules.
This version of the design rules has been submitted to Forum Standaardisatie for inclusion on the Comply or Explain list of mandatory standards in the Dutch Public Sector. This document originates from the document API Strategie voor de Nederlandse Overheid, which was recently split into separate sub-documents.
This document is part of the Nederlandse API Strategie.
The Nederlandse API Strategie consists of a set of distinct documents.
Status | Description & Link |
---|---|
Informative | Inleiding NL API Strategie |
Informative | Architectuur NL API Strategie |
Informative | Gebruikerswensen NL API Strategie |
Normative | API Design Rules (ADR) |
Normative | Open API Specification (OAS) |
Normative | NL GOV OAuth profiel |
Normative | Digikoppeling REST API koppelvlak specificatie |
Normative module | GEO module |
Normative module | Transport Security module |
Before reading this document it is advised to gain knowledge of the informative documents, in particular the Architecture.
An overview of all current documents is available in this Dutch infographic:
This section describes security principles, concepts and technologies to apply when working with APIs. Controls need to be applied for the security objectives of integrity, confidentiality and availability of the API and services and data provided thereby. The (new draft of the) architecture section of the API strategy contains architecture patterns for implementing Transport security.
The scope of this section is limited to generic security controls that directly influence the visible parts of an API. Effectively, only security standards directly applicable to interactions are discussed here. In order to meet the complete security objectives, every implementer MUST also apply a range of controls not mentioned in this section.
Note: security controls for signing and encrypting of application level messages will be part of a separate extension, Signing and Encryption.
One should secure all APIs assuming they can be accessed from any location on the internet. Information MUST be exchanged over TLS-based secured connections. No exceptions, so everywhere and always. This is required by law. One SHOULD follow the latest NCSC guidelines for TLS
/transport/tls: Secure connections using TLS
Secure connections using TLS following the latest NCSC guidelines [NCSC.TLS].
Since the connection is always secured, the access method can be straightforward. This allows the application of basic access tokens instead of encrypted access tokens.
Even when using TLS-based secured connections information in URIs is not secured. URIs can be cached and logged outside of the servers controlled by clients and servers. Any information contained in them should therfor be considered readable by anyone with access to the netwerk being used (in case of the internet the whole world) and MUST NOT contain any sensitive information. Neither client secrets used for authentication, privacy sensitive informations suchs as BSNs nor any other information which should not be shared. Be aware that queries (anything after the '?' in a URI) are also part of an URI.
/transport/no-sensitive-uris: No sensitive information in URIs
Do not put any sensitive information in URIs
Even when the connection is secure URIs can be cached and logged, in systems outside the control of client and/or server.
How to test Sensitive information URIS is not machine testable and therfor not part of automated tests. It should be part of any security audit performed by human experts.
The usage of TLS is machine testable. The test is designed for maximum automation. To test, adherence to NCSC reccomendations should be tested. The serverside is what will be tested, only control over the server is assumed for testing. A testing client will be employed to test adherence of the server. Supporting any protocols, algorithms, key sizes, options or ciphers dat are deemed insufficient or phase out by NCSC will lead to failure on the automated test. Both positive and negative scenario's are part of the test. Testing that a subset of good and sufficient reccomendations are supported and testing that phase out and insufficient reccomendations are not. A manual exception to the automated test results can be made when phase out reccomendations are supported. The API provider will have to provide clear documentation for the phase out schedule.
The guidelines and principles defined in this extension are client agnostic. When implementing a client agnostic API, one SHOULD at least facilitate that multi-purpose generic HTTP-clients like browsers are able to securely interact with the API. When implementing an API for a specific client it may be possible to limit measures as long as it ensures secure access for this specific client. Nevertheless it is advised to review the following security measures, which are mostly inspired by the OWASP REST Security Cheat Sheet
Even while remaining client agnostic, clients can be classified in four major groups. This is much in line with common practice in OAuth2. The groups are:
This section contains elements that apply to the generic classes of clients listed above. Although not every client implementation has a need for all the specifications referenced below, a client agnostic API SHOULD provide these to facilitate any client to implement relevant security controls.
Most specifications referenced in this section are applicable to the first three classes of clients listed above. Security considerations for native applications are provided in [OAUth2 for Native Apps]](https://tools.ietf.org/html/rfc8252), much of which can help non-OAuth2 based implementations as well. For browser-based applications a subsection is included with additional details and information. System-to-system (sometimes called machine-to-machine) may have a need for the listed specifications as well. Note that different usage patterns may be applicable in contexts with system-to-system clients, see above under Client Authentication.
/transport/security-headers: Use mandatory security headers in API all responses
Return API security headers in all server responses to instruct the client to act in a secure manner
There are a number of security related headers that can be returned in the HTTP responses to instruct browsers to act in specific ways. However, some of these headers are intended to be used with HTML responses, and as such may provide little or no security benefits on an API that does not return HTML. The following headers SHOULD be included in all API responses:
Header | Rationale |
---|---|
Cache-Control: no-store |
Prevent sensitive information from being cached. |
Content-Security-Policy: frame-ancestors 'none' |
To protect against drag-and-drop style clickjacking attacks. |
Content-Type |
To specify the content type of the response. This SHOULD be application/json for JSON responses. |
Strict-Transport-Security |
To require connections over HTTPS and to protect against spoofed certificates. |
X-Content-Type-Options: nosniff |
To prevent browsers from performing MIME sniffing, and inappropriately interpreting responses as HTML. |
X-Frame-Options: DENY |
To protect against drag-and-drop style clickjacking attacks. |
Access-Control-Allow-Origin |
To relax the 'same origin' policy and allow cross-origin access. See CORS-policy below |
Note that strict transport security is not only mandated by this module but also by law.
The headers below are only intended to provide additional security when responses are rendered as HTML. As such, if the API will never return HTML in responses, then these headers may not be necessary. However, if there is any uncertainty about the function of the headers, or the types of information that the API returns (or may return in future), then it is RECOMMENDED to include them as part of a defense-in-depth approach.
Header | Rationale |
---|---|
Content-Security-Policy: default-src 'none' |
The majority of CSP functionality only affects pages rendered as HTML. |
Feature-Policy: 'none' |
Feature policies only affect pages rendered as HTML. |
Referrer-Policy: no-referrer |
Non-HTML responses SHOULD not trigger additional requests. |
In addition to the above listed HTTP security headers, web- and browser-based applications SHOULD apply Subresource Integrity SRI. When using third-party hosted contents, e.g. using a Content Delivery Network, this is even more relevant. While this is primarily a client implementation concern, it may affect the API when it is not strictly segregated or for example when shared supporting libraries are offered.
How to test The precense of the mandatory security headers can be tested in an automated way. A test client makes a call to the API root. The response is tested for the precense of mandatory headers.
/transport/cors: Use CORS to control access
Use CORS to restrict access from other domains (if applicable).
Modern web browsers use Cross-Origin Resource Sharing (CORS) to minimize the risk associated with cross-site HTTP-requests. By default browsers only allow 'same origin' access to resources. This means that responses on requests to another [scheme]://[hostname]:[port]
than the Origin
request header of the initial request will not be processed by the browser. To enable cross-site requests API's can return a Access-Control-Allow-Origin
response header. It is RECOMMENDED to use a whitelist to determine the validity of different cross-site request. To do this check the Origin
header of the incoming request and check if the domain in this header is on the whitelist. If this is the case, set the incoming Origin
header in the Access-Control-Allow-Origin
response header.
Using a wildcard *
in the Access-Control-Allow-Origin
response header is NOT RECOMMENDED, because it disables CORS-security measures. Only for an open API which has to be accessed by numerous other websites this is appropriate.
How to test Tests of this design rule can only be performed when the intended client is known to the tester. A thest can be performed when this information is provided by the API provider. Otherwise no conclusive test result can be reached.
A specific subclass of clients are browser-based applications, that require the presence of particular security controls to facilitate secure implementation. Clients in this class are also known as user-agent-based or single-page-applications (SPA). As with the (draft) OAuth 2.0 for Browser-Based Apps, browser-based application can be split into three architectural patterns:
All browser-based application SHOULD follow the best practices specified in OAuth 2.0 for Browser-Based Apps.
Apply a whitelist of permitted HTTP Methods e.g. GET
, POST
, PUT
. Reject all requests not matching the whitelist with HTTP response code 405 Method not allowed
.
A REST request or response body SHOULD match the intended content type in the header. Otherwise this could cause misinterpretation at the consumer/producer side and lead to code injection/execution.
406 Unacceptable
or 415 Unsupported Media Type
.@consumes("application/json"); @produces("application/json")
. This avoids XXE-attack vectors for example.It is common for REST services to allow multiple response types (e.g. application/xml
or application/json
, and the client specifies the preferred order of response types by the Accept header in the request.
Accept
header to the Content-type
header of the response.406 Not Acceptable
response) if the Accept header does not specifically contain one of the allowable types.Services (potentially) including script code (e.g. JavaScript) in their responses MUST be especially careful to defend against header injection attack.
application/json
and not application/javascript
.HTTP defines status codes. When designing a REST API, don't just use 200
for success or 404
for error. Always use the semantically appropriate status code for the response.
Realizations may rely on internal usage of HTTP-Headers. Information for processing requests and responses can be passed between components, that can have security implications. For instance, this is commonly practices between a reverse proxy or TLS-offloader and an application server. Additional HTTP headers are used in such example to pass an original IP-address or client certificate.
Implementations MUST consider filtering both inbound and outbound traffic for HTTP-headers used internally. Primary focus for inbound filtering is to prevent injection of malicious headers on requests. For outbound filtering, the main concern is leaking of information.