100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

OAuth for Mobile Apps

How native iOS and Android apps should implement OAuth 2.0 per RFC 8252: external user-agents, PKCE, claimed redirect URIs, and hardware-backed token storage.

Practical OAuthIntermediate10 min readJul 10, 2026
Analogies

Native Apps as Public Clients

Like SPAs, native mobile apps cannot keep a client_secret confidential — the compiled binary can be decompiled and any embedded secret extracted — so mobile apps are also public OAuth clients. RFC 8252, OAuth 2.0 for Native Apps, mandates that the authorization request must open in an external user-agent, meaning the platform's system browser or an in-app browser tab like Android's Custom Tabs or iOS's ASWebAuthenticationSession, rather than an embedded WebView the host app fully controls.

🏏

Cricket analogy: It's like decompiling a fielding app's APK being similar to a rival team getting hold of a printed strategy sheet left in a dugout — since the secret is embedded in something physically handed out, it can't stay confidential.

PKCE and Redirect URIs on Mobile

After completing authorization in the external browser, the operating system must route the redirect back into the correct app; this is done either via a custom URI scheme like com.example.app://callback, which is easy to register but can be claimed by multiple apps on some platforms, or preferably via claimed HTTPS redirects — Android App Links or iOS Universal Links — which are cryptographically tied to a specific app through a domain-hosted association file. PKCE is mandatory in this flow, since it's what actually binds the authorization code to the specific app instance that initiated the request, closing the gap left by an unclaimed custom scheme.

🏏

Cricket analogy: A custom URI scheme is like a generic team jersey number that two different clubs could both claim, while an HTTPS App Link is like a jersey verified against the official league registry — only PKCE's proof-of-possession check confirms which specific player actually started the play.

kotlin
// AppAuth-Android: configuring an authorization request with PKCE
val serviceConfig = AuthorizationServiceConfiguration(
    Uri.parse("https://idp.example.com/authorize"),
    Uri.parse("https://idp.example.com/token")
)

val authRequest = AuthorizationRequest.Builder(
    serviceConfig,
    "mobile-client-id",
    ResponseTypeValues.CODE,
    Uri.parse("com.example.app:/oauth2redirect")
)
    .setScope("openid profile email offline_access")
    .setCodeVerifier(CodeVerifierUtil.generateRandomCodeVerifier())
    // AppAuth derives and attaches the code_challenge automatically
    .build()

val authService = AuthorizationService(context)
val authIntent = authService.getAuthorizationRequestIntent(authRequest)
startActivityForResult(authIntent, RC_AUTH)

Secure Token Storage on Device

Once tokens are obtained, they must be stored using the platform's hardware-backed secure storage: the Android Keystore system, which can wrap keys in a Trusted Execution Environment or Secure Element, or the iOS Keychain, which encrypts entries and can be gated behind biometric authentication. Storing a refresh_token in plain SharedPreferences on Android or an unencrypted plist on iOS leaves it readable by any process with root or jailbreak access, or recoverable from an unencrypted device backup.

🏏

Cricket analogy: It's like storing the team's match strategy in a locked safe at the team hotel rather than in a notebook left in a shared team bus — the Keystore/Keychain is the safe, SharedPreferences is the notebook anyone could flip through.

AppAuth (Google's open-source library for Android and iOS) implements RFC 8252's recommendations out of the box — external user-agent usage, PKCE, and safe redirect handling — so most teams should adopt it rather than reimplementing the native OAuth flow from scratch.

Handling Redirect Back to App and Token Refresh

After the user authenticates in the system browser, the OS matches the redirect URI to the registered app and routes control back to it with the authorization code, which the app then exchanges at the token endpoint along with its code_verifier. From then on, the app uses the refresh_token grant to silently obtain new access tokens in the background, avoiding repeated browser redirects and keeping the user logged in across app launches until the refresh token itself expires or is revoked.

🏏

Cricket analogy: It's like a runner completing a quick single and returning to the same end without needing to restart the over — the app returns from the browser and resumes its session using the refresh token instead of restarting the whole login.

Never use an embedded WebView for the login screen. WebViews don't share cookies or session state with the system browser, forcing users to log in repeatedly even if they're already authenticated elsewhere, and a malicious host app could inject JavaScript into the WebView to capture credentials directly — a practice RFC 8252 explicitly prohibits and that major app stores increasingly reject during review.

  • Mobile apps are public OAuth clients, just like SPAs, since compiled binaries can be decompiled to extract embedded secrets.
  • RFC 8252 mandates using the system browser or an in-app browser tab, never an embedded WebView, for the login screen.
  • PKCE is mandatory on mobile to bind the authorization code to the specific app instance that started the flow.
  • Claimed HTTPS redirects (App Links / Universal Links) are safer than custom URI schemes, which can be claimed by other apps.
  • Refresh tokens and other secrets must be stored in hardware-backed secure storage: Android Keystore or iOS Keychain.
  • AppAuth is a widely used open-source library implementing RFC 8252's native app best practices out of the box.
  • Embedded WebViews for login break session sharing and are explicitly disallowed by RFC 8252 and app store policy.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#OAuth20StudyNotes#OAuthForMobileApps#OAuth#Mobile#Apps#Native#StudyNotes#SkillVeris#ExamPrep