How To Secure API Access in Mobile Apps

Curity
8 min readAug 14, 2024

--

The article was written by Curity’s Gary Archer and originally published on The New Stack

By using the OAuth 2.0 authorization framework, you can avoid expensive mistakes and enable the most up-to-date security behaviors in your apps.

When an organization provides mobile apps as part of its digital services, security requirements are not always understood. Here are some common issues and resolutions to consider when integrating mobile apps with secured APIs. With this knowledge, you can avoid expensive mistakes and enable the most up-to-date security behaviors in your apps.

Avoid Authentication-First Security

Mobile apps must call APIs to interact with secured data. Those APIs need to receive a credential in an API request before they will grant access. The credential must identify the user who is interacting with the app, so that user must be authenticated.

There are many authentication solutions out there, and developers are often encouraged to integrate particular authentication methods into their apps. For example, social login providers may enable a fast authentication solution with a modern login user experience.

Yet the developer is likely to experience problems when calling APIs. After login, the social login provider may issue an API message credential called an access token to the app. Yet if the app sends this token to its APIs, it will be rejected. I call this the “foreign access token” problem.

Some developers might work around this by issuing separate tokens from API endpoints. Yet this approach has a number of security concerns given that the token may have the wrong security characteristics, like allowing too much API access or having too long a lifetime. More importantly, your organization’s security and compliance stakeholders should have visibility into the mobile app and its API security, and must be able to govern these factors over time.

Use API-First Security

A better option is to use an API-first approach, where you design APIs before coding either the frontend or backend. This should include the design of the API message credential that will be sent from the mobile app. This type of approach is central to the OAuth 2.0 authorization framework. To use OAuth, you must introduce a new component, the authorization server, which issues access tokens that clients, such as mobile apps, can send to APIs.

Your mobile app then runs a code flow using the OAuth 2.0 and OpenID Connect standards. Mobile-specific best practices are explained in the RFC 8252 — OAuth for Native Apps specification. An updated flow is illustrated below, with the same login user experience as the authentication-first approach. When the social login provider issues tokens, the authorization server validates them and then issues its own tokens. The key difference is that APIs now trust those tokens since they are issued by the authorization server.

Using OAuth has major benefits:

  • You can design access tokens with API security boundaries using scopes.
  • You can design access tokens with the least API privilege using claims.
  • You can design access tokens to have short lifetimes in case one is stolen.
  • The authorization server provides visibility of security behaviors to stakeholders.
  • Your app can be updated to use any method of authentication without code changes.
  • Both mobile apps and APIs outsource the difficult security functionality to the authorization server.

Protect Against App Impersonation

When following the directions in RFC 8252, you open an instance of the mobile system browser to authenticate the user. The simplest way to implement a mobile code flow is to receive the authorization response using a Private-Use Scheme Redirect URI such as com.example.app:/callback. Yet mobile operating systems allow multiple apps to associate themselves with the same scheme. This opens up a threat: A malicious app could impersonate your app and steal tokens by using your app’s OAuth client_id and redirect_uri parameters in its own code flow.

The best OAuth standards-based solution is to use a Claimed HTTPS Scheme Redirect URI. An example would be https://app.example.com//callback. These HTTPS URLs use the mobile platform’s support for HTTPS deep links. To return the authorization response to the app, an App Link is invoked on Android, or a Universal Link on iOS. For this to work, you must host a deep linking assets file on the HTTPS internet domain, which associates your app’s code-signing certificate with the domain. At installation time, the mobile platform validates this association and only allows the app to use the deep linking URL when validation succeeds. This prevents a malicious app from using the redirect URI to receive tokens.

Yet there are annoyances in this approach. The authorization response is returned in a redirect response, and the mobile browser may not allow a deep link to be invoked automatically after a redirect, resulting in the mobile browser presenting a Not Found page. One technique to overcome this problem is to change the redirect URI to an intermediate web page that you host online in a separate web domain. This web page can render a continue button and, when the user clicks it, the web page can execute JavaScript to forward the authorization response to the app using a deep link.

