A mobile app runs on a device the attacker controls, so any authentication or authorisation decision made only inside the app can be skipped, patched out or replayed straight against the back end. OWASP ranks this as M3 in the Mobile Top 10 2024, published as "Insecure Authentication/Authorization", and rates it easy to exploit and common. This guide goes beyond the OWASP Mobile Top 10 Guide: it sets out what M3 covers, the MASVS-AUTH controls, a server-side design for sign-in, sessions, biometrics and object-level authorisation, and how to test and measure it. It is for mobile and API engineers, identity architects and penetration testers.
Key takeaways
- The server is the only place a decision counts. OWASP's core advice for M3 is to assume client-side controls can be bypassed and enforce authentication and authorisation on the back end for every request.
- Most M3 findings are API findings. Requests accepted without an access token, IDOR, hidden admin endpoints and roles sent by the app are all fixed in the API, not the app.
- Biometrics should unlock a key, not answer yes or no. Bind Face ID, Touch ID or BiometricPrompt to a hardware-backed key that releases or signs a token, so patching the app's callback achieves nothing.
- Use OAuth 2.0 for native apps as written. RFC 8252 requires an external user-agent, PKCE and no reliance on client secrets, because a native app is a public client.
- Prefer revocable, device-specific tokens. OWASP recommends tokens users can revoke within the app, never storing the password for "Remember Me", and opt-in persistent login.
What it is and who it applies to
Authentication confirms who the user is; authorisation confirms what that user may do, and OWASP stresses that authorisation checks should follow authentication. M3 covers failures in either when the client is a mobile app. OWASP notes that mobile differs from web in three ways that create risk: decisions are sometimes made on the device, small screens push teams towards short passwords and 4-digit PINs, and offline use leads to local-only checks.
| OWASP factor | Rating | What it means in practice |
|---|---|---|
| Exploitability | Easy | Attackers call the back end directly or log in as a low-privilege user and reach admin endpoints, often with automated tools, malware or botnets. |
| Prevalence | Common | Mobile APIs are often designed assuming only the app will call them. |
| Detectability | Average | Testers find it by removing tokens, replaying requests with low-privilege sessions and attacking offline checks. |
| Impact | Severe | Over-privileged functions can destroy systems or expose data; unidentified users cannot be audited; fraud and reputational damage follow. |
Who it applies to: every app with a back end, and especially banking, health, retail and B2B apps that expose account data or transactions. Apps with no remote endpoint still fall under MASVS-AUTH-2 for local authentication. The back-end team owns most of the fix, so M3 should be assessed jointly with the API, using the Top 10 API Security Risks.
Structure and key requirements
OWASP lists the indicators of M3. For authorisation: IDOR vulnerabilities, hidden endpoints with no checks because developers assume only certain roles will reach them, and the app sending the user's role or permissions to the back end. For authentication: the app can call back-end APIs without an access token, passwords or shared secrets are stored on the device, weak password policies or simplified entry are used, and Face ID or Touch ID is used as a stand-alone check. MASVS groups the requirements into three controls.
| MASVS control | Control statement | What good looks like |
|---|---|---|
| MASVS-AUTH-1 | The app uses secure authentication and authorization protocols and follows the relevant best practices. | OAuth 2.0 authorisation code flow with PKCE in the system browser, short-lived access tokens, rotating or sender-constrained refresh tokens, server-side checks on every call. |
| MASVS-AUTH-2 | The app performs local authentication securely according to the platform best practices. | Biometric or device credential prompt bound to a Keystore or Keychain key; no local password store; key invalidated on biometric enrolment change. |
| MASVS-AUTH-3 | The app secures sensitive operations with additional authentication. | Step-up for payments, payee changes, email or MFA changes, enforced by the server through a fresh authentication event or signed confirmation. |
The five OWASP scenarios and their fixes
| OWASP scenario | Root cause | Server-side fix |
|---|---|---|
| Hidden service requests | Back end does not confirm the request comes from a known user | Require a valid access token on every endpoint by default; deny unauthenticated routes unless explicitly allowlisted |
| Interface reliance | Admin functions hidden in the UI, not checked on the server | Function-level authorisation on each endpoint (ASVS 5.0 V8.2.1); separate admin APIs from consumer APIs |
| Usability requirements | 4-digit passwords hashed correctly but trivially recovered if hashes leak | No short PIN as the account password; a PIN may only unlock a device-bound key, with server-side rate limiting |
| Insecure direct object reference | API checks a bearer token exists but not that the ID in the URL belongs to it | Object-level check that the subject in the token owns or may access the object (ASVS 5.0 V8.3.1); non-sequential identifiers as defence in depth |
| Transmitted LDAP roles | Back end trusts group membership sent in a header | Derive roles on the server from the identity provider or directory, never from client input |
The IDOR pattern is not limited to mobile. In the McHire Default Password Flaw 2025, an internal API returned applicant records by sequential ID without checking that the caller was entitled to them, putting an estimated 64 million records in reach. See the OWASP API Top 10 API1 Broken Object Level Authorization Guide.
Identity and NHI requirements
M3 sits where human and non-human identity meet. The user authenticates, but what the API actually sees is a token held by an app instance, and attackers increasingly drive the API with scripts rather than the app.
- The app is a public client: RFC 8252 (BCP 212) states that secrets embedded in distributed native apps should not be treated as confidential. Do not rely on a client secret or static API key in the app to prove the caller is your app. See the OWASP Mobile Top 10 M1 Improper Credential Usage Guide.
- App instance identity through attestation: to raise confidence that a request comes from a genuine build, use Google's Play Integrity API (appRecognitionVerdict PLAY_RECOGNIZED, deviceIntegrity labels such as MEETS_DEVICE_INTEGRITY and MEETS_STRONG_INTEGRITY) or Apple App Attest. Google states the API works best alongside other signals and not as the sole anti-abuse mechanism, and advises against caching verdicts because a verdict from a good device could be replayed elsewhere.
- Tokens as credentials: access and refresh tokens on the device are bearer credentials. ASVS 5.0 V10.3.5 calls for sender-constrained tokens using mutual TLS or DPoP at higher assurance, which stops a token copied from the device being replayed from another machine. See the DPoP Guide and the Token and Session Security Guide.
- Back-end service identities: the mobile API often calls internal services with its own credentials. ASVS 5.0 V8.3.3 requires access to an object to be based on the originating subject's permissions, not the intermediary service's, so the user's identity must flow through to the data layer rather than being replaced by a powerful service account.
- Device-specific, revocable sessions: OWASP recommends device-specific tokens that users can revoke within the app. ASVS 5.0 V6.5.6 similarly requires that any authentication factor, including physical devices, can be revoked on theft or loss.
Implementation steps
- Map every endpoint the app calls: proxy the app on a test device, list each request, and record whether it needs authentication, which role may call it and which object IDs it takes. Compare with the API gateway's route list to find endpoints the app never uses but which remain exposed.
- Make authentication the default: configure the gateway or framework to reject any request without a valid token, then allowlist only genuinely public routes such as sign-in and app configuration. Run this in log-only mode for a release cycle to find legitimate unauthenticated calls, then enforce. Roll back by reverting the gateway policy, not the app.
- Move sign-in to the standard flow: use the authorisation code flow with PKCE in an external user-agent (Android Custom Tabs, iOS ASWebAuthenticationSession), with claimed https redirect URIs where the platform supports them, as RFC 8252 prefers. Remove embedded web views for login and any resource owner password flow. Consider passkeys for the primary factor; on Android, Google recommends Credential Manager for sign-in. See the Passwordless and Passkeys Guide.
- Add object and function checks: centralise authorisation in middleware or a policy engine so every handler checks that the token's subject may perform this action on this object. Write negative tests: user A requests user B's object, a standard user calls an admin function, a request carries a client-supplied role.
- Bind local authentication to keys: on Android, create a key in AndroidKeyStore with setUserAuthenticationRequired(true) and setInvalidatedByBiometricEnrollment(true), and pass a CryptoObject to BiometricPrompt with BIOMETRIC_STRONG for per-operation unlock. On iOS, protect the Keychain item with an access control such as biometryCurrentSet and an accessibility class like kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. The unlocked key then decrypts a refresh token or signs a server challenge.
- Design sessions for loss and theft: short-lived access tokens, refresh tokens with absolute expiry (ASVS 5.0 V10.4.8) and rotation, a server-side device list users can revoke, and opt-in persistent login. Never store the password for "Remember Me".
- Add step-up for sensitive actions: require fresh authentication before changing email, phone, MFA settings or payees (ASVS 5.0 V7.5.1) and for high-value transactions, enforced by checking authentication time or a signed confirmation on the server.
- Handle offline needs explicitly: if the app must authorise anything offline, encrypt local data with a key derived from or protected by the user's credentials, add integrity checks to detect tampering (MASVS-RESILIENCE-2), and re-validate on the server when the device reconnects.
- Introduce attestation gradually: collect Play Integrity and App Attest results without enforcement first, as Google advises, then apply graded responses (allow, allow with limits, challenge, deny) on high-value endpoints.
Decision guidance
| Choice | Option A | Option B | Guidance |
|---|---|---|---|
| Primary sign-in | Passkeys through the platform credential manager | Password plus MFA through the identity provider | A where your user base and identity provider support it; keep B as fallback and require at least as many factors as the web app, as OWASP advises |
| Biometric mode | Per-operation key (CryptoObject, validity 0) | Time-bound key validity window | A for payments and record changes; B for low-risk browsing where repeated prompts hurt usability |
| Token protection | Bearer tokens in Keystore or Keychain | Sender-constrained tokens (DPoP or mTLS) | B for financial and health apps or where token theft is in the threat model; A with short lifetimes elsewhere |
| Authorisation location | In each service handler | Central policy engine or gateway plus handler checks | Small teams with one API can start with A and shared middleware; large estates need B for consistency and audit |
NIST SP 800-63B (Revision 4) supports this design: biometrics shall only be used as part of multi-factor authentication with a physical authenticator, and single-factor passwords need at least 15 characters (8 when used within MFA). A 4-digit PIN is acceptable only as a local activation secret for a device-bound key, not as the account password.
Evidence and assessment
Test the API as an attacker would, without the app's cooperation, following the OWASP approach of removing tokens and replaying requests with low-privilege sessions.
- Anonymous access test: strip the Authorization header from every captured request; any success on a non-public endpoint is an M3 finding.
- Horizontal and vertical tests: with two standard accounts and one admin, swap object IDs and replay admin calls with a standard token.
- Client-supplied privilege test: modify any role, group, tier or user ID field in requests and headers.
- Local authentication review: on a rooted or jailbroken test device, confirm that bypassing the biometric callback does not release data, because the key stays locked. Confirm no password or long-lived secret sits in shared preferences, plist files or the Keychain without access control.
- Session review: confirm tokens expire, refresh tokens rotate and are revoked on logout and on device removal, and that a revoked device cannot obtain new tokens.
- Logging: confirm the API logs authenticated subject, device or client identifier, decision and object for each sensitive request, since OWASP notes unidentified users cannot be audited.
Metrics
- Authenticated-by-default coverage: percentage of API routes behind the default-deny policy (target 100% minus a documented allowlist).
- Authorisation test coverage: percentage of endpoints with automated negative tests for object and function access.
- Authorisation denials by reason: rate of 401 and 403 responses per endpoint; spikes on object endpoints suggest enumeration.
- Token lifetime: median access token lifetime and maximum refresh token age in production.
- Attestation failure rate: share of sensitive requests with failed or missing app attestation, tracked before and after enforcement.
- Revocation time: time from a user removing a device to its refresh token failing.
Mapping to other frameworks
| Framework | Reference | Relevance to M3 |
|---|---|---|
| OWASP MASVS | MASVS-AUTH-1, AUTH-2, AUTH-3; RESILIENCE-2 for offline checks | Protocols, local authentication, step-up, tamper detection |
| OWASP API Security Top 10 2023 | API1 Broken Object Level Authorization, API2 Broken Authentication, API5 Broken Function Level Authorization | The back-end side of most M3 findings |
| OWASP ASVS 5.0 | V6.5.6, V7.5.1, V8.2.1, V8.3.1, V8.3.3, V10.3.5, V10.4.6, V10.4.8 | Factor revocation, re-authentication, function and object authorisation at a trusted layer, sender-constrained tokens, PKCE, refresh token expiry |
| IETF | RFC 8252 (BCP 212), RFC 7636 (PKCE) | OAuth 2.0 for native apps |
| NIST SP 800-53 Rev 5 | IA-2, IA-5, IA-8, IA-11, AC-3, AC-6, AC-12 | User authentication, authenticator management, re-authentication, access enforcement, least privilege, session termination |
| NIST CSF 2.0 | PR.AA-01, PR.AA-03, PR.AA-05 | Identity management, authentication, access permissions |
| ISO/IEC 27001:2022 Annex A | A.5.15, A.5.17, A.8.3, A.8.5 | Access control, authentication information, information access restriction, secure authentication |
| MITRE ATT&CK v20 (Mobile) | T1635 Steal Application Access Token, T1634 Credentials from Password Store | Theft of tokens and stored credentials from the device |
Common pitfalls
- Hiding the button instead of checking the call: admin features removed from the consumer UI but still served by the same API with no role check, OWASP's "interface reliance" scenario. See the OWASP API Top 10 API5 Broken Function Level Authorization Guide.
- Token present, owner unchecked: the API validates the JWT signature and stops, so any user can read any object by changing an ID. See the JWT Security Guide.
- Boolean biometrics: the app calls the biometric API and proceeds on success with no key involved, so a hooking tool on a rooted device flips the result.
- Login in an embedded web view: the app can read the user's credentials and the identity provider's session, which RFC 8252 forbids for authorisation requests.
- Long-lived tokens with no device revocation: a lost phone keeps a valid session for months because refresh tokens never expire and cannot be revoked per device.
- Trusting device identifiers or location: OWASP warns these values are spoofable and must not be used to authenticate.
Practitioner checklist
- Enforce default-deny authentication at the gateway with a documented allowlist of public routes.
- Check object ownership and function permissions on the server for every request, using roles derived on the server.
- Use the authorisation code flow with PKCE in the system browser, with no client secret or embedded web view.
- Bind biometric and PIN unlock to Keystore or Keychain keys with per-operation authentication for sensitive actions.
- Never store the user's password on the device; make persistent login opt-in.
- Issue short-lived access tokens, rotating refresh tokens with absolute expiry, and a user-visible device revocation list.
- Require step-up authentication on the server for account changes and high-value transactions.
- Adopt sender-constrained tokens where token theft is in your threat model.
- Add app attestation as a risk signal after a monitoring period, never as the only control.
- Automate negative authorisation tests in CI and repeat manual testing on every major release.
Standards and references
- OWASP: Mobile Top 10 2024 M3 Insecure Authentication/Authorization
- OWASP: Mobile Application Security Verification Standard (MASVS)
- OWASP: Application Security Verification Standard (ASVS) 5.0
- IETF: RFC 8252 OAuth 2.0 for Native Apps
- NIST: SP 800-63B Digital Identity Guidelines, Authentication and Authenticator Management
- Android Developers: Show a biometric authentication dialog
- Android Developers: Play Integrity API overview
Related NHI Mgmt Group resources: OWASP Mobile Top 10 Guide · OAuth 2.0 and OpenID Connect Guide · Mobile App Security Testing Guide · OWASP API Top 10 API2 Broken Authentication Guide · OWASP Mobile Top 10 M2 Inadequate Supply Chain Security Guide