To ensure an application is secure, developers tend to do —
- Input validation
- Using Secure Sockets Layer (SSL) protocol
- Validating content types
- Maintaining audit logs
- Protecting against cross-site request forgery (CSRF)
- Protecting against cross-site scripting (XSS)
Beyond these general web application security practices, there are additional techniques that apply specifically to web APIs that we expose to other developers or end users.
Authentication and Authorization
The process of verifying who you are is Authentication. Web applications usually accomplish this by asking you to log in with a username and password. This combination is checked against an existing username/password record to ensure the request is authentic.
The process of verifying that you’re permitted to do what you’re trying to do is Authorization. A web application might allow you to view a page, but not allow you to edit that page unless you are an administrator.
I’s the simplest technique used to enforce access control on the web. The clients send HTTP requests with an Authorization header which consists of the work “Basic” followed by a space and a string generated by combining username and password with colon (username:password) and encoding it with base64.
Authorization: Basic dXNlcjpwYXNzd2yZA==
- The password is sent over the wire in base64 encoding which can be easily converted into plaintext
- SSL can solve #1 but once on the server side, the password may be routed in plaintext after SSL termination
- Applications are required to store these credentials in plaintext or in a way that they can decrypt them
- #3 can be solved using SALT and one-way hash techniques but is a security overhead
- The password may be cached on the browser, if user permits. This can be stolen by the any user on the shared machine
Famous companies like Facebook and Google use a more secure form of Basic authentication for login workflows. MFA adds a second layer of security. To understand more, refer https://quakkels.com/posts/what-happens-when-you-login/
It is an open standard that allows users to grant access to applications without sharing passwords with them.
Benefits of OAuth
- The biggest benefit of OAuth is that users do not need to share passwords with the applications. For example, TripAdvisor wants to build an application that will use a user’s Facebook identity, profile, contact list and other FB data. With OAuth, tripAdvisor can redirect the user to Facebook, where they can authorize TripAdvisor to access their information. After the user authorizes the sharing of data, tripAdvisor can then call the Facebook API to fetch this information.
- Second benefit is thet API providers’ users can grant selective permissions. Each application has different requirements of what data it needs from an API provider. For example, TripAdvisor would receive permission to read a user’s profile, contacts and more but it cannot post on Facebook on user’s behalf.
- If at any point a user would like to revoke TripAdvisor’s access to their Facebook data, they can simply go to their Facebook settings and revoke it without changing their password.
With OAuth, applications use an access token to call APIs on behalf of a user. The generation of this token happens in a multistep flow.
Before an application can start the OAuth flow, it needs to be registered with the API provider. During registration, developers provide a redirect URL to which the API provider can redirect the authorizing user. The API provider issues a client ID and client secret that are unique to the application. The client ID can be public, whereas the client secret should be kept confidential.
After the registration, the application can generate an access token by following the below steps —
- Applications typically show users a button labeled “Continue with Facebook” or “Continue with Google”. When users click the button, they are redirected to the API provider’s authorization URL. While redirecting, the application sends client ID, the permissions requested in a parameter called scope, an optional unique state parameter and (optionally) a redirect URL.
- The API provider should clearly indicate what permissions the application is requesting. If the user denies the authorization, they are redirected back to the application’s redirect URL with an access_denied error. If the user approves the request, they are redirected back to the application with an authorization code.
- Upon successful authorization, the application sends the client ID, client secret, authorization code and redirect URL to the API provider to receive an access token. The authorization code provided can only be used once; this helps in preventing replay attacks. Applications can then use this access token to access resources on user’s behalf.
OAuth scopes are used to limit an application’s access to user’s data. For instance, an application might only need to identify a user. Rather than requesting access to all of the user’s data, the application can request access to only the user’s profile information by means of a granular OAuth scope.
Often, API providers open up their APIs without thinking too much about scopes. Only when the API begins to be widely adopted or is being abused do they start realizing the need for additional scopes and at that time, introducing new scopes becomes complicated.
Token and Scope Validation
After the application has received the access token, it can begin making API requests using this token by setting the HTTP Authorization header.
Authorization: Bearer xoxp-1504398475-a24afg879
"text":"This is the message text",
When receiving these requests, there are 2 things that the API provider needs to verify —
- Access token is valid by matching the given access token with the granted access token in your database
- The access token has the required scope for the action that the request is supposed to perform
If either check fails, the API should return an error like —
Token Expiry and Refresh Tokens
OAuth protocol allows limiting the validity of the access token. Many APIs chose to issue tokens that expire in few hours or days, so that the impact of a compromise can be contained.
If an access token is issued with limited validity, there should be a way for applications to obtain a new token. One way to do this is by issuing refresh tokens.
A refresh token is a special token used to obtain a new access token when the current access token expires. Applications need to provide the client ID, client secret and the refresh token to generate a new access token.
Even if the access token does not expire, it can be a good idea to share refresh tokens. This way, in case of compromise, an app developer can rotate an existing access token and generate a new one.
Short lived access tokens are more secure because —
- If an access token is compromised, it will work only until it expires.
- If a refresh token is compromised, it will be useless without the client secret, which is typically not stored with access tokens or refresh tokens.
- If both the refresh token and the client secret are compromised and the attacker generates a new access token, the compromise can potentially be detected because typically refresh tokens are one-time use only.
Listing and Revoking Authorizations
For various reasons, a user might want to know which applications can access their data and might want to revoke access to one or more of them. To support this use case, most API providers typically offer a page that lists the applications that a user has authorized along with the ability to revoke access.
A snapshot of how FB provides this feature to users—
Best practice : Because access tokens are sent as part of every HTTP request, it’s important that your API endpoints require HTTPS. This prevents man-in-the-middle attacks.