Mobile apps
This guide covers best practices for integrating AgeKey flows into mobile applications. On the web, AgeKey flows are commonly embedded in iframes or opened in new windows, but mobile apps require webview components that support WebAuthn for passkey compatibility.
Overview
AgeKey flows (Use AgeKey, Create AgeKey, and Upgrade AgeKey) are web-based OIDC flows that require redirecting users to AgeKey service URLs. When integrating these flows into mobile applications, you have several options for displaying them, each with different capabilities and trade-offs. The key consideration is:
- AgeKeys support: Whether users can create and use AgeKeys (FIDO-based passkeys) for future verifications
AgeKeys require WebAuthn support, which isn't available in all mobile webview components. To enable AgeKeys for your users, you must use webview components that support WebAuthn.
Mobile implementation methods
Android options
Android provides three primary methods for displaying web content:
-
Custom Tabs ⭐ Recommended - Opens the AgeKey flow URL in a customized Chrome browser tab that maintains your app's branding. This provides full browser capabilities while keeping users within your app's context. Custom Tabs share cookies and authentication state with Chrome, enabling seamless experiences.
-
WebView - Embeds web content directly within your app using Android's native WebView component. While simple to implement, WebView has limited support for modern web standards and can't access certain browser features.
WebView doesn't support WebAuthn, which is required for AgeKeys. Users won't be able to create or use AgeKeys when flows are embedded using WebView. For the best user experience with full AgeKeys support, use Custom Tabs instead.
- Trusted Web Activity (TWA) - Displays web content in full-screen mode, primarily designed for Progressive Web Apps. TWAs require establishing a digital asset link between your app and your domain. When digital asset links aren't detected, TWA automatically falls back to Custom Tabs.
Trusted Web Activities require establishing digital asset links between your app and your domain. Since this adds complexity and TWA falls back to Custom Tabs when digital asset links aren't detected, use Custom Tabs directly for a simpler implementation.
iOS options
iOS provides three primary methods for displaying web content:
-
ASWebAuthenticationSession ⭐ Recommended - Designed specifically for secure authentication flows, this method presents web content in a system-managed browser view. It shares cookies with Safari and provides access to modern web features such as WebAuthn, making it ideal for AgeKey flows.
-
SFSafariViewController - Presents web content in a Safari-like interface that shares cookies and authentication state with Safari. This provides a familiar browsing experience while maintaining app context.
-
WKWebView - Apple's modern web view component that embeds web content within your app. Similar to Android's WebView, WKWebView has limitations with certain web standards and can't access all browser features.
WKWebView doesn't support WebAuthn, which is required for AgeKeys. Users won't be able to create or use AgeKeys when flows are embedded using WKWebView. For the best user experience with full AgeKeys support, use ASWebAuthenticationSession instead.
Receiving flow results
Your mobile app needs to receive results after users complete the AgeKey flow. The recommended approach is to use your backend server as the redirect_uri, which validates and stores results before redirecting to your mobile app's deep link.
Callback URL (recommended method)
The recommended approach for all implementation methods is to use your backend server as the redirect_uri. When you build the AgeKey authorization URL, include your backend server URL as the redirect_uri parameter. After the AgeKey flow completes, it redirects to your backend with the results. Your backend then validates the results, stores them securely, and redirects to your mobile app's deep link.
Advantages of this approach:
- Server-side validation ensures security and data integrity
- Results are stored securely on your backend
- Works with all implementation methods
- Standard pattern for mobile apps with backend validation
How callback URLs work
- Register a deep link handler in your app (for example,
myapp://agekey/callback,myapp://agekey/create-callback, ormyapp://agekey/upgrade-callback) - Set your backend server URL as the
redirect_uriwhen building the AgeKey authorization URL (for example,https://yourapp.com/agekey/callback) - The AgeKey service redirects to your backend after completion
- Your backend validates the results, stores them securely, and redirects to your mobile app's deep link
- Your app handles the deep link and receives the validated results
Redirects only occur when the AgeKey flow URL is opened directly in a browser or web view, not when embedded in an iframe.
Callback URL parameters
When the AgeKey service redirects to your backend server, it includes query parameters or URL fragments relevant to the flow type:
Use AgeKey flow:
id_token: The JWT token containing age threshold results (in URL fragment)state: The state parameter you sent (for CSRF protection)
Create AgeKey flow:
state: The state parameter you sent (for CSRF protection)error: Present if the user declined or an error occurred (for example,access_denied)
Upgrade AgeKey flow:
code: Authorization code (present when all age thresholds are false, in URL fragment)id_token: The JWT token containing age threshold results (in URL fragment)state: The state parameter you sent (for CSRF protection)
Example backend callback URLs from AgeKey:
https://yourapp.com/agekey/callback#id_token=eyJhbGc...&state=abc123xyz789
https://yourapp.com/agekey/create-callback?state=abc123xyz789
https://yourapp.com/agekey/create-callback?state=abc123xyz789&error=access_denied
https://yourapp.com/agekey/upgrade-callback#code=abc123&id_token=eyJhbGc...&state=def456
After your backend validates and stores the results, it redirects to your mobile app's deep link:
myapp://agekey/callback?result=success
myapp://agekey/create-callback?result=success
myapp://agekey/create-callback?result=declined
myapp://agekey/upgrade-callback?result=success
Implementing callback URLs
Always use your backend server URL as the redirect_uri in your authorization URL when initiating AgeKey flows. The redirect_uri must be:
- An HTTPS URL:
https://yourapp.com/agekey/callback - Registered with AgeKey as an allowed redirect URI
Your backend should:
- Receive the callback from AgeKey
- Validate the results server-side, including verifying the JWT signature and checking state
- Store the results securely
- Redirect to your mobile app's deep link with the validation result
For detailed information about building authorization URLs and server-side validation, see the Use AgeKey guide, Create AgeKey guide, and Upgrade AgeKey guide.
Method comparison
| Method | Platform | AgeKeys | Callback URL | Best For |
|---|---|---|---|---|
| WebView | Android | ❌ | ✅ | Not recommended (no AgeKeys support) |
| Custom Tabs | Android | ✅ | ✅ | Most use cases (recommended) |
| Trusted Web Activity | Android | ✅ | ✅ | Not recommended (requires digital asset links) |
| WKWebView | iOS | ❌ | ✅ | Not recommended (no AgeKeys support) |
| ASWebAuthenticationSession | iOS | ✅ | ✅ | Most use cases (recommended) |
| SFSafariViewController | iOS | ✅ | ✅ | Safari-like experience |
Summary
When integrating AgeKey flows into mobile applications, use Custom Tabs for Android or ASWebAuthenticationSession for iOS. Both provide full AgeKeys support via WebAuthn.
Implementation steps:
- Register deep link handlers (URL schemes) for your app's callback URLs
- Build AgeKey authorization URLs with your backend server URL as
redirect_uri - Open the authorization URL using Custom Tabs (Android) or ASWebAuthenticationSession (iOS)
- Your backend validates results server-side, then redirects to your app's deep link
- Handle the deep link callback with validated results
For complete implementation details, see the Use AgeKey guide, Create AgeKey guide, and Upgrade AgeKey guide.