mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-05-25 22:08:06 +02:00
style fix
This commit is contained in:
parent
21499a4d40
commit
473a50dbd3
@ -14,10 +14,10 @@ In this Section, we will specify those API design problems that we see as the mo
|
||||
|
||||
Before we proceed to the patterns, we need to formulate first, how developing APIs differs from developing other kinds of software. Below, we will formulate three important concepts, which we will be referring to in the subsequent chapters.
|
||||
|
||||
1. The more distributed and multi-faceted systems are and the more general-purpose channels of communication used, the more errors occur in the process of interaction. In the most interesting case of distributed many-layered client-server systems, raising an exception on client side (like losing context as a result of app crash and restart), server side (the pipeline of executing a query threw at some stage), communication channel (connection fully or partially lost), or any other interim agent (intermediate web-server hasn't got a response from backend and returned a gateway error) is a norm of life, and all systems must be designed in a manner that **in a case of exception of any kind, API clients must be able to restore their state** and continue operating normally.
|
||||
1. The more distributed and multi-faceted systems are and the more general-purpose channels of communication used, the more errors occur in the process of interaction. In the most interesting case of distributed many-layered client-server systems, raising an exception on the side of a client (like losing context as a result of app crash and restart), server (the pipeline of executing a query threw at some stage), communication channel (connection fully or partially lost), or any other interim agent (intermediate web-server hasn't got a response from backend and returned a gateway error) is a norm of life, and all systems must be designed in a manner that in a case of an exception of any kind, API clients must be able to restore their state and continue operating normally.
|
||||
|
||||
2. The more partners use the API, the more chance is that some of the mechanisms of the expected workflow are implemented wrongly. In other words, **not only physical mistakes related to network or server overload should be expected, but also logical ones caused by improper API usage** (and, in particular, there should be safeguards to avoid errors in one partner's code leading to a denial of service for other partners).
|
||||
2. The more partners use the API, the more chance is that some of the mechanisms of the expected workflow are implemented wrongly. In other words, not only physical mistakes related to network or server overload should be expected, but also logical ones caused by improper API usage (and, in particular, there should be safeguards to avoid errors in one partner's code leading to a denial of service for other partners).
|
||||
|
||||
3. Any part of the system might introduce unpredictable latencies to serving requests, and those latencies might be quite high — seconds and tens of seconds. Even if you fully control the execution environment and network, client apps are fully capable of impeding themselves as they might be written in a suboptimal manner or be executed on a low-performant or overloaded device. Because of that, **proper API design must not rely on critical operations being executed quickly**. This includes:
|
||||
* if carrying out some task through API requires making a sequence of calls, there must be a mechanism for resuming the operation from the current step if needed instead of re-starting it from the beginning;
|
||||
* operations affecting shared resources should impose some locking mechanisms for the operation duration.
|
||||
3. Any part of the system might introduce unpredictable latencies when serving requests, and these latencies could be quite high, up to seconds and tens of seconds. Even if you have full control over the execution environment and network, client apps may hinder themselves due to suboptimal code or execution on low-performing or overloaded devices. As a result, it is important to ensure that proper API design does not rely on critical operations being executed quickly. This includes:
|
||||
* If carrying out a task through the API requires making a sequence of calls, there should be a mechanism in place to resume the operation from the current step if needed, instead of restarting it from the beginning.
|
||||
* Operations that affect shared resources should have locking mechanisms in place for the duration of the operation.
|
@ -1,25 +1,23 @@
|
||||
### [Authenticating Partners and Authorizing API Calls][api-patterns-aa]
|
||||
|
||||
Before we proceed further to discussing technical matters, we feel obliged to make an overview of the problems of authorizing API calls and authenticating clients that make it. Based on the very same main principle (“an API serves as a multiplier to both your opportunities and mistakes”), organizing authorization & authentication (AA) is one of the most important problems that any API vendor faces, especially if we talk about public APIs. So it's rather surprising that there is basically no standard approach to it: every big vendor develops its own interface to solve AA issues, and those interfaces are often quite archaic.
|
||||
Before we proceed further to discussing technical matters, we feel obliged to provide an overview of the problems related to authorizing API calls and authenticating clients. Based on the main principle that “an API serves as a multiplier to both your opportunities and mistakes,” organizing authorization and authentication (AA) is one of the most important challenges that any API vendor faces, especially when it comes to public APIs. It is rather surprising that there is no standard approach to this issue, as every big vendor develops its own interface to solve AA problems, and these interfaces are often quite archaic.
|
||||
|
||||
If we put aside implementation details (regarding which we once more strongly recommend not inviting a bicycle and using standard techniques and security protocols), there are basically two approaches to authorizing an API call:
|
||||
* introduce a special “robot” type of account into the system, and carry on the operations on behalf of the robot account;
|
||||
* authorize the caller system (backend or client application) as a single entity (usually API keys, signatures, or certificates are used for the purpose of authenticating such calls).
|
||||
If we set aside implementation details (for which we strongly recommend not reinventing the wheel and using standard techniques and security protocols), there are basically two approaches to authorizing an API call:
|
||||
* Introducing a special “robot” type of account into the system, and carrying out the operations on behalf of the robot account.
|
||||
* Authorizing the caller system (backend or client application) as a single entity, using API keys, signatures, or certificates for the purpose of authenticating such calls.
|
||||
|
||||
The difference between the two approaches is the access granularity:
|
||||
* if an API client is making requests as a regular user of the system, then it can conduct only the operations allowed to a specific user which in most cases implies it might have access only to a partial dataset within the API endpoint;
|
||||
* if the caller system is authorized, it implies that it has full access to the endpoint and might supply any parameters (i.e., has access to the full dataset exposed through the endpoint).
|
||||
The difference between the two approaches lies in the access granularity:
|
||||
* If an API client is making requests as a regular user of the system, then it can only perform operations allowed for a specific user, which often means it might have access only to a partial dataset within the API endpoint.
|
||||
* If the caller system is authorized, it implies that it has full access to the endpoint and can supply any parameters, i.e., has access to the full dataset exposed through the endpoint.
|
||||
|
||||
Therefore, the first approach is more granular (the robot might be a “virtual employee” and have access only to some limited dataset) and is a natural choice for those APIs that are supplemental to the existing service for end users (and thus might reuse the existing AA solutions). The disadvantages of the approach are:
|
||||
Therefore, the first approach is more granular (the robot might be a “virtual employee” with access only to a limited dataset) and is a natural choice for APIs that are supplemental to an existing service for end users (and thus can reuse the existing AA solutions). However, this approach has some disadvantages:
|
||||
* The need to develop a process for securely fetching authorization tokens for the robot user (e.g., via having a real user generate tokens in the web UI), as regular login-password authentication (especially multi-factored) is not well-suited for API clients.
|
||||
* The need to make exceptions for robot users in almost every security protocol:
|
||||
* Robots might make many more requests per second than real users and might perform several queries in parallel (possibly from different IP addresses located in different availability zones).
|
||||
* Robots do not accept cookies and cannot solve captchas.
|
||||
* Robots should not be logged out or have their token invalidated “just in case” (as it would impact the partner's business processes), so it is usually necessary to invent specific long-lived tokens for robots and/or token renewal procedures.
|
||||
* Finally, you may encounter significant challenges if you need to allow robots to perform operations on behalf of other users (as you will have to either expose this functionality to all users or, conversely, hide its existence from them).
|
||||
|
||||
1. The necessity to develop the process of safely fetching authorization tokens for the robot user (for example, via making a real user generate tokens somewhere in the web UI) as regular login-password authentication (especially multi-factored) is poorly applicable to API clients.
|
||||
2. The necessity of to make exceptions for robot users in almost every security protocol:
|
||||
* robots might make much more requests per second than real users, and might do several queries in parallel (possibly from several different IP addresses located in different availability zones)
|
||||
* robots won't set cookies and can't solve captcha
|
||||
* robots should not be logged out or have their token invalidated “just in case” (as it means the partner's business processes will suffer), so it is usually necessary to invent specific long-living tokens for robots and/or token renew procedure.
|
||||
3. Finally, you will face big problems if it happens you *need* to allow robots to conduct operations on behalf of other users (as you will have to either expose this functionality to all users or, conversely, hide its existence from them).
|
||||
|
||||
If the API is not about providing additional access to some service for end users, it's usually much easier to opt-in for the second approach and authorize clients with API keys. Per-endpoint granularity might be achieved in this case (i.e., allowing partners to regulate the set of permitted endpoints for a key); developing more granular access might be much more complex and rarely see realization.
|
||||
|
||||
Both approaches might be morphed into one another (if we allow robot users to conduct operations on behalf of any other users, it's effectively API key-based authorization; if we allow binding some limited dataset to API key, it effectively becomes a user account), and there are some hybrid systems in the wild (the request requires to be signed with both API key and user token).
|
||||
If the API is not about providing additional access to a service for end users, it is usually much easier to opt for the second approach and authorize clients with API keys. In this case, per-endpoint granularity can be achieved (i.e., allowing partners to regulate the set of permitted endpoints for a key), while developing more granular access can be much more complex and rarely implemented.
|
||||
|
||||
Both approaches can be morphed into each other (e.g., allowing robot users to perform operations on behalf of any other users effectively becomes API key-based authorization; allowing binding of a limited dataset to an API key effectively becomes a user account), and there are some hybrid systems in the wild (where the request requires being signed with both an API key and a user token).
|
Loading…
x
Reference in New Issue
Block a user