You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Amplify React Native注册验证码问题及MFA启用与状态查询

AWS Amplify React Native: Verification Code Tracking & MFA Management

Hey there! Let's break down your two questions step by step with practical code examples and explanations tailored for React Native.


1. Tracking Verification Code Delivery & UI Notifications for Auth.signUp

AWS Amplify doesn’t provide a direct real-time way to confirm if a user received their verification code (since delivery depends on email/SMS providers), but you can guide users through the signup flow with clear UI feedback based on API responses and error handling.

Key Approaches:

  • Success Feedback: After a successful signUp call, immediately notify the user to check their email/phone for the code.
  • Error Handling: Catch specific exceptions during confirmation to address issues like incorrect/expired codes, and offer a way to resend the code.
  • State Management: Use React state to store messages and render them in your UI.

Example Code:

import { Auth } from 'aws-amplify';
import { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet } from 'react-native';

export default function SignUpScreen() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [verificationCode, setVerificationCode] = useState('');
  const [uiMessage, setUiMessage] = useState('');

  const handleSignUp = async () => {
    try {
      const { user } = await Auth.signUp({
        username: email,
        password,
        attributes: { email } // Use `phone_number` for SMS verification
      });
      setUiMessage(`Check your inbox at ${user.attributes.email} for the verification code!`);
    } catch (err) {
      setUiMessage(`Signup failed: ${err.message}`);
      console.error('Signup error:', err);
    }
  };

  const handleConfirmSignUp = async () => {
    try {
      await Auth.confirmSignUp(email, verificationCode);
      setUiMessage('Signup confirmed! You can now log in.');
    } catch (err) {
      // Target specific error cases to give precise feedback
      switch (err.name) {
        case 'CodeMismatchException':
          setUiMessage('Oops, that verification code is incorrect. Try again!');
          break;
        case 'ExpiredCodeException':
          setUiMessage('Your code has expired. Request a new one below.');
          break;
        default:
          setUiMessage(`Confirmation failed: ${err.message}`);
      }
      console.error('Confirmation error:', err);
    }
  };

  const handleResendCode = async () => {
    try {
      await Auth.resendSignUpCode(email);
      setUiMessage('New verification code sent! Check your email again.');
    } catch (err) {
      setUiMessage(`Failed to resend code: ${err.message}`);
      console.error('Resend code error:', err);
    }
  };

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        autoCapitalize="none"
      />
      <TextInput
        style={styles.input}
        placeholder="Password"
        secureTextEntry
        value={password}
        onChangeText={setPassword}
      />
      <Button title="Sign Up" onPress={handleSignUp} />

      {uiMessage && <Text style={styles.message}>{uiMessage}</Text>}

      {uiMessage.includes('verification code') && (
        <>
          <TextInput
            style={styles.input}
            placeholder="Verification Code"
            value={verificationCode}
            onChangeText={setVerificationCode}
            keyboardType="numeric"
          />
          <Button title="Confirm Sign Up" onPress={handleConfirmSignUp} />
          <Button title="Resend Code" onPress={handleResendCode} />
        </>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 20, gap: 15 },
  input: { borderWidth: 1, borderColor: '#ccc', padding: 10, borderRadius: 5 },
  message: { marginTop: 10, color: '#333', textAlign: 'center' }
});

2. Querying User MFA Status & Enabling MFA

Since your MFA is set to optional, you can check a user’s current MFA status and let them enable it directly from your UI using Amplify’s Auth methods.

Checking MFA Status

Use Auth.currentAuthenticatedUser() to fetch the user object. The MFAOptions array in the user object will contain any enabled MFA methods (e.g., TOTP). If the array is empty, MFA is not enabled.

Enabling MFA (TOTP)

The process involves three steps:

  1. Generate a TOTP secret/URI (for QR code scanning) with Auth.setupTOTP().
  2. Verify the code from the user’s authenticator app with Auth.verifyTotpToken().
  3. Set TOTP as the preferred MFA method with Auth.setPreferredMFA().

Example Code:

import { Auth } from 'aws-amplify';
import { useState, useEffect } from 'react';
import { View, Text, Button, TextInput, StyleSheet } from 'react-native';
// Optional: Use a QR code library like `react-native-qrcode-svg` to render the QR code
// import QRCode from 'react-native-qrcode-svg';

export default function MfaSettingsScreen() {
  const [user, setUser] = useState(null);
  const [mfaEnabled, setMfaEnabled] = useState(false);
  const [totpCode, setTotpCode] = useState('');
  const [uiMessage, setUiMessage] = useState('');
  const [totpUri, setTotpUri] = useState('');

  useEffect(() => {
    fetchUserMfaStatus();
  }, []);

  const fetchUserMfaStatus = async () => {
    try {
      const currentUser = await Auth.currentAuthenticatedUser();
      setUser(currentUser);
      // Check if any MFA methods are enabled
      setMfaEnabled(currentUser.MFAOptions.length > 0);
    } catch (err) {
      setUiMessage(`Failed to load user info: ${err.message}`);
      console.error('User fetch error:', err);
    }
  };

  const startMfaSetup = async () => {
    try {
      const { uri } = await Auth.setupTOTP(user);
      setTotpUri(uri);
      setUiMessage('Scan the QR code below with your authenticator app (e.g., Google Authenticator).');
    } catch (err) {
      setUiMessage(`Failed to start MFA setup: ${err.message}`);
      console.error('MFA setup error:', err);
    }
  };

  const verifyAndEnableMfa = async () => {
    try {
      // Verify the code from the authenticator app
      await Auth.verifyTotpToken(user, totpCode);
      // Set TOTP as the preferred MFA method
      await Auth.setPreferredMFA(user, 'TOTP');
      setUiMessage('MFA successfully enabled! Your account is now more secure.');
      setMfaEnabled(true);
      setTotpUri('');
    } catch (err) {
      setUiMessage(`Failed to verify code: ${err.message}`);
      console.error('MFA verification error:', err);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.header}>MFA Settings</Text>
      <Text style={styles.status}>Current Status: {mfaEnabled ? '✅ Enabled' : '❌ Not Enabled'}</Text>
      
      {uiMessage && <Text style={styles.message}>{uiMessage}</Text>}

      {!mfaEnabled && (
        <Button title="Enable MFA" onPress={startMfaSetup} />
      )}

      {totpUri && (
        <>
          {/* Render QR code if using a library */}
          {/* <QRCode value={totpUri} size={200} /> */}
          <Text style={styles.note}>Or manually enter the secret from the URI into your app.</Text>
          <TextInput
            style={styles.input}
            placeholder="Enter MFA Code"
            value={totpCode}
            onChangeText={setTotpCode}
            keyboardType="numeric"
          />
          <Button title="Verify & Enable" onPress={verifyAndEnableMfa} />
        </>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 20, gap: 15 },
  header: { fontSize: 20, fontWeight: 'bold', textAlign: 'center' },
  status: { fontSize: 16, textAlign: 'center' },
  message: { textAlign: 'center', color: '#333' },
  note: { textAlign: 'center', marginTop: 10, color: '#666' },
  input: { borderWidth: 1, borderColor: '#ccc', padding: 10, borderRadius: 5 }
});

内容的提问来源于stack exchange,提问作者sejn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:12:41