API Authentication Best Practices

Authentication is a critical aspect of building secure APIs, ensuring the protection of sensitive user data. By following industry-standard authentication protocols, one can establish robust and scalable security measures while leveraging established services, components, and libraries. This article delves into best practices for API authentication and provides recommendations for suitable authentication methods based on different client types.

Photo by Ed Hardie on Unsplash

NOTE: To ensure security, it is essential that all authentication options described in this article take place over an HTTPS (TLS) connection.

Authentication Options for Server-Side Clients

When constructing an API for server-side clients, the following are the primary authentication options:

HTTP Basic Authentication

This straightforward method involves clients sending their username and password with each request. However, it has limitations in terms of security and key rotation. The credentials are transmitted with every request, increasing the risk of interception. Additionally, managing key rotation becomes complex as the server lacks the ability to invalidate credentials without requiring client updates.

NOTE: The end user needs to validate that they are accessing the correct URL each time to prevent sending their password to an untrusted server, which results in phishing attacks. Users often fail to do this, which is why phishing has become the most common form of security breach.

Digest Authentication

This authentication method offers improved security compared to HTTP Basic Authentication. It involves the client sending a request with a hashed value of the username, password, and other data. The server responds with a randomly generated challenge, which the client hashes with the user’s credentials. While Digest Authentication provides enhanced security, it requires customizations and increased engineering effort to implement and maintain. Moreover, it shifts the security burden to the server owner instead of relying on standardized protocols.

NOTE: Digest Authentication should not be used. This is because you must store your passwords in plaintext or an encrypted or MD5 format, all of which are insecure. Also, MD5 is not allowed by FIPS (Federal Information Processing Standard Publication 140–2).

OAuth Client Credentials

Specifically designed for server-side clients, the OAuth Client Credentials flow allows clients to exchange their client ID and secret for a token. The client includes the client ID and secret in the authorization header of the request to the token endpoint. Upon successful authentication, the server issues an access token, enabling the client to access protected resources. OAuth Client Credentials offers a more robust and secure authentication mechanism than HTTP Basic Authentication. It also facilitates key rotation, as the server can revoke and issue new client credentials without disrupting client access to the API.

Authentication Options for Web Apps with Server-Side Backends

When developing an API for web apps with server-side backends, the OIDC Authorization Code Flow is the recommended approach because, for one, it is easier to setup than SAML which uses XML tokens vs OIDC’s JSON tokens. Here is the OIDC authentication flow.

  1. The web app redirects the user to an authentication server such as Okta or Auth0.
  2. The user authenticates on the authentication server and grants permissions to the web app.
  3. The authentication server issues an authorization code to the web app.
  4. The web app exchanges the authorization code for an access token and a refresh token.
  5. The web app can then employ the access token to authenticate and authorize subsequent API requests.

NOTE: OIDC (published in 2014) is more modern than SAML (published in 2005) and some suggest that it will eventually replace it, although SAML is still widely used in legacy enterprise and government applications due to its age.

Authentication Options for Mobile Clients and SPAs

For APIs servicing mobile clients and single-page applications (SPAs), prioritizing security and user experience is paramount. In this context, it is recommended to use the OIDC (OpenID Connect) Authorization Code Flow with PKCE (Proof Key for Code Exchange). This authentication flow provides a robust mechanism for authentication and authorization.

  1. The mobile app generates a random code verifier string value.
  2. The mobile app transforms the code verifier into a code challenge (hashed representation of the code verifier) using SHA-256, for example.
  3. The mobile app sends the code challenge with an authorization request to an authentication server, such as as Okta or Auth0.
  4. The user enters their credentials on the authentication server and grants permissions to the mobile app.
  5. The authentication server issues an authorization code to the mobile app.
  6. The mobile app sends the authorization code and the generated code verifier (generated in step 1 above) to the authentication server which verifies it and then returns an access token and a refresh token.
  7. The mobile app can subsequently utilize the access token to make authenticated requests to the API.

By employing the OIDC Authorization Code flow with PKCE, secure communication between the client and the server is ensured, safeguarding sensitive user information. PKCE adds an extra layer of security by preventing interception of the authorization code during the exchange, and this is because it is tied to its code verifier. It is crucial to secure the code verifier.

NOTE: Another option for SPAs with no server-side backend, although not recommended for new deployments [5], is to use the OIDC Implicit Flow protocol. When used with the OIDC Form Post response mode, the Implicit Flow offers a streamlined workflow, particularly if the application requires only an ID token for user authentication.

When to use PKCE

PKCE (Proof Key for Code Exchange) is primarily recommended for public clients that cannot store a client secret, such as mobile apps and single-page applications (SPAs). In these scenarios, the client secret cannot (and should not) be securely stored within the client-side code. This is because the client environment may be uncontrolled or have risky third-party integrations or dependencies.

For web apps with server-side backends, the backend typically has the capability to securely store and protect a client secret. This backend component can handle the authentication process securely, eliminating the need for PKCE in most of these situations.

NOTE: The PKCE code verifier is not typically persisted or stored beyond the duration of the authentication process. It is best to store it encrypted in your framework’s session mechanism. One recommended approach is to store it in an encrypted session cookie with client-side scripting access disabled. This can be achieved by utilizing the HttpOnly flag, which is an option in the Set-Cookie HTTP response header.

References

[1] D. Hardt, A. Parecki, and T. Lodderstedt. OAuth Working Group. The OAuth 2.1 Authorization Framework. Published 13 March 2023. https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-08.html

[2] OAuth. RFC 8252: OAuth 2.0 for Mobile and Native Apps. https://oauth.net/2/native-apps/

[3] OAuth. RFC 7636: Proof Key for Code Exchange. https://oauth.net/2/pkce/

[4] Kirby, Richard. Trelica. What sort of Single Sign-On should I use: OpenID Connect or SAML2?. https://trelica.com/blog/what-sort-of-single-sign-on-should-i-use-openid-connect-or-saml2/

[5] Auth0 docs by Okta. Implicit Flow with OIDC. https://auth0.com/docs/authenticate/login/oidc-conformant-authentication/oidc-adoption-implicit-flow

Scroll to Top