AWS Cognito Authentication Integration in Mobile Applications
AWS Cognito is two different services under one roof: User Pools (user management, authentication) and Identity Pools (federated identities, temporary AWS credentials). Confusion between them is source of most architectural errors in projects.
User Pool needed when you want to store users and issue JWT tokens. Identity Pool needed when mobile app needs temporary IAM credentials for direct access to S3, DynamoDB, or other AWS services. Often both needed — User Pool for authentication, Identity Pool for authorization on AWS resources.
Amplify SDK vs aws-mobile-client
Before 2020, standard was AWSMobileClient. Now it's legacy — official AWS recommendation is Amplify Libraries for iOS and Android. Amplify is high-level wrapper taking care of:
- Configuration via
amplifyconfiguration.json - Token storage (Keychain on iOS, EncryptedSharedPreferences on Android)
- Automatic access token refresh
- Hosted UI (OAuth 2.0 + PKCE flow via system browser)
But Amplify has problem — pulls many dependencies. If only auth needed without other Amplify categories — app size may grow 5–10 MB. In such cases use AWSCognitoIdentityProvider directly (low-level SDK).
Hosted UI vs SRP
Cognito supports two flows:
Hosted UI — browser-based OAuth 2.0 + PKCE via ASWebAuthenticationSession (iOS) / Custom Tabs (Android). Cognito itself renders login pages. Convenient for quick start and social providers (Google, Facebook via Cognito federation). Downside: customization limited to CSS, no native UX.
SRP (Secure Remote Password) — authentication without sending password in plaintext. User enters password in native UI, SDK executes SRP math protocol with Cognito. Password never transmitted — only computed proof values. Right choice for native login forms.
Amplify uses SRP by default on Amplify.Auth.signIn(username:password:). Important: SRP doesn't work without enabled USER_SRP_AUTH in App Client Cognito User Pool settings.
MFA: TOTP vs SMS
Cognito supports both:
- SMS MFA — code sent via SNS. Easy to configure, but needs IAM role for SNS and extra SMS costs.
-
TOTP (Time-based OTP) — Google Authenticator / Authy. No SMS costs, more reliable against SIM swap. Configuration via
Amplify.Auth.setUpTOTP().
On TOTP setup: app gets secret key and QR-code URI (otpauth://totp/...). Display QR via CIQRCodeGenerator (iOS Core Image) or zxing (Android). User scans in authenticator app, enters first 6-digit code for verification.
// iOS — TOTP setup
Amplify.Auth.setUpTOTP() { result in
switch result {
case .success(let totpDetails):
let qrCodeURL = totpDetails.getSetupURI(appName: "MyApp", accountName: username)
// generate QR from qrCodeURL
case .failure(let error):
print(error)
}
}
Custom Attributes and Lambda Triggers
Cognito User Pool allows adding custom attributes (custom:role, custom:company_id). Included in ID Token and accessible in mobile app without extra requests.
Lambda Triggers are powerful for custom logic:
-
Pre-sign-up: email domain validation, block corporate accounts. -
Post-confirmation: create DB record after email confirmation. -
Pre-token-generation: add custom claims to JWT on-the-fly.
Pre-token-generation especially useful: add roles from DynamoDB right into ID Token without extra API calls from mobile client.
Device Tracking
Cognito supports deviceKey — with enabled device tracking, user can see list of authorized devices and delete them. Amplify SDK automatically saves deviceKey in Keychain/EncryptedSharedPreferences on first login.
Enabled in User Pool settings → Devices → Always remember or User opt-in. Adds one parameter to auth flow — doesn't affect performance.
Common Problems
Token expiry vs refresh. Cognito access token lives 5 minutes to 24 hours (configurable). ID token — same. Refresh token — 1 to 3650 days. Amplify auto-refreshes, but if refresh token expired or revoked — Amplify.Auth.fetchAuthSession() returns AuthError.sessionExpired. Must catch and redirect to login.
PKCE and App Client Secret. Mobile App Clients in Cognito shouldn't have Client Secret — can't securely store it in app. When creating App Client: uncheck "Generate client secret". If secret already created — create new App Client without it.
Timeline
Basic integration (SRP auth + TOTP MFA + social providers + Amplify) — 7–12 business days. Adding Identity Pool + IAM roles for direct S3/DynamoDB access — plus 3–5 days. Lambda Triggers with custom business logic — estimate separately by complexity.