Yet mobile apps have a better way to protect against impersonation: using the attestation features built into most modern mobile devices. Attestation enables the genuine app to create a cryptographic signature that a malicious party could not produce, which can then be verified by a server component. You might be able to introduce attestation logic into your OAuth flows. Currently, you may need to account for a small minority of devices that do not support attestation, though these should disappear over time.

Protect Against Token Theft

You should also take steps to prevent an unauthorized party from using your mobile app’s access tokens. In most internet mobile use cases, these are bearer tokens, so if an attacker intercepts an access token somehow, the attacker can send it to your APIs. You limit the impact of this type of exploit by designing least-privilege and short-lived access tokens.

A mobile client is most commonly a public client that acquires tokens from the authorization server without a client credential. When running a code flow, you should use Proof Key for Code Exchange (PKCE) to create a runtime secret called a code verifier that protects the initial issuance of tokens. You might then receive an access token with a lifetime of 15 minutes as well as a refresh token whose lifetime represents the time of the user’s authenticated session.

The refresh token is used to get new access tokens to ensure that there is no impact on usability when access tokens expire. Yet if a refresh token is somehow intercepted, an attacker could easily send it to your authorization server to get an access token to use against your APIs. A partial protection is the use of single-use refresh tokens that invalidate any other refresh tokens for the same user session.

Ideally, you should also be able to protect the refresh token more robustly. One possible way to implement a hardened refresh token flow might be to base a solution on attestation. In this example, the mobile app interacts with an attestation API such as Google Play Integrity API or Apple App Attest. The app sends an attestation request to prove its identity and receives an attestation proof that a malicious party could not provide. This proof is then sent to the authorization server’s token endpoint. The authorization server then runs custom logic to validate the proof before accepting the refresh token:

More advanced token protection is possible in some use cases. For example, if you control devices, you might be able to use a device management solution to provision each device with a distinct client certificate. This would enable instances of the mobile app to act as confidential OAuth clients, where the client certificate is used in all requests to get tokens. This enables you to upgrade from bearer tokens to certificate-bound access tokens.

Plan for Native Authentication

When an OAuth-secured app runs a code flow, it can use your authorization server’s built-in options, which might include strong security options like passkeys and digital wallets. Some authorization servers also provide a plug-in system. This enables you to implement any custom authentication method whose logic you can design. If required, you can chain these together in a multifactor authentication workflow.

OAuth secured mobile apps implement logins using the system browser by default. Yet in many mobile use cases, this may not be what you want. There are many ways in which native features of the device, which may be unavailable from the browser, can authenticate users.

Consider this example native flow, as illustrated below: An organization provides a kiosk app that shops use to send data to APIs about member transactions. A user presents a QR code to communicate data from a membership app running on their personal device to the kiosk app. The data includes a proof that is sent to the organization’s authorization server, where it is verified. An access token is then issued to the kiosk app for its subsequent API communications.

For this to work, the code flow executed by the mobile app would need to work differently than it normally would. By default, the mobile browser runs a workflow of authentication HTTP requests, and the browser renders HTML-based authentication screens. Native mobile OAuth could instead use a workflow of authentication API requests, and the mobile app would use response data to render native screens.

I expect newer mobile security behaviors to become integrated into improved OAuth standards for mobile apps in the coming years. You should then be able to rely on native security improvements like attestation and use the latest native authentication methods. Until standards are improved, authorization server providers are likely to implement custom solutions, like the Hypermedia Authentication API (HAAPI) provided by Curity.

Conclusion

When designing security for mobile apps that call APIs, start with the API message credential that the app will send to APIs. Then, ensure that mobile logins enable the app to use such a credential. Also, consider cyberthreats and how you will mitigate them. Aim to get the end-to-end security design right as early as possible to prevent expensive mistakes.

By using the OAuth 2.0 authorization framework and an authorization server with the right features, you can implement your mobile-to-API security, yielding many benefits:

  • Security complexity is outsourced from your apps and APIs.
  • Access tokens can be designed in a way that minimizes data exploits.
  • Your mobile apps can integrate the most up-to-date authentication methods.
  • Your teams can follow an ecosystem of best practices.
  • Your authorization server enables you to keep your security up to date.

--

--

Curity

Curity is the leading supplier of API-driven identity management, providing unified security for digital services. Visit curity.io or contact info@curity.io