# (bing) Api Security
## How to Secure Your API with Different Authentication and Authorization Methods
API security is the practice of protecting APIs from cyberattacks and misuse. Proper API security measures ensure that all processed requests to the API are from legitimate sources and valid. Security best practices also ensure that all responses from the API are protected from interception or exploitation.
In this blog post, we will explore some of the common authentication and authorization methods that you can use to secure your API, such as HTTP Basic Authentication, API Key Authentication, OAuth 2.0, OpenID Connect, JWT, HMAC, and SAML. We will also compare their advantages and disadvantages and provide some examples of how to implement them.
## Authentication vs Authorization
Before we dive into the details of each method, let's clarify the difference between authentication and authorization in the context of access to APIs:
- **Authentication** - The process of verifying the identity of a user or app that accesses the API. Authentication may be done through credentials such as username and password, a certificate, or through single sign-on (SSO) or other methods.
- **Authorization** - The process of determining whether a user or app has permission to access a particular API, often through a token-based protocol such as OAuth 2.0.
## HTTP Basic Authentication
This is one of the simplest methods, which uses a username and password as a single value and passes it through a special HTTP header known as authorization. The value is encoded with Base64 and compared to the stored credentials.
This method is easy to implement, but not very secure, as it exposes the credentials in plain text and does not support granular access control or revocation.
To use this method, you need to add an authorization header to your API request with the value `Basic <base64-encoded username:password>`. For example:
```
GET /api/users HTTP/1.1
Host: example.com
Authorization: Basic dXNlcjpwYXNzd29yZA==
```
## API Key Authentication
This method uses a unique identifier (API key) that is assigned to each client or user and passed as a query parameter or a header in each API request. The API key is verified against a database or a cache to authorize the request.
This method is also easy to implement, but not very secure, as it exposes the API key in plain text and does not support granular access control or revocation.
To use this method, you need to add an api_key parameter or header to your API request with the value of your API key. For example:
```
GET /api/users?api_key=1234567890 HTTP/1.1
Host: example.com
```
## OAuth 2.0
This is a standard authorization framework that is widely used to secure access to resources such as web APIs. OAuth 2.0 restricts actions of what a client app can perform on resources on behalf of the user, without ever sharing the user's credentials.
OAuth 2.0 uses tokens that are issued by an authorization server and validated by a resource server. OAuth 2.0 supports different grant types or flows for different scenarios, such as authorization code, implicit, client credentials, password, or device code.
OAuth 2.0 is more secure and flexible than the previous methods, as it supports encryption, revocation, scopes, and expiration of tokens. However, it is also more complex to implement and requires additional components and infrastructure.
To use this method, you need to follow these steps:
1. Register your client application with the authorization server and obtain a client ID and client secret (if applicable).
2. Redirect the user to the authorization server's authorization endpoint with the required parameters such as response_type, client_id, redirect_uri, scope, state, etc.
3. The user authenticates and consents to the requested permissions on the authorization server's UI.
4. The authorization server redirects the user back to your client application's redirect URI with an authorization code (if using authorization code grant type) or an access token (if using implicit grant type) in the query string or fragment.
5. The client application exchanges the authorization code for an access token (and optionally a refresh token) by sending a POST request to the authorization server's token endpoint with the required parameters such as grant_type, code, client_id, client_secret, redirect_uri, etc.
6. The authorization server returns an access token (and optionally a refresh token) in JSON format.
7. The client application adds an authorization header to its API request with the value `Bearer <access_token>`.
8. The resource server validates the access token and returns the requested resource if authorized.
For example:
```
GET /authorize?response_type=code&client_id=abc&redirect_uri=https://example.com/callback&scope=read&state=xyz HTTP/1.1
Host: auth.example.com
```
```
HTTP/1.1 302 Found
Location: https://example.com/callback?code=123&state=xyz
```
```
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=123&client_id=abc&client_secret=def&redirect_uri=https://example.com/callback
```
```
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "456",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "789"
}
```
```
GET /api/users HTTP/1.1
Host: api.example.com
Authorization: Bearer 456
```
#### References
OAuth 2.0 is a standard authorization framework that is widely used to secure access to resources such as web APIs. You can find the official specification and its extensions here: https://oauth.net/2/
DigitalOcean has an informative tutorial on OAuth 2.0 that explains the roles, flows, and use cases of the protocol. You can check it out here: https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
Auth0 has a helpful guide on OAuth 2.0 that clarifies the difference between authentication and authorization and how to implement OAuth 2.0 with Auth0. You can read it here: https://auth0.com/intro-to-iam/what-is-oauth-2
## OpenID Connect
This is an extension of OAuth 2.0 that provides user authentication and single sign-on (SSO) functionality. OpenID Connect uses an identity token (ID token) that contains information about the user's identity and session state. The ID token is issued by an identity provider (IdP) and validated by a relying party (RP).
OpenID Connect is useful when you need to associate some private data with a single person or when you want to leverage existing identity providers such as Google or Facebook.
To use this method, you need to follow these steps:
1. Register your client application with the IdP and obtain a client ID and client secret (if applicable).
2. Redirect the user to the IdP's authorization endpoint with the required parameters such as response_type, client_id, redirect_uri, scope, state, nonce, etc. The scope parameter must include the value `openid`.
3. The user authenticates and consents to the requested permissions on the IdP's UI.
4. The IdP redirects the user back to your client application's redirect URI with an ID token (and optionally an authorization code or an access token) in the query string or fragment.
5. The client application validates the ID token by checking its signature, issuer, audience, expiration, nonce, etc.
6. The client application extracts the user information from the ID token and optionally requests additional user information from the IdP's userinfo endpoint using the access token.
7. The client application adds an authorization header to its API request with the value `Bearer <access_token>` or passes the ID token as a credential.
8. The resource server validates the access token or the ID token and returns the requested resource if authorized.
For example:
```
GET /authorize?response_type=id_token&client_id=abc&redirect_uri=https://example.com/callback&scope=openid%20profile%20email&state=xyz&nonce=123 HTTP/1.1
Host: idp.example.com
```
```
HTTP/1.1 302 Found
Location: https://example.com/callback#id_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLmNvbSIsInN1YiI6IjEyMzQiLCJhdWQiOiJhYmMiLCJleHAiOjE2Mzg0MjEwMDAsImlhdCI6MTYzODQxNzQwMCwibm9uY2UiOiIxMjMiLCJuYW1lIjoiSm9obiBEb2UiLCJlbWFpbCI6ImpvaG5AZXhhbXBsZS5jb20ifQ.Ry8x4vzD3eXC49ZGH7aWRU9n6i8xKq7UG3r4WKZ4Fm0&state=xyz
```
```
GET /api/users HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLmNvbSIsInN1YiI6IjEyMzQiLCJhdWQiOiJhYmMiLCJleHAiOjE2Mzg0MjEwMDAsImlhdCI6MTYzODQxNzQwMCwibm9uY2UiOiIxMjMiLCJuYW1lIjoiSm9obiBEb2UiLCJlbWFpbCI6ImpvaG5AZXhhbXBsZS5jb20ifQ.Ry8x4vzD
```
---
## JWT (JSON Web Token)
This is a token-based authentication and authorization mechanism. It is used for transmitting claims (user identity, permissions, etc.) between parties. It does not rely on a centralized authentication server or session state. It is commonly used in single-page applications (SPAs) and mobile applications. It can be used for authentication and authorization.
A JWT consists of three parts: header, payload, and signature. The header contains information about the token type and the algorithm used to generate the signature. The payload contains the claims or data that are relevant for the API access. The signature is used to verify the integrity and authenticity of the token. A JWT is passed as a bearer token in the authorization header of the API request.
To use this method, you need to follow these steps:
1. The user or client app sends a sign-in request with their credentials to the API.
2. The API verifies the credentials and creates a JWT with the required claims and signs it using a secret key.
3. The API returns the JWT to the user or client app.
4. The user or client app verifies the JWT on its own side and stores it locally.
5. The user or client app adds an authorization header to its API request with the value `Bearer <JWT>`.
6. The API validates the JWT by checking its signature, issuer, audience, expiration, etc. and returns the requested resource if authorized.
For example:
```
POST /signin HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"username": "john",
"password": "password"
}
```
```
HTTP/1.1 200 OK
Content-Type: application/json
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsInN1YiI6ImpvaG4iLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImV4cCI6MTYzODQyMTAwMCwiaWF0IjoxNjM4NDE3NDAwLCJzY29wZSI6InJlYWQifQ.qNrcqfzfwfBD5VcGgjq_KfDbxZCQ0KPNyXbCt2LmFME"
}
```
```
GET /api/users HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsInN1YiI6ImpvaG4iLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImV4cCI6MTYzODQyMTAwMCwiaWF0IjoxNjM4NDE3NDAwLCJzY29wZSI6InJlYWQifQ.qNrcqfzfwfBD5VcGgjq_KfDbxZCQ0KPNyXbCt2LmFME
```
## HMAC (Hash-based Message Authentication Code)
This is a cryptographic authentication and authorization mechanism. It is used for verifying the integrity and authenticity of a message or data. It relies on a shared secret key between the client and the server.
This method is very secure, as it provides strong encryption, identity verification, and non-repudiation. However, it requires both parties to have access to the same secret key and to synchronize their clocks.
To use this method, you need to follow these steps:
1. The client generates a nonce (a random number) and a timestamp for each API request.
2. The client concatenates the nonce, timestamp, HTTP method, request URI, and request body (if any) into a single string.
3. The client computes an HMAC from the string using a hash function (such as SHA-256) and a secret key that is shared with the server.
4. The client adds an authorization header to its API request with the value `HMAC <nonce>:<timestamp>:<HMAC>`.
5. The server receives the API request and extracts the nonce, timestamp, and HMAC from the authorization header.
6. The server checks if the nonce has been used before and if the timestamp is within an acceptable range.
7. The server concatenates the nonce, timestamp, HTTP method, request URI, and request body (if any) into a single string.
8. The server computes an HMAC from the string using the same hash function and secret key as the client.
9. The server compares the computed HMAC with the received HMAC and returns the requested resource if they match.
For example:
```
GET /api/users HTTP/1.1
Host: api.example.com
Authorization: HMAC 1234567890:1638417400:8f41f67f8e403d4e6b4a48d21dbb64e5a5c6f39c1d4fde79d9f5c6fb1e4b16a7
```
## SAML (Security Assertion Markup Language)
This is an XML-based authentication and authorization mechanism. It is used for exchanging authentication and authorization data between an identity provider (IdP) and a service provider (SP). It relies on a trust relationship between the IdP and the SP.
This method is useful for web applications and SSO scenarios that involve multiple domains or organizations. It can be used for authentication and authorization.
A SAML consists of three components: assertions, protocols, and bindings. Assertions are statements that contain information about the user's identity, attributes, or permissions. Protocols are rules that define how assertions are requested and delivered. Bindings are methods that define how SAML messages are transported over different protocols such as HTTP or SOAP.
To use this method, you need to follow these steps:
1. Register your client application (SP) with the IdP and obtain a metadata file that contains information such as entity ID, endpoints, certificates, etc.
2. Redirect the user to the IdP's single sign-on (SSO) endpoint with a SAML authentication request that contains information such as issuer, destination, ID, etc.
3. The user authenticates on the IdP's UI and consents to the requested permissions.
4. The IdP returns a SAML response that contains a SAML assertion to the user's browser.
5. The user's browser posts the SAML response to the SP's assertion consumer service (ACS) endpoint.
6. The SP validates the SAML response by checking its signature, issuer, audience, expiration, etc. and extracts the user information from the SAML assertion.
7. The SP adds an authorization header to its API request with the value `SAML <SAML assertion>` or passes the SAML assertion as a credential.
8. The API validates the SAML assertion and returns the requested resource if authorized.
For example:
```
GET /sso?SAMLRequest=fZFfa8IwFMXfBb9DyXvaJtZ1BqsURRC2Mabbw95ivcG20FrWz%2FfOdm5CJLvnnvmm75%2FzJ4XgK1WjCtA2pZI8kFQpw4qk9lKphnEwWkKtNQqyCILYzYw3kNjGpZ1DeR%2B8ZGx8kS9UYMSotD3xjvVfyhr%2B%2FyT%2B%2FyjAWWLrgmEJ9VrKoIVGmEhPei%2FyCmLJmNV4js7nANZcL8WKGHaTcMwTh0L4Qgq2ErVUHtcyUyvlwHxgCFY0hGK21bw0xpLzaGpeUIzcLhaMRlEx%2F5X%2B%2B3NjSMwYzI45XUzGLOMWkSEOhhZNYxjuIAmlIzDhHPfpbVl0dR%2F7QrHlTwonBa5AYWU4ZEQGClpRwE69pGMYbDhlM4PNH6xP0rA8%3D HTTP/1.1
Host: idp.example.com
```
```
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head>
<script>
function postForm() {
document.forms[0].submit();
}
</script>
</head>
<body onload="postForm()">
<form method="POST" action="https://sp.example.com/acs">
<input type="hidden" name="SAMLResponse" value="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6
```
---
## OAuth 2.0 Grant Types
OAuth 2.0 grant types are different ways of obtaining an access token from an authorization server. The access token is then used to authorize requests to the protected API resources. The grant type you use depends on the type of client application and the level of trust between the client and the authorization server. Here are some of the common grant types:
- **Authorization Code**: This is the most common and recommended grant type for web applications and mobile applications that can securely store a client secret. The client application redirects the user to the authorization server, where the user authenticates and consents to the requested permissions. The authorization server then returns an authorization code to the client application, which exchanges it for an access token using its client secret. This grant type provides better security than other grant types, as it prevents the exposure of the access token to the user agent (browser) or other intermediaries.
- **Implicit**: This is a simplified version of the authorization code grant type for client-side applications that cannot store a client secret, such as single-page applications (SPAs). The client application redirects the user to the authorization server, where the user authenticates and consents to the requested permissions. The authorization server then returns an access token directly to the client application via the user agent. This grant type is less secure than the authorization code grant type, as it exposes the access token to the user agent and other intermediaries. It also does not support refresh tokens, which means the user has to re-authenticate when the access token expires.
- **Client Credentials**: This is a simple grant type for server-to-server applications that can securely store a client secret. The client application requests an access token from the authorization server using its client credentials (client ID and client secret). The authorization server then returns an access token to the client application. This grant type is suitable for accessing APIs that do not require user consent or interaction, such as internal APIs or APIs that provide public data.
- **Password**: This is a legacy grant type for trusted applications that can securely store a client secret and collect the user's credentials (username and password). The client application requests an access token from the authorization server using its client credentials and the user's credentials. The authorization server then returns an access token and optionally a refresh token to the client application. This grant type is not recommended, as it requires the user to share their credentials with the client application and does not support federated or multi-factor authentication.
- **Refresh Token**: This is not a standalone grant type, but a mechanism to obtain a new access token when the previous one expires or becomes invalid. The client application requests a new access token from the authorization server using a refresh token that was issued along with the original access token. The authorization server then returns a new access token and optionally a new refresh token to the client application. This mechanism reduces the need for user interaction and improves user experience.
You can find more details and examples of these grant types in these articles:
: [OAuth Grant Types](https://oauth.net/2/grant-types/)
: [Application Grant Types - Auth0](https://auth0.com/docs/get-started/applications/application-grant-types)
: [What is the OAuth 2.0 Authorization Code Grant Type?](https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type)
: [What is the OAuth 2.0 Implicit Grant Type? | Okta Developer](https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type)
: [What is the OAuth 2.0 Password Grant Type? | Okta Developer](https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant)