Skip to main content
Authenticate users with email or SMS one-time passwords (OTP).

Email Authentication

import com.dynamic.sdk.android.DynamicSDK

val sdk = DynamicSDK.getInstance()

// Send OTP to email
sdk.auth.email.sendOTP("[email protected]")

// Later, verify:
sdk.auth.email.verifyOTP("123456")

// Resend if needed:
sdk.auth.email.resendOTP()

Rate Limits

Email verification is subject to the following rate limits:
  • 3 attempts per 10 minutes per email address
This is in place to protect deliverability of emails and to prevent abuse.

SMS Authentication

import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.PhoneData

val sdk = DynamicSDK.getInstance()

// Send OTP via SMS
val phoneData = PhoneData(
    dialCode = "+1",
    iso2 = "US",
    phone = "5551234567"
)
sdk.auth.sms.sendOTP(phoneData)

// Later, verify:
sdk.auth.sms.verifyOTP("123456")

// Resend if needed:
sdk.auth.sms.resendOTP()

External JWT Authentication

For apps with existing authentication systems, you can authenticate users with an external JWT:
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.SignInWithExternalJwtParams

val sdk = DynamicSDK.getInstance()

sdk.auth.externalAuth.signInWithExternalJwt(
    SignInWithExternalJwtParams(jwt = "your-jwt-token")
)

Passkey Authentication

Sign in with a passkey:
import com.dynamic.sdk.android.DynamicSDK

val sdk = DynamicSDK.getInstance()

sdk.auth.passkey.signIn()
For more details on passkey management and setup, see the Passkeys documentation.

Authentication State

Monitor authentication state and get user information:
import com.dynamic.sdk.android.DynamicSDK
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

val sdk = DynamicSDK.getInstance()

// Check if user is authenticated
val isAuthenticated = sdk.auth.isAuthenticated()

// Get current user
val user = sdk.auth.authenticatedUser
if (user != null) {
    println("User: ${user.userId}")
    println("Email: ${user.email}")
}

// Get auth token
val token = sdk.auth.token
if (token != null) {
    println("Token: $token")
}

// Listen for authentication changes (in ViewModel)
viewModelScope.launch {
    sdk.auth.authenticatedUserChanges.collect { user ->
        if (user != null) {
            // User logged in
            println("User authenticated: ${user.userId}")
        } else {
            // User logged out
            println("User logged out")
        }
    }
}

// Listen for token changes (in ViewModel)
viewModelScope.launch {
    sdk.auth.tokenChanges.collect { token ->
        if (token != null) {
            println("Token updated: $token")
        }
    }
}

// Logout
sdk.auth.logout()

Built-in UI

The easiest way to add authentication is using the built-in UI which handles all authentication methods:
import com.dynamic.sdk.android.DynamicSDK

val sdk = DynamicSDK.getInstance()
sdk.ui.showAuth()

Best Practices

1. Error Handling

Always handle errors gracefully and provide clear feedback to users:
try {
    sdk.auth.email.sendOTP(email)
} catch (e: Exception) {
    when {
        e.message?.contains("rate limit") == true -> {
            showError("Too many attempts. Please try again later.")
        }
        e.message?.contains("invalid email") == true -> {
            showError("Please enter a valid email address.")
        }
        else -> {
            showError("Failed to send OTP: ${e.message}")
        }
    }
}

2. User Experience

  • Show loading states during authentication
  • Provide clear error messages
  • Allow users to resend OTP if needed
  • Display the email/phone where OTP was sent

3. Security

  • Never store OTP codes
  • Always use HTTPS connections
  • Implement proper session management
  • Handle token refresh automatically

Troubleshooting

OTP Not Received

  • Check that the email/phone number is valid
  • Look in spam folder for email OTP
  • Verify that the provider is enabled in Dynamic dashboard
  • Check rate limits haven’t been exceeded

Authentication Fails

  • Ensure OTP code is entered correctly
  • Check that the code hasn’t expired (codes typically expire after 10 minutes)
  • Verify network connectivity
  • Check for any error messages in Logcat

Session Not Persisting

  • Ensure you’re listening to authenticatedUserChanges flow
  • Verify that the SDK is properly initialized
  • Check that you’re not clearing app data

What’s Next

Now that you have authentication set up:
  1. Social Authentication - Add social login options
  2. Session Management - Manage authenticated sessions with Kotlin Flow
  3. Wallet Operations - Work with user wallets
  4. MFA - Add multi-factor authentication