Passkey Authentication

Register or login a user using passkeys on Android

Register a new user with a passkey

To create a new user account with a passkey, pass the user’s email address or phone number to passage.registerWithPasskey:

suspend fun register(identifier: String) {
    try {
        passage.registerWithPasskey(identifier)
        // passage.getCurrentUser should now return the authenticated user
        val user = passage.getCurrentUser() ?: return
        // Do authenticated stuff
    } catch (e: RegisterWithPasskeyException) {
        handleRegisterWithPasskeyException(e)
    }
}

fun handleRegisterWithPasskeyException(e: RegisterWithPasskeyException) {
    when (e) {
        is RegisterWithPasskeyCancellationException -> {
            // User dismissed native passkey UI prompt
        }
        is RegisterWithPasskeyInvalidRequestException -> {
            // User provided invalid identifier
        }
        is RegisterWithPasskeyConfigurationException -> {
            // There's an issue with your Passage configuration
        }
        is RegisterWithPasskeyInterruptedException -> {
            // The app was interrupted by the OS, try again
        }
        is RegisterWithPasskeyCredentialException -> {
            // Something wrong with the user's passkey
        }
    }
}

Log in an existing user with a passkey

To log in an existing user with a passkey, pass the user’s email address or phone number to passage.loginWithPasskey:

suspend fun login(identifier: String) {
    try {
        passage.loginWithPasskey(identifier)
        // passage.getCurrentUser should now return the authenticated user
        val user = passage.getCurrentUser() ?: return
        // Do authenticated stuff
    } catch (e: LoginWithPasskeyException) {
        handleLoginWithPasskeyException(e)
    }
}

fun handleLoginWithPasskeyException(e: LoginWithPasskeyException) {
    when (e) {
        is LoginWithPasskeyCancellationException -> {
            // User dismissed native passkey UI prompt
        }
        is LoginWithPasskeyInvalidRequestException -> {
            // User provided invalid identifier
        }
        is LoginWithPasskeyConfigurationException -> {
            // There's an issue with your Passage configuration
        }
        is LoginWithPasskeyInterruptedException -> {
            // The app was interrupted by the OS, try again
        }
        is LoginWithPasskeyCredentialException -> {
            // Something wrong with the user's passkey
        }
        is LoginWithPasskeyInactiveUserException -> {
            // User account is no longer active
        }
    }
}

Autofill passkey login (aka “Conditional UI”)

On your app’s login screen, you can try to surface the user’s passkey without them needing to type in an identifier using the passage.autofillPasskeyLogin method. We recommend attempting this method when the user taps into the email/phone Edit Text component. If the user does not already have a passkey, no passkey prompt will be shown. Here’s an example:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // ...
    editText.setOnFocusChangeListener { _, hasFocus ->
        if (hasFocus) {
            attemptPasskeyAutofill()
        }
    }
}

fun attemptPasskeyAutofill() {
    ioScope.launch {
	// If user has a passkey for this app, they'll be prompted to log in with it.
        passage.autofillPasskeyLogin() ?: return@launch
        // Do authenticated stuff
    }
}

What's next? ❤️

Your users will LOVE using passkeys. But sometimes you might want to provide fallbacks in the odd case it won't work for them. This is why we provide amazing fallback solutions, too. Read on!

Last updated

Change request #337: react native