Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Add MFA with TOTP authenticator apps.
Add MFA device
Register a new TOTP authenticator device:
import com.dynamic.sdk.android.Models.MfaAddDevice
// Generate a new MFA secret
val deviceInfo: MfaAddDevice = sdk.mfa.addDevice("totp")
println("Secret: ${deviceInfo.secret}")
println("QR Code URI: otpauth://totp/YourApp:user@example.com?secret=${deviceInfo.secret}&issuer=YourApp")
The MfaAddDevice response contains:
secret: The TOTP secret to add to an authenticator app
- Use this secret to generate a QR code for easy scanning
Generate QR code
Create a QR code for easy authenticator app setup:
import com.google.zxing.BarcodeFormat
import com.google.zxing.qrcode.QRCodeWriter
import android.graphics.Bitmap
import java.net.URLEncoder
fun generateQRCode(secret: String, accountName: String, issuer: String): Bitmap? {
return try {
val encodedIssuer = URLEncoder.encode(issuer, "UTF-8")
val encodedAccount = URLEncoder.encode(accountName, "UTF-8")
val totpUri = "otpauth://totp/$encodedIssuer:$encodedAccount?secret=$secret&issuer=$encodedIssuer"
val writer = QRCodeWriter()
val bitMatrix = writer.encode(totpUri, BarcodeFormat.QR_CODE, 512, 512)
val width = bitMatrix.width
val height = bitMatrix.height
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until height) {
bitmap.setPixel(
x, y,
if (bitMatrix[x, y]) android.graphics.Color.BLACK
else android.graphics.Color.WHITE
)
}
}
bitmap
} catch (e: Exception) {
null
}
}
// Usage
val user = sdk.auth.authenticatedUser
val accountName = user?.email ?: user?.userId ?: "Account"
val issuer = "YourApp"
val qrBitmap = generateQRCode(deviceInfo.secret, accountName, issuer)
Verify MFA device
After adding the secret to an authenticator app, verify it with a code:
// User enters the 6-digit code from their authenticator app
val verificationCode = "123456"
sdk.mfa.verifyDevice(verificationCode, "totp")
Get MFA devices
List all registered MFA devices:
import com.dynamic.sdk.android.Models.MfaDevice
val devices: List<MfaDevice> = sdk.mfa.getUserDevices()
devices.forEach { device ->
println("Device ID: ${device.id}")
println("Type: ${device.type}")
println("Created: ${device.createdAt}")
}
Remove MFA device
Delete an MFA device:
val deviceId = "device-id"
val mfaAuthToken = "mfa-auth-token" // Obtained from MFA authentication
sdk.mfa.deleteUserDevice(deviceId, mfaAuthToken)
Get recovery codes
Retrieve MFA recovery codes:
val recoveryCodes: List<String> = sdk.mfa.getRecoveryCodes()
recoveryCodes.forEach { code ->
println("Recovery code: $code")
}
Complete MFA setup flow
Here’s a complete example of the MFA setup flow:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.MfaAddDevice
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class MfaSetupViewModel(private val sdk: DynamicSDK) : ViewModel() {
private val _deviceInfo = MutableStateFlow<MfaAddDevice?>(null)
val deviceInfo: StateFlow<MfaAddDevice?> = _deviceInfo
private val _verificationCode = MutableStateFlow("")
val verificationCode: StateFlow<String> = _verificationCode
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading
private val _error = MutableStateFlow<String?>(null)
val error: StateFlow<String?> = _error
fun generateSecret() {
viewModelScope.launch {
_isLoading.value = true
_error.value = null
try {
val device = sdk.mfa.addDevice("totp")
_deviceInfo.value = device
} catch (e: Exception) {
_error.value = "Failed to generate secret: ${e.message}"
}
_isLoading.value = false
}
}
fun updateCode(code: String) {
_verificationCode.value = code
}
fun verifyDevice(onSuccess: () -> Unit) {
viewModelScope.launch {
_isLoading.value = true
_error.value = null
try {
sdk.mfa.verifyDevice(_verificationCode.value.trim(), "totp")
onSuccess()
} catch (e: Exception) {
_error.value = "Verification failed: ${e.message}"
}
_isLoading.value = false
}
}
}
Supported authenticator apps
The Dynamic SDK works with any TOTP-compatible authenticator app:
- Google Authenticator
- Microsoft Authenticator
- Authy
- 1Password
- Bitwarden
- LastPass Authenticator