Did you follow the quick start instructions to set up the Authenticator first?
Initial State
By default, unauthenticated users are redirected to the Sign In flow. You can explicitly redirect to Sign Up or Forgot Password:
Login Mechanisms
Whether the user is able to sign in with their username, phone number or email is determined based on the value in amplifyconfiguration.json, which is created on amplify pull. This value determines which login mechanism Authenticator for Android uses, no other configuration is supported.
Passwordless Authentication
Passkey support requires Android API level 28+ with Google Play Services.
Backend Configuration
For backend setup including Email OTP, SMS OTP, and WebAuthn (Passkey) configuration, see the Passwordless documentation.
Authentication Flows
The Authenticator supports two authentication flows:
Password Flow (Default)
Traditional password-based authentication:
val authenticatorState = rememberAuthenticatorState(
authenticationFlow = AuthenticationFlow.Password
)
Authenticator(
state = authenticatorState
) { state ->
Text("Welcome!")
}
User Choice Flow
Allows users to choose from available authentication methods:
val authenticatorState = rememberAuthenticatorState(
authenticationFlow = AuthenticationFlow.UserChoice()
)
Authenticator(
state = authenticatorState
) { state ->
Text("Welcome!")
}
Available Authentication Factors
| Factor | Description | Code |
|---|---|---|
| Password | Traditional password with SRP | AuthFactor.Password(srp = true) |
| Password (no SRP) | Password without SRP | AuthFactor.Password(srp = false) |
| Email OTP | One-time code via email | AuthFactor.EmailOtp |
| SMS OTP | One-time code via SMS | AuthFactor.SmsOtp |
| WebAuthn (Passkey) | Biometric/security key authentication | AuthFactor.WebAuthn |
Preferred Auth Factor
Skip the factor selection step by specifying a preferred factor:
val authenticatorState = rememberAuthenticatorState(
authenticationFlow = AuthenticationFlow.UserChoice(
preferredAuthFactor = AuthFactor.WebAuthn
)
)
Authenticator(
state = authenticatorState
) { state ->
Text("Welcome!")
}
When a preferred factor is set:
- If the user has that factor available, they'll use it directly
- If not available, they'll see the factor selection screen
Passkey Prompts
Control when users are prompted to create a passkey:
val authenticatorState = rememberAuthenticatorState(
authenticationFlow = AuthenticationFlow.UserChoice(
passkeyPrompts = PasskeyPrompts(
afterSignUp = PasskeyPrompt.Always, // Prompt after sign-up
afterSignIn = PasskeyPrompt.Never // Don't prompt after sign-in
)
)
)
Authenticator(
state = authenticatorState
) { state ->
Text("Welcome!")
}
PasskeyPrompt Options:
PasskeyPrompt.Always- Always prompt to create a passkey (if user doesn't have one)PasskeyPrompt.Never- Never prompt to create a passkey
Authentication Flow Steps
When using UserChoice flow, users may encounter these additional steps:
- SignInSelectAuthFactor - User selects their preferred authentication method
- SignInConfirmPassword - User enters password (if password factor selected)
- PromptToCreatePasskey - User is prompted to create a passkey
- PasskeyCreated - Confirmation after successful passkey creation
Complete Example
val authenticatorState = rememberAuthenticatorState(
authenticationFlow = AuthenticationFlow.UserChoice(
preferredAuthFactor = AuthFactor.WebAuthn,
passkeyPrompts = PasskeyPrompts(
afterSignUp = PasskeyPrompt.Always,
afterSignIn = PasskeyPrompt.Always
)
)
)
Authenticator(
state = authenticatorState
) { state ->
Text("Welcome!")
}
Sign Up Attributes
The Authenticator automatically infers signUpAttributes from amplify pull,
but can be explicitly defined as seen below.
The Authenticator automatically renders most Cognito User Pools attributes,
with the exception of address, gender, locale, picture, updated_at, and zoneinfo. Because these are often app-specific, they can be customized via Sign Up fields.
By default, the Authenticator will still require any attributes required for
verification, such as email, even if signUpAttributes is empty:
val authenticatorState = rememberAuthenticatorState(
signUpForm = {
email()
username()
password()
confirmPassword()
}
)
Authenticator(state = authenticatorState) {
// ...
}
val authenticatorState = rememberAuthenticatorState(
signUpForm = {
username()
password()
confirmPassword()
email()
phoneNumber()
birthdate()
familyName()
givenName()
middleName()
name()
nickname()
preferredUsername()
profile()
website()
}
)
Authenticator(state = authenticatorState) {
// ...
}
TOTP Issuer
The TOTP issuer is the name that will be shown in TOTP applications preceding the account name. In most cases, this should be the name of your app. For example, if your app is called "My App", your user will see "My App" - "username" in their TOTP app. This can be customized by adding the totpOptions argument to the Authenticator state with a value for issuer.
Note: Unless changed, the default issuer is the application label retrieved from package manager.
val authenticatorState = rememberAuthenticatorState(
totpOptions = TotpOptions(issuer = "My App")
)
Authenticator(state = authenticatorState) {
// ...
}