Learn React Native - Authentication & Authorization
Episode 15 of 23

Learn React Native - Authentication & Authorization

This episode covers authentication: JWT and OAuth 2.1, the refresh token flow with an interceptor, biometric authentication with Face ID and fingerprints, SSO, and the principle of never trusting client input.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Every app that stores personal data must make sure the owner is indeed the legitimate user. Authentication is the gate — and on mobile, this gate has special challenges: tokens must be safe on the device, and the session must keep working when the app is opened again.

Episode 15 covers authentication and authorization: JWT and OAuth 2.1, the refresh token flow with an Axios interceptor, biometric authentication using Face ID and fingerprints, SSO, and the security principle that client input must not be trusted.

JWT and OAuth 2.1

Access and Refresh Tokens

JWT is a common token format for identifying users: the payload contains claims, signed by the server. The modern flow uses two tokens: a short-lived access token for every request, and a long-lived refresh token to obtain a new access token.

OAuth 2.1

OAuth 2.1 combines the best practices of OAuth 2.0 — Authorization Code with PKCE for mobile apps, without a client secret on the client side. PKCE ensures that the code exchange can't be intercepted. For mobile apps that aren't server-side applications, the PKCE pattern is the correct standard.

Refresh Token Flow

Axios Interceptor

Access tokens expire quickly. When a request is rejected with status 401, the app must refresh the access token with the refresh token, then retry the request. All of this happens automatically in the interceptor:

JSRefresh token interceptor
let refreshPromise = null;
 
api.interceptors.response.use(
  (res) => res,
  async (error) => {
    const status = error.response?.status;
    if (status !== 401) return Promise.reject(error);
 
    if (!refreshPromise) {
      refreshPromise = refreshToken().finally(() => {
        refreshPromise = null;
      });
    }
    await refreshPromise;
    error.config.headers.Authorization = `Bearer ${bacaToken()}`;
    return api(error.config);
  }
);

The refreshPromise pattern ensures that many requests failing at once trigger only a single refresh process. When the refresh finishes, all requests are retried with the new token.

Logout When Refresh Fails

If the refresh token is also rejected, the session ends. Don't replay the request forever — clear the credentials, redirect to the login screen, and tell the user the session has expired. Episode 13 explains how to remove tokens from secure storage.

Biometric Authentication

Face ID and Fingerprints

A comfortable login experience uses biometrics: the user just scans their face or fingerprint. react-native-keychain supports storing credentials that can only be accessed via biometrics:

JSBiometric login
import * as Keychain from "react-native-keychain";
 
async function loginBiometrik() {
  const kredensial = await Keychain.getGenericPassword({
    accessControl:
      Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE,
    accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
  });
  return kredensial;
}

accessControl establishes that Keychain only releases the credentials after successful biometric verification. The token can never be read without a valid fingerprint or Face ID.

Biometric UX

Check biometric support before offering it: does the device have Face ID or a fingerprint sensor, and has the user enrolled biometrics in the system? If not, fall back to a regular password. Every failed scan should provide an alternative path.

SSO and Social Login

SSO Through Platforms

SSO (Single Sign-On) lets users sign in with an existing account — Apple, Google, or a corporate service. Apple Sign In and Google Sign In provide a smooth flow on mobile, including profile retrieval and valid tokens.

Implementation Options

For Expo projects, expo-auth-session and expo-apple-authentication handle the OAuth and platform SSO flows. For the React Native CLI, libraries like react-native-apple-authentication and react-native-google-signin are available. Choose one primary login path and keep it consistent.

Don't Trust the Client

Authorization Always on the Server

All security validation must happen on the server. The client can be modified — via reverse engineering or request tools — so re-check on the server: does the user have the right to access this resource, and is the sent data valid.

Rate Limiting and Input Validation

Login endpoints and public APIs must have rate limiting to slow down brute force. Validate input on the server, not just in the UI. Treat every request coming from the app as untrusted, even with a valid token.

Warning

A token on the client only proves the client knows the token, not that the client is the real user. Always evaluate authorization on the server for every resource, and treat all input as a threat until proven valid.

Closing

Episode 15 closed the authentication gate: JWT and OAuth 2.1 with PKCE, the refresh token flow via an interceptor, biometric authentication in Keychain, SSO, and the principle that the server must not trust the client.

Key takeaways:

  • JWT is used for requests; the refresh token renews the access token.
  • OAuth 2.1 with PKCE is the standard for mobile apps.
  • A single refreshPromise prevents the refresh token from racing repeatedly.
  • Biometrics wrap credentials in Keychain with access control.
  • The server must check authorization on every request.
  • Rate limiting and server validation protect against modified clients.

In the next episode, episode 16, we'll discuss privacy and data handling: data minimization per GDPR and CCPA, minimal permissions, the consent flow, secure logging, plus data retention and audit policies.

Learn React Native - Authentication & Authorization | Learn React Native