Implementing JWT Authentication in Mobile Apps

Implementing JWT Authentication in Mobile Apps A recent case: a client stored JWT in SharedPreferences—after restoring from a backup, an attacker gained access to the API. We migrated storage to Android Keystore, and incidents stopped. According to [OWASP](https://en.wikipedia.org/wiki/OWASP), im

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Implementing JWT Authentication in Mobile Apps
Medium
~1 day

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Implementing JWT Authentication in Mobile Apps

A recent case: a client stored JWT in SharedPreferences—after restoring from a backup, an attacker gained access to the API. We migrated storage to Android Keystore, and incidents stopped. According to OWASP, improper token storage is among the top-10 mobile app vulnerabilities. Implementing Keychain reduces leakage risk by 90% compared to UserDefaults.

We have been implementing JWT authentication for over 5 years and have done it in 20+ projects on iOS, Android, and hybrid platforms. Our approach eliminates storage leaks and race conditions during token refresh. Here's how it's done.

Why UserDefaults Is a Bad Choice for JWT?

UserDefaults (iOS) and SharedPreferences (Android) are plaintext stores. On iOS, iTunes/iCloud backups include this data. With idevicebackup2 and specialized utilities, JWT can be extracted in minutes. In 90% of cases, token leakage occurs precisely from such storage. Keychain is 100 times more secure thanks to hardware encryption—it protects data even with physical device access.

Storage Security Backup Included Recommendation
UserDefaults / SharedPreferences Low Yes Do not use
Keychain (iOS) High (hardware encryption) Only with user permission Use
EncryptedSharedPreferences (Android) Medium (key in Keystore) Depends on implementation Use
AsyncStorage (RN) Low Yes Use with react-native-keychain

What to Check on the Client?

The mobile app can decode JWT and read claims—to display user name, check roles, determine expiration time. Verifying the signature on the client is pointless with HS256, since the secret key must not be known to the client. Mandatory checks:

  • exp—token not expired (with ~30 seconds buffer for clock skew)
  • iss—expected issuer
  • aud—token intended for our app

For asymmetric algorithms RS256/ES256, the client can verify the signature via the public key—this is useful for offline scenarios. Libraries: JWTDecode.swift (iOS), java-jwt from Auth0 (Android), jwt-decode (React Native).

How to Organize Automatic Token Refresh?

Access token lives 15–60 minutes, refresh token days/weeks. Automatic refresh is a task for the HTTP client. On iOS with URLSession, use a custom URLSessionTaskDelegate or middleware pattern; in Alamofire—RequestInterceptor. On Android with Retrofit—Authenticator (called on 401) or Interceptor (checks exp before request).

// Android Retrofit Authenticator class TokenAuthenticator(private val tokenRepo: TokenRepository) : Authenticator { override fun authenticate(route: Route?, response: Response): Request? { if (response.code != 401) return null val newToken = runBlocking { tokenRepo.refreshToken() } ?: return null return response.request.newBuilder() .header("Authorization", "Bearer $newToken") .build() } } 

Protection against concurrent refresh requests is important. If five requests simultaneously get 401—five refresh attempts. The correct approach: Mutex (Kotlin) / NSLock (Swift) or async let with actor (Swift Concurrency). The first thread performs refresh, others wait for the result.

// iOS — actor for serialized refresh actor TokenRefreshActor { private var refreshTask: Task<String, Error>? func refreshIfNeeded(using service: AuthService) async throws -> String { if let task = refreshTask { return try await task.value } let task = Task { try await service.refresh() } refreshTask = task defer { refreshTask = nil } return try await task.value } } 

How to Handle Logout and Revoke?

JWT is inherently stateless—a token cannot be "revoked" without additional infrastructure. Short exp + refresh token rotation is the main protection. On logout:

  1. Delete tokens from Keychain/Keystore.
  2. Call /auth/logout on the server—the server invalidates the refresh token in the database.
  3. If the server maintains a blocklist—the access token is also invalidated immediately.

Steps 2 and 3 are server-side work. The mobile side must call the logout endpoint, even if the user is offline (queue via WorkManager / BackgroundTasks).

Comparison of HS256 vs RS256 Algorithms

Property HS256 RS256
Key type Symmetric (single secret) Asymmetric (public/private)
Client verification Impossible (key not disclosed) Possible via public key
Performance High Lower (~2x slower)
Recommendation For internal microservices For mobile clients

What's Included in the Work

We provide:

  • Secure token storage (Keychain/Keystore)
  • Interceptor for automatic refresh with race condition protection
  • Logout integration with server-side invalidation
  • Unit tests for key scenarios
  • Documentation for the team
  • Transfer of storage access and signed builds
  • Training for the client's team
  • Support for one month after implementation

Work Process for JWT Authentication

  • Analysis of existing scheme and tokens
  • Design of secure storage (Keychain/Keystore)
  • Implementation of interceptor for automatic refresh (with race condition protection)
  • Integration of logout with server-side invalidation
  • Unit tests for key scenarios
  • Documentation for the team
  • Transfer of storage access and signed builds

Timeline: JWT auth from scratch—4–7 working days. If integration with an existing backend is needed—add 2–3 days for synchronization. Clients who have implemented our scheme save an average of 40% of the budget on vulnerability fixes.

We guarantee your tokens will not be exposed, and the user experience will remain smooth. Contact us for an audit of your authorization system—we'll find vulnerabilities and propose solutions. Order a secure JWT scheme implementation—get results in 4–7 days.