Using passkeys with native mobile apps
Learn how to add passkeys to your native mobile app when using AWS Cognito.
This example will demonstrate how to add passkeys to a native mobile app when using AWS Cognito. It uses the Amplify React Native SDK, but if you’re not using Amplify then you can follow a similar approach can be used to our pre-built UI examples which use the AWS SDK client-side or server-side.
Although the example uses our React Native SDK a similar integration can also be achieved using our iOS SDK, Android SDK or Flutter SDK.
Example code
You can find the full code example on Github.
User flow
Sign up
The user verifies their email via an OTP challenge then is prompted to create a passkey.
Creating a passkey after registration via email OTP
This example uses the pre-built UI to present the email OTP challenge but you can also refer to this branch for a fully native implementation which uses our Client API.
Sign in
The user is prompted to sign in with their passkey without having to input their email.
Signing in with a passkey
Prerequisites
You should first enable passkeys for your Authsignal tenant and ensure that you’ve configured your relying party.
Next, you’ll need to follow these steps to setup apple-app-site-association
(iOS) and assetlinks.json
(Android) files on your web domain.
Installation
Configuration
Update this file with the config values for your Authsignal tenant and region-specific URL, along with the values for your AWS Cognito user pool.
The AWS lambdas
Create Auth Challenge lambda
You can find the full lambda code for this example here.
Verify Auth Challenge Response lambda
You can find the full lambda code for this example here.
The app code
Sign up
You can find a full example of the sign up implementation here.
1. Call Amplify SDK signUp
method
Pass the email as the username.
2. Call Amplify SDK signIn
method
This step invokes the Create Auth Challenge lambda.
3. Launch Authsignal pre-built UI
Pass the url returned by the Create Auth Challenge lambda.
4. Call Amplify SDK confirmSignIn
method
This step invokes the Verify Auth Challenge Response lambda.
Sign in
You can find a full example of the sign in implementation here.
1. Call Authsignal SDK passkey.signIn
method
2. Call Amplify SDK signIn
and confirmSignIn
methods
Pass the username and token returned by the Authsignal SDK.
Optimizing UX for edge cases
Our sign-in approach above optimizes for the happy path where a user has a passkey available on their device. But it can also handle the scenario where a registered user doesn’t have a passkey available - for example, if they have deleted their existing passkey, or if they’ve switched to a new device on a different platform where their existing passkey can’t be synced.
Falling back to email OTP when no passkey is available
This scenario is handled by checking the errorCode
returned by the Authsignal SDK passkey.signIn
method:
On iOS if no passkey is available the Authsignal SDK will return the passkeySignInCanceled
error code, because iOS treats the absence of a passkey credential as a cancellation event if preferImmediatelyAvailableCredentials is set to true.
On Android if no passkey is available the Authsignal SDK will return the noPasskeyCredentialAvailable
error code, because Android returns a more explicit error in this scenario.
To keep the behavior consistent on both platforms, we treat cancellation the same as not having a credential available and fall back to presenting an email OTP sign-in option in each case.
Falling back to email OTP when the user cancels passkey sign-in
This approach allows us to optimize sign-in for the happy path while also achieving a good UX for the edge case where a user can’t use passkeys.
Was this page helpful?