API Development - Overview and Best Practice
14. November 2023
Published in:
WebdevelopmentFundamentals for Basic Understanding
Without well-documented programming interfaces, information technology as we know it today would be unimaginable. An Application Programming Interface (API) facilitates the communication between different programs and services. In times of distributed systems and web applications, which are gaining increasing importance, the need to adhere to certain standards and conventions is also rising. In this article, we aim to provide an initial overview of the opportunities and possibilities of well-documented APIs. The article will attempt to impart a basic understanding of programming interfaces, independent of programming language. For basic understanding, it doesn't matter whether Ruby, PHP, or JavaScript is used. The focus will be on the nature of web APIs that are programmed following the REST paradigm.
HTTP and REST: Symbiosis for Effective Web Services
REST (Representational State Transfer) is not a protocol like SOAP, but an architectural paradigm that represents the state of a web service. It does not require method information in the Uniform Resource Identifier (URI), as the URI indicates the function, not the name and location of a resource. The main advantage of REST is its seamless integration with the existing World Wide Web infrastructure and the widespread REST compliance of many services.
REST ≠ Protocol
REST = Architectural Paradigm
A common misconception is that REST is specifically tied to one application. Instead, it operates independently and requires only a uniform interface. The HTTP protocol is often used, as HTTP and REST form a harmonious duo that complements each other.
HTTP (Hypertext Transfer Protocol) acts as an application layer protocol, defining the possible actions through methods such as GET
, POST
, PUT
, and DELETE
. The use of REST-compliant HTTP eliminates the need for protocols like SOAP.
Over the years, however, a strong alternative to REST has emerged: GraphQL. GraphQL is a powerful query language for APIs and a runtime environment for executing these queries with the existing data.
Unlike REST, which requires an endpoint per resource, GraphQL offers a single endpoint for precise client requests. This allows clients to request specific data while avoiding over- and under-fetching, making it a more efficient method for accessing data.
Data Structures: The DNA of Your API
Choosing the right data structure for your API is a crucial decision that should be based on the specific requirements of your project. The choice can have a significant impact on the flexibility, speed, and user-friendliness of your API.
Commonly used data formats are XML
and JSON
. XML, or "Extensible Markup Language," is a markup language designed to represent structured data in text-based form. It is known for its strict typing and detailed validation, which allows mapping complex and highly structured data. This can be particularly useful in environments where precision and control over the data structure are crucial.
On the other hand, JSON
- JavaScript Object Notation - is a lightweight data interchange format, both human-readable and easy to generate and process. JSON has become the preferred format for APIs in many use cases, mainly because of its ease of processing and seamless integration into JavaScript-based applications.
The choice between these formats should be based on a careful review of your specific requirements. Keep in mind that changing the data format later often requires extensive revisions to your API, so it's worth choosing the right one from the start.
Finally, when designing your API, you should also consider future extensibility. A well-thought-out data structure will allow you to add new features and improvements effortlessly without compromising existing functionality.
Authentication
As mentioned, REST is stateless. So how do you prevent users from accessing content they're not supposed to? There are various solutions to this, with OAuth 2.0 currently being the most widespread. However, we would like to take a brief look at alternative authentications.
OAuth 2.0 and OpenID Connect
OAuth 2.0 is an industry-standard protocol for authorization. It allows third-party applications to grant access to web resources on behalf of a user without revealing their login credentials. OAuth 2.0 focuses primarily on providing authorization and defines four roles: resource owner, client, authorization server, and resource server.
A key application of OAuth 2.0 is the creation of API keys that grant third parties access to specific resources. These keys, also known as "Access Tokens," have a limited lifespan and can be renewed as necessary.
Although OAuth 2.0 provides a robust framework for authorization, it does not offer authentication support in itself. This is where OpenID Connect (OIDC) comes into play. OIDC is an identity layer that builds on top of OAuth 2.0, allowing clients to verify a user's identity based on the authentication performed by an authorization server and to obtain basic profile information about the user.
Together, OAuth 2.0 and OpenID Connect form a powerful combination for securely handling authentication and authorization in modern web applications and APIs. They offer a number of benefits:
- Delegation of Permissions: OAuth 2.0 allows users to delegate access to their data securely without revealing their credentials, making it ideal for scenarios where third-party applications need access to user data.
- Single Sign-On (SSO): With OpenID Connect, users can use the same set of credentials to sign in to multiple applications, improving the user experience and reducing the number of credentials needed.
- Flexibility: OAuth 2.0 defines multiple "flows" (authorization code, implicit, resource owner password credentials, and client credentials), which are tailored to different use cases, offering high flexibility for developers.
- Identity Information: OpenID Connect facilitates the exchange of identity information in the form of ID tokens, which are structured like JWTs and contain claims about the user.
As with JWTs, OAuth 2.0 and OpenID Connect must be carefully implemented to avoid potential security issues. In particular, sensitive data should always be encrypted, and appropriate measures should be taken to prevent the misuse of access tokens.
HTTP-Basic
HTTP-Basic is a simple authentication method built into the HTTP protocol. It allows clients to send requests with an Authorization
header that contains the username and password in a base64-encoded format. The header structure is as follows: Authorization: Basic base64(username:password)
.
Although HTTP-Basic is simple to implement and use, it has several limitations to consider:
- No Built-in Security: HTTP-Basic offers no application-level security. Usernames and passwords are transmitted in clear text across the network unless protected by a secure connection (e.g., HTTPS).
- No Token Management: Unlike OAuth 2.0 or JWT, HTTP-Basic does not offer a way to manage sessions or tokens, which can limit scalability and control over user sessions.
- Limited User-Friendliness: As HTTP-Basic does not support advanced authentication features such as Single Sign-On or multi-factor authentication, it can be less user-friendly in some cases.
Despite these limitations, HTTP-Basic can be useful in certain scenarios, especially when simplicity and convenience are prioritized, and the application is deployed exclusively through secure connections. However, it should always be used with caution and is generally not suitable for APIs that are exposed to the public Internet.
JSON Web Tokens (JWTs)
A JSON Web Token (JWT) is an open standard (RFC 7519) that allows information to be securely transferred between two parties. A JWT is a compact, URL-safe means of representing claims exchanged between two parties. The claims in a JWT are encoded in JSON, making the token easy to use and very flexible.
JWTs consist of three parts: a header, a payload, and a signature. The header typically indicates the token type (usually JWT) and the algorithm used for signature, such as HMAC SHA256 or RSA. The payload contains the "claims" or statements about an entity (usually the user) and additional metadata. The signature is a hash of the combined header and payload data, along with a secret key.
There are several key advantages to using JWTs for authentication:
- Self-Validating: JWTs are self-validating. They contain all the information needed to validate themselves, with no additional call to the server or database needed to check the token's validity.
- Compact: Due to their compact size, JWTs can be easily transmitted through URLs, POST parameters, or HTTP headers, making them particularly useful for scenarios where a token needs to be carried in an HTTP request.
- Flexible: JWTs can be used for all types of claims, including authentication information, roles and rights, and even user data.
Despite their many advantages, it's important to note that JWTs must be implemented carefully to avoid security issues. Sensitive information should never be stored in a JWT without encryption. Furthermore, there should be an appropriate mechanism for revoking or updating tokens, as JWTs remain valid until their expiration.
A common practice is the use of short-lived access tokens and longer-lived refresh tokens. When the access token expires, the refresh token can be used to obtain a new access token without requiring the user to authenticate again. This ensures a good balance between usability and security.
Versioning
The older your API gets, the more likely you will want or need to change something, whether to implement additional functions or to close security gaps. But with every change, take care not to annoy your users, who may rely on existing features and structures. Of course, you don't have to keep the old version of an API indefinitely. Announce changes well in advance and give users a generous transition period. Opinions differ on how versioning should be done, but let's briefly present two of the most common methods:
URL-Based Versioning
Some APIs use the URL path to indicate the version, such as: api/v1/users
. This approach is simple and easy to understand since the version is visible directly in the URL. However, it can also lead to confusion when different versions of endpoints coexist.
Header-Based Versioning
Header-based versioning uses HTTP headers to indicate the API version. This approach keeps the URL clean and allows the versioning to be separated from the rest of the application. However, it can be more challenging since the versioning information is not directly visible in the URL.
Parameter-Based Versioning
With parameter-based versioning, the API version is indicated as a query parameter in the URL, such as api/users?v=1
. This approach is flexible and easy to implement but can lead to messy URLs if many parameters are involved.
In practice, we almost always use the URL-based versioning method. However, there is no "right" or "best" approach to API versioning - it depends on the specific requirements and context of your application. The important thing is to choose a method that is understandable and easy to use for your team and users. Also, make sure that changes are well documented and that enough lead time is provided for adapting to new versions, ensuring smooth and continuous use of your API.
API-First Approach
The API-First approach actually has the potential to fundamentally change the dynamics of development. It's more than just a mindset - it's a paradigm shift that redefines the way software applications are designed and developed.
What Does API-First Mean?
With the API-First approach, the development process starts with the API specification. Instead of developing an application first and then creating an API as an interface, the API-First approach reverses this order. An API is created first, setting the framework for application development. Subsequently, the application itself is developed based on this API.
The Benefits of API-First Approach
There are a number of advantages that the API-First approach offers:
- Consistency: When an API is created first, developers can ensure that it is consistent and standardized before being integrated into the application, contributing to a more robust and maintainable application.
- Reusability: APIs developed as part of an API-First approach are often modular and reusable. This means they can be used in different contexts and for various purposes, increasing developer efficiency and productivity.
- Collaboration: The API-First approach promotes collaboration between backend and frontend teams. Both teams can work simultaneously because the frontend can be developed on a "mock" version of the API while the backend team creates the actual API.
- Future-Proof: Since the API-First approach centers the API in the application development process, applications developed in this way are better prepared for future changes and enhancements.
API-First Approach in Practice
Some practical steps to implement the API-First approach might look like this:
- Planning and Design: Define the basic requirements of your application and design the API specification accordingly. Tools like OpenAPI or Swagger can be helpful in this process.
- API Development: Build the API according to the specification. At this stage, you can also create a "mock" version of the API for the frontend team.
- API Testing: Thoroughly test the API to ensure it functions correctly and meets the requirements. Tools like Postman can be useful here.
- API Integration: Integrate the API into your application and begin actual application development.
By emphasizing the API as the central element of the development process, the API-First approach can help create more robust, flexible, and future-proof applications. With the API-First approach, you'll be at the forefront of modern software development.
API Programming is a Versatile Challenge
Of course, a short, general article that does not delve into programming languages cannot provide a complete introduction to API programming. Keep a few basic rules in mind when developing your own APIs. Most likely, any problem you encounter while developing an interface has already been encountered by another programmer elsewhere. Be curious, look at existing solutions, adapt these approaches to your project if suitable, and thus come to an optimized solution.
Do you have questions about interface programming? Contact us! At mindtwo in Bonn, we'll be happy to advise you on your web project.
Can we help?
You have an exciting project and want to work with us? Contact us now!