API Security Best Practices Primer
On this page
- Purpose
- Authentication and Identity
- Authorization
- Data Filtering
- Encryption and Signing
- Content Protection
Purpose
This document discusses various concepts of API security and best practices when developing an API. It is a companion document to the Guidance on Securing Application Programming Interfaces (accessible only on the Government of Canada network) (Section 7 of the Guidance on Secure Application Development) and Guidance on API Gateways.
It covers the following:
- Authentication mechanisms and identity context
- Granularity of authorizations
- Data filtering
- Transport vs. payload encryption
- Ensuring safe content
Authentication and Identity
APIs are a part of a system-to-system interaction rather than a user-to-system interaction. As such, the concept of authentication and identity are related, but must be considered separately.
Authentication Mechanisms
There are a wide range of options when determining what authentication mechanisms to support with your API. It is important to note that RESTful authentication mechanisms are optimized for API interactions initiated by web users while SOAP mechanisms have more robust system-to-system options.
Mechanisms appropriate for system-to-system (not user/browser initiated):
- Static API keys are the simplest method of direct authentication. Static keys should only be used when the API consumer is a highly trusted party (e.g., same security domain, restricted network) and the data is of low sensitivity, or there are step-up authentication and authorization mechanisms downstream. API keys should be passed using the Authorization HTTP header and not in the query string or the request body to ensure compatibility with components such as API gateways;
- JSON Web Tokens (JWT) are effectively a standardized method of generating, signing, exchanging, and verifying time-limited API keys. JWT should be the defacto standard for any RESTful API exposing sensitive data. Use trusted code libraries and/or Cloud services to generate and verify JWT instead of custom developing them;
- WSS Username Tokens for SOAP web services are similar to static API keys for RESTful APIs and should only be used for highly trusted consumers and data with low sensitivity. The Nonce option should be implemented where possible to prevent against replay attacks;
- X.509 Certificates for SOAP web services create a strong authentication method where both the API consumer and provider can access the same Certificate Authority;
- SAML Tokens for SOAP web services are used for federated authentication whereby the API provider relies on a separate authentication provider. SAML interactions should be configured for back-channel in system-to-system calls where possible;
- OAuth 2.0 is the defacto authentication and authorization protocol for RESTful APIs. It uses a federated authentication approach similar to SAML for SOAP. OAuth’s main purpose is to enable browser-initiated interactions allowing the user to grant the a requesting application to their data on another federated application. The OAuth 2.0 Client Credentials Grant type should be used for machine-to-machine API interactions where a user is not involved;
- OpenID Connect is a simplified identity authentication layer on top of OAuth 2.0. In the case of machine-to-machine, the API consumer effectively acts as the user and must authenticate to the authentication provider first via some pre-established credential (e.g., static key, username/password) to receive a transactional token. The token is typically represented as a JWT; and
- Mutual Authentication requires that both the API consumer and provider authenticate to each other to establish a strong trust and to mitigate against man-in-the-middle (MTM) attacks. SSL/TLS mutual authentication can be implemented at the HTTP protocol layer if both the API provider and consumer have control over the HTTPS handshake. OAuth also provides a TLS mutual authentication mechanism.
Mechanisms appropriate for user/browser-initiated API calls:
- Federated Authentication Methods such as SAML Tokens or OAuth should be used. Users should authenticate to an authentication provider which returns the appropriate token which the web application should use to authenticate to backend APIs. In the case of OAuth, the Implicit Grant type should be avoided as it is not considered to be very secure.
Least preferable mechanisms:
- Session and cookie-based authentication methods does not align with stateless API interactions;
- Technology-specific mechanisms such as NTLM are not open standards and creates compatibility restrictions for API consumers;
- HTTP Basic Auth offer little to no security or assurance and is easily compromised; and
- Time-limited API keys requiring a separate authentication API creates significant complexity for the API consumer to manage and effectively makes the interaction stateful.
Identity Context
The sensitivity of the data along with privacy requirements should dictate the identity context required by the API (i.e., whether the API needs to authenticate the end user or simply the consumer system).
User Context – If the data is personal in nature, highly sensitive, or there are specific data access auditing/logging requirements at the individual level, authentication should be established using the end user credential all the way through to the backend API. Where possible, federated authentication mechanisms such as SAML and OpenID Connect should be used so the authentication token can be traced back to the initiating user. Where federated authentication mechanisms are not available, some user identifier (e.g., User ID) must be passed through the payload of the API request so the backend API can correlate the request to an individual.
System Context – If the data is less sensitive or does not need to be authorized at the individual level (e.g., reporting, financial, reference) and a system-to-system level trust relationship is adequate, then there is no need to propagate the user context. Direct system-to-system authentication methods are typically easier to implement and lower latency as they don’t require the extra interactions with an authentication provider or the extra steps of extracting and passing on the user context in a message.
Authorization
While authentication mechanisms validate the identity that the API consumer, authorization methods validate the permission of that consumer to access an API or components of that API.
API/Resource Level
The simplest authorization method is to grant access to the entire API as long as the consumer is authorized. This is made easier when APIs are sufficiently small in scope or the data is low-sensitivity so that multiple authorization profile are not needed.
Implied Authorization – This is the easiest authorization method on APIs using direct authentication (i.e., non-federated) mechanisms. The assumption is that if the API has validated the user, then the user should have access to the API. It’s important to note that care should be taken where authentication is carried out against credential directories which are shared with other systems and/or security domains (e.g., enterprise LDAP). This method should only be used on data of low sensitivity or where the API authentication is self-contained and does not share authentication data with any other system.
Access Control List – A permitted list of authorized credentials (e.g., API Keys, User IDs) should be implemented on APIs with a small and mostly static set of consumers. The management of ACLs at the individual credential level can get extremely cumbersome as the number of consumers and APIs grow, and thus should only be used in small API environments.
Role Based Access Control – RBAC is the defacto standard for API authorization at scale. Conceptually, consumer credentials should be attributed roles in the credential directory or authentication provider systems. The roles are then passed to the API and authorization is determined based on the role rather than the individual credential.
Externalizing Authorization – Several common mechanisms exist to externalize the authorization decisions from the API to keep the API code small and portable between environments:
- OAuth is the most popular method to pass authorization information between the API and the authorization provider for RESTful APIs. OAuth flows typically places the user in the middle of authorization process in browser-initiated interactions. The ability to define static authorization rules typically depends on the particular Gateway or Access Management solutions implementing OAuth.
- SAML also has provisions for authorization information (assertions) for SOAP web services. Similar to OAuth, the ability to manage authorizations are dependent on the Gateway or Access Management solutions.
- Gateways can be used to manage access to endpoints by providing the façade for API consumers to interact with. Gateway implementations typically involve the API providers having to implicitly trust the Gateway service. Passing user context through Gateways usually require extra design and customization efforts. Many Gateways support OAuth and/or SAML to pass authorization assertions/claims.
- Other Access Management Solutions such as those designed for web applications (e.g., Oracle Access Manager, Open AM) can be used to manage access to APIs and API operations/methods. The level of granularity and the compatibility requirements for the API vary greatly depending on the vendor solution. It is not recommended to implement a web access management solution to externalize API authorizations unless the organization already has one in place as they can be quite expensive and cumbersome to setup and maintain.
Operation/Method Level
APIs can be secured at the Operation (SOAP) or Method (RESTful) level if more granular control is required (e.g., read-only vs. update). This typically requires the API provider to implement code to enforce the authorization. Some externalized access management solutions can also provide Operation or Method level protection. It is generally recommended to avoid managing access at this level as it can be operationally cumbersome. It is typically easier to break the API down into smaller APIs each with a different security/access profile.
Data Filtering
Limiting the amount of data returned via an API, either for privacy or for performance stability is an essential part of designing a secure API.
User-Specific Data
The API code should ensure that only data which the requesting user/system is permitted to see should be returned. Commonly understood identifiers (e.g., user ID, employee ID, system name, account number) should be used and propagated.
Data Segmentation
The ability to return large amounts of data make query APIs targets for DDoS attacks. APIs should be designed to prevent wildcard searches or long running queries. Limits should be set on the amount of data which can be returned per request to mitigate against HTTP timeouts and overflow types of attacks. In cases where large amount of data needs to be exchanged, look to implement a callback handler whereby the return data can be segmented into smaller payloads (e.g., pagination) and sent incrementally to the callback endpoint.
Encryption and Signing
APIs can be encrypted at the transport and message levels depending on the sensitivity of the data being passed.
Transport Encryption
As all APIs take place over HTTP, TLS (i.e., HTTPS) is the simplest form of encryption. This must be the default minimum for all API implementations. Transport encryption prevents the interaction from being observed by unauthorized parties elsewhere in the network, but does not prevent breaches whereby the authentication mechanism is compromised or downstream data leaks.
TLS certificates must be issued by a public or GC approved private certificate authority. Self-signed certificates should not be used for any purpose beyond testing.
Message Encryption
APIs dealing with highly sensitive data should be encrypted at the message layer. Encrypting the API message ensures that only consumers with the appropriate decryption key can view the payload. It provides an additional level of protection from unauthorized access.
WS-Security provides mechanisms (e.g., key exchanges, headers, schemas) for encrypting SOAP payloads.
Javascript Object Signing and Encryption (JOSE) is the best available framework for encrypting and signing JSON messages, but there are a few concerns and considerations:
- Lack of standardized implementations – JOSE is a collection of separate standards (JWT for token, JWS for signing, and JWE for encryption) with no standard direction on how to implement them collectively for each use case (e.g., encrypt the message vs encrypt the entire payload);
- Crypto weaknesses – The underlying crypto for JWE has a known attack vector for potentially exposing private keys. The risk of the flaw can be mitigated by ensuring access to the API is restricted to trusted parties (e.g., IP allow-listing). This means JOSE is not recommended for APIs openly accessible from the Internet.
Message Signing
Similar to message encryption, digital signatures for SOAP web services are supported by the WS-Security standard. In the case of SOAP, a message must be first encrypted for it to be signed. For RESTful APIs, JOSE can be used whereby the JOSE header is used to pass the cryptographic parameters and the entire payload is encrypted and signed. Cleartext JWS should be avoided as the message can be read even if the API consumer doesn’t validate the signature.
Content Protection
APIs must be designed to protect against malicious content and to ensure that responses can’t be intercepted and redirected to inject malicious content back to the API consumer.
Request Validation
APIs are similar in function to web forms in that they take data via HTTP and forward it to the business logic and data layers. Like web forms, the following request validation methods should be implemented:
Schema validation – Having a well-defined request schema and validating against that schema should be the first line of defense against malicious messages. Schema validation can implemented additionally in a gateway or proxy service to reduce the processing load on the API and to move the security perimeter further away from the data. Note that gateway or proxy implementation does not absolve the API itself of schema validation responsibilities. It is only intended as shifting of primary validation further to the perimeter and should not in any way weaken the security posture of the API code itself;
Regex – Implementing regex validation in addition to schema validation further protect against malformed messages and overflow type of attacks looking to exploit some form of data querying edge scenario. Note that regex is only effective on simple field types where the expected content is fairly consistent;
Strong types – The more specific the data structure, the easier it is to identify invalid messages. Define attributes as strong types (e.g., amount, length, name) instead of everything as a String to further limit malformed message attacks. This is also good development practice and allows APIs to be more easily tested; and
Special characters/keywords – Restricting special characters and key words mitigate against classic scripting or injection attacks.
Response Security
The following methods should be implemented to ensure the response message back to the API consumer is as secure as possible.
Response types – The API consumer may request the response be in a particular content type (e.g., JSON, XML, Javascript) in the Accept header. The API provider must first confirm whether the content type requested is safe and supported and ensure the Content-type header is appropriate and not just a copy of the Accept header. For example, the consumer may request Javascript to be returned, but the API provider should return JSON instead.
Error data – Effort must be taken to ensure that unnecessary backend system information (e.g., system names, IP, IDs, stack dumps) are not presented back to the API consumer. Error data is a common area where this is overlooked as it is easier to simply forward the system exception as a part of the response. System errors should be handled internally to the API and error responses should only contain information pertinent to the API consumer.
Virus Protection
APIs accepting attachments, BLOB, or binary payloads (e.g., image upload, documents) are at risk of virus attacks. Most API Gateway products provide virus scanning capabilities, but should be noted that if the API payload are encrypted, the Gateway must be able to decrypt the payload in order to scan it. It is not recommended to handle virus protection within the API code as virus scanning should occur as close to the perimeter as possible.
Page details
- Date modified: