OAuth 2.0 is an industry-standard authorization protocol that provides third-party applications with limited access to a user’s resources without sharing their credentials. The protocol has become the de facto standard for delegated authorization in web and mobile applications, used by platforms such as Google, Facebook, Apple, and GitHub. According to IETF RFC 6749 (2025), OAuth 2.0 is used in over 85% of all API integrations requiring delegated data access.
Key Takeaways
OAuth 2.0 is an authorization protocol defined in IETF RFC 6749 that allows third-party applications to obtain limited access to a user’s resources without revealing their username and password. The protocol solves a fundamental problem with the password model: an application you trust with your password gains unrestricted access to all account data. OAuth 2.0 replaces this approach by issuing a temporary token with an explicitly limited access scope.
The architecture of OAuth 2.0 is delegated authorization. The user (Resource Owner) authorizes an application (Client) to access their data stored on a resource server (Resource Server) through an intermediary — the authorization server (Authorization Server). The authorization server issues an Access Token — a cryptographic string that the application presents to the resource server to access data. An important distinction between OAuth 2.0 and SAML or OpenID Connect: OAuth 2.0 addresses the authorization task (what is allowed), not authentication (who the user is). The OpenID Connect (OIDC) protocol is built on top of OAuth 2.0 for authentication.
The protocol is supported by all major platforms. Google uses OAuth 2.0 for accessing Google APIs (Gmail, Drive, Calendar), Facebook for Graph API, Apple for Sign in with Apple (ASAuthorizationAppleIDProvider), and GitHub for repository access. In the context of mobile development, OAuth 2.0 is the standard mechanism for integrating third-party services: social media login, cloud storage access, and content publishing on behalf of the user.
The OAuth 2.0 protocol defines four roles whose interaction forms the complete authorization cycle. Understanding each role is essential for correctly implementing the protocol in a mobile application.
| Role | Description | Example |
|---|---|---|
| Resource Owner | The data owner — the user who grants access to their resources | An app user clicking “Sign in with Google” |
| Client | The application requesting access to resources on behalf of the owner | A mobile app that needs access to Google Drive |
| Authorization Server | The server that issues tokens after authentication and authorization | accounts.google.com — Google’s authorization server |
| Resource Server | The API that provides access to protected resources using a token | www.googleapis.com — Google Drive API resource server |
The key protocol entities are the Access Token, Refresh Token, and Authorization Code. The Access Token is a short-lived token (usually 15–60 minutes) presented to the resource server with each data request. The Refresh Token is a long-lived token (days or weeks) used to obtain a new Access Token without requiring the user to log in again. The Authorization Code is a temporary code issued after user authorization and exchanged for an Access Token and Refresh Token.
OAuth 2.0 defines several Grant Types — token acquisition scenarios, each designed for a specific type of client and security context. Choosing the right Grant Type is a critical architectural decision when designing authorization in a mobile application.
The main Grant Types are: Authorization Code (the most secure for mobile and web applications with a server component), Authorization Code with PKCE (Proof Key for Code Exchange — for mobile and SPA applications without a server backend), Client Credentials (for server-to-server authentication without user involvement), and Resource Owner Password Credentials (deprecated — transmits the password directly). PKCE is a mandatory extension for public clients (mobile applications, SPAs) according to the OAuth Security BCP (RFC 9700) recommendations.
Authorization Code Flow with PKCE is the recommended OAuth 2.0 configuration for native mobile applications. PKCE (Proof Key for Code Exchange) adds an additional layer of protection, preventing authorization code interception attacks. The protocol is described in IETF RFC 7636.
The sequence of steps: (1) the client generates a random code_verifier (a 43–128 character string using only unreserved characters), (2) the client computes code_challenge = SHA-256(code_verifier), (3) the client opens a browser for user authorization on the Authorization Server, passing the code_challenge, (4) after successful authorization, the server returns the authorization code to the application via a custom URI scheme (app deep link), (5) the client sends the authorization code + code_verifier to the server, (6) the server verifies SHA-256(code_verifier) === code_challenge and issues an Access Token + Refresh Token.
The advantage of PKCE is that even if an attacker intercepts the authorization code in the URI scheme, they cannot exchange it for a token without the code_verifier, which is known only to the legitimate client. In mobile applications, you should use Chrome Custom Tabs (Android) or ASWebAuthenticationSession (iOS) to open the browser — this ensures the system browser cannot access the code_verifier from the application’s memory.
AppAuth is the reference implementation of OAuth 2.0 and OpenID Connect for native applications, recommended by the IETF. The library supports PKCE, Chrome Custom Tabs, custom URI schemes for returning the authorization code, and automatic token refresh. AppAuth for Android is available via the `net.openid:appauth:0.11.1` dependency.
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
"CLIENT_ID.apps.googleusercontent.com",
ResponseTypeValues.CODE,
Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()
val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)
// Launching Chrome Custom Tab for authorization
startActivityForResult(intent, REQUEST_CODE_AUTH)
After receiving the authorization code (onActivityResult), the application exchanges it for an Access Token and Refresh Token via a TokenRequest. Tokens are saved in SharedPreferences with encryption using EncryptedSharedPreferences (Android Security Crypto). The Refresh Token should be stored in the KeyStore — a hardware-backed key store inaccessible to other applications. Each time the Access Token expires, the application uses the Refresh Token to obtain a new one — the user does not need to re-authenticate.
// Exchanging authorization code for tokens
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
?: return
authService.performTokenRequest(
exchangeReq,
ClientAuthentication.none()
) { tokenResp, ex ->
if (tokenResp != null) {
// Access Token and Refresh Token received
val accessToken = tokenResp.accessToken
val refreshToken = tokenResp.refreshToken
// Save to EncryptedSharedPreferences
saveTokens(accessToken, refreshToken)
}
}
The code above demonstrates the complete OAuth 2.0 PKCE flow: creating a server configuration via OpenID Connect Discovery, generating an authorization request with a code_verifier, launching a Chrome Custom Tab, receiving the authorization code via a custom URI scheme, and exchanging the code for tokens via a Token Request. It is important to handle Access Token expiration: when receiving an HTTP 401 response from the Resource Server, the application should use the Refresh Token to obtain a new Access Token and retry the request.
OAuth 2.0 is a complex protocol with many attack vectors. The IETF Security BCP (RFC 9700) describes over 20 classes of OAuth 2.0 vulnerabilities. For mobile applications, the most critical are: authorization code interception via custom URI schemes, CSRF attacks on callback endpoints, Refresh Token theft from insecure storage, and client impersonation through intent interception.
Protection against these attacks includes mandatory measures: (1) PKCE with S256 code_challenge — prevents authorization code interception even if the URI scheme is intercepted; (2) use of a nonce or state parameter to prevent CSRF — the server verifies that the authorization code matches the original request; (3) storing the Refresh Token only in the KeyStore (Android) or Keychain (iOS) — never in SharedPreferences or UserDefaults; (4) using TLS with Certificate Pinning to protect against MITM at the transport layer; (5) validating redirect_uri — the authorization server must strictly validate it against the registered URI.
Additional recommendations from the IETF: mobile applications should use AppAuth or similar libraries that have undergone security audits; do not rely on WebView for OAuth (WebView does not isolate data from the main application); implement automatic Refresh Token rotation (each Refresh Token can be used only once); add Certificate Pinning via the TrustManager for Android and URLSession for iOS. OpenID Connect Discovery (well-known endpoint) helps automatically determine the correct authorization server endpoints and avoid redirects to phishing pages.
Frequently Asked Questions
OAuth 2.0 is an authorization protocol (what is allowed to do?), while OpenID Connect (OIDC) is an authentication protocol (who is the user?). OIDC is built on top of OAuth 2.0 and adds an ID Token — a JWT token containing information about the user’s identity. OAuth 2.0 provides an Access Token, while OIDC supplements it with an ID Token and a UserInfo endpoint for obtaining the user profile.
A Bearer Token is an Access Token presented in the HTTP Authorization: Bearer header. Its danger lies in the fact that anyone who possesses the token can access the resource — the token is not bound to the client. Therefore, Bearer Tokens must only be transmitted over TLS (HTTPS), have a short lifetime (15–60 minutes), and never be stored in logs or URL parameters.
Mobile applications are public clients that do not have a client_secret (a secret cannot be protected in an APK/IPA). Without PKCE, an attacker could intercept the authorization code via a custom URI scheme (e.g., malformed://callback?code=ABC) and exchange it for a token. PKCE adds a code_verifier known only to the application, making the intercepted code useless.
A typical Access Token lives for 15–60 minutes (configurable on the authorization server). With each HTTP request to the Resource Server, the response is checked: if the code is 401, the application triggers the Refresh Token Flow to obtain a new Access Token. The Refresh Token lives from 24 hours to several months, depending on the provider’s security policy. When the Refresh Token changes, the old one is invalidated.
No — the IETF Security BCP (RFC 9700) prohibits WebView for OAuth 2.0 in mobile applications. WebView does not isolate cookies and data from the main application, allowing the application to intercept the user’s credentials. Instead of WebView, use Chrome Custom Tabs (Android) or ASWebAuthenticationSession (iOS) — system browser components that are isolated from the application.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also