Verifica el correo y el teléfono
Cómo viajan los códigos de un solo uso, quién los envía y los campos que los piden.
Una persona demuestra que un correo o un número de teléfono es suyo escribiendo un código que el kit envió ahí. Esta guía cubre cuándo ocurre, qué necesita cada canal en .env, cómo es el código y cómo poner esos mismos campos verificados en tus propios formularios.
Cuándo se pide un código
| Momento | Canal | Condición |
|---|---|---|
| Registro, campo de correo | Correo | Siempre. El formulario recibe la dirección sólo cuando el código se confirma. |
| Registro, campo de teléfono | SMS o llamada | AUTH_ENABLE_VALIDATION=true. Apagado, el campo no tiene el enlace "Verificar ahora". |
| Inicio de sesión de un paso con correo sin verificar | Correo | AUTH_APPROACH es CreationValidation o LoginValidation, y AUTH_ENABLE_VALIDATION=true. |
| Inicio de sesión de dos pasos, paso uno, correo sin verificar | Correo | Siempre. |
| Perfil, al cambiar el correo | Correo | Siempre. El perfil conserva la nueva dirección sólo después del código. |
| Perfil, al cambiar el teléfono | SMS o llamada | Siempre. |
No se envía nada cuando la dirección o el número ya pertenece a otra cuenta: el campo muestra el error de unicidad en su lugar.
El código
- Los códigos por correo tienen diez caracteres, letras y dígitos, y distinguen mayúsculas. El asunto es "Validación de correo electrónico: " seguido del nombre de tu aplicación, y el cuerpo es un mensaje corto con el código.
- Los códigos por teléfono tienen cuatro dígitos. El mensaje dice "Tu app - Tu código de verificación es: 1234".
Cada solicitud genera un código nuevo, y cada reenvío reemplaza al anterior. El código vive en el estado de la pantalla que lo pidió: no tiene caducidad propia y desaparece con esa pantalla, así que recargar la página empieza de cero. Debe escribirse exacto; un valor equivocado responde "El código de verificación es incorrecto".
Bajo el campo del código corre una cuenta regresiva de treinta segundos: "¿No recibiste el código? 27s". Al terminar aparece el enlace "Reenviar código"; en la pantalla del teléfono, "Reenviar SMS" y "Recibir una llamada". La cuenta regresiva es el único freno: no hay límite de intentos contra un código.
Los códigos por correo y el mailer
Los códigos por correo pasan por el sistema de correo de Laravel, de forma síncrona, con el mailable App\Mail\Auth\ValidateEmail. El primer envío usa MAIL_MAILER. Cada reenvío avanza al siguiente mailer de mail_fallbacks en config/auth.php, que viene así:
'mail_fallbacks' => [
'mailgun',
],
Con la configuración por omisión una persona puede pedir el código dos veces: una por MAIL_MAILER, otra por Mailgun. Un tercer intento ya no encuentra mailer y muestra "No pudimos enviar el código de verificación. Por favor, intenta con otro correo electrónico". Agrega nombres al arreglo para permitir más reenvíos; el mismo nombre puede repetirse. El mailer que finalmente entregó queda registrado en el extra_data de la cuenta bajo mail_driver_used.
Los mailers y sus variables son los de config/mail.php: smtp, mailgun, ses, postmark, resend, log, y failover, que .env.example selecciona y que intenta Mailgun y luego SES. Sus credenciales y cómo elegir uno están en /help/email-and-sms-delivery.
Los códigos por teléfono y el proveedor
AUTH_VALIDATION_PROVIDER elige quién lleva el código al teléfono.
aws, el valor por omisión: Amazon SNS
El código sale como SMS transaccional por Amazon SNS con estas credenciales:
AUTH_VALIDATION_PROVIDER=aws
AWS_ACCESS_KEY_ID=your-aws-access-key-id
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
AWS_DEFAULT_REGION=us-west-1
La región vuelve a us-west-1 cuando la variable falta. Son las mismas llaves que usan el mailer ses y el disco S3, así que un solo usuario IAM con permisos de SNS, SES y S3 cubre los tres. SNS sólo envía mensajes de texto: el diálogo del teléfono envía el SMS en cuanto abre y no hay opción de llamada. El número se envía tal como la persona lo escribió, por eso el campo pide incluir el código de país.
telnyx: Telnyx Verify
AUTH_VALIDATION_PROVIDER=telnyx
TELNYX_API_KEY=your-telnyx-api-key
TELNYX_VERIFY_PROFILE_ID=your-telnyx-verify-profile-id
TELNYX_TOKEN se acepta como nombre antiguo de la llave. Crea un perfil de Verify en el portal de Telnyx y pega su id; el kit le pasa su propio código de cuatro dígitos al perfil, así que el SMS y la llamada llevan el código que la pantalla espera. Con Telnyx el diálogo pregunta primero "Elige cómo quieres recibir el código de verificación" con dos botones, "Enviar SMS" y "Recibir una llamada", y la llamada sigue disponible bajo la cuenta regresiva como alternativa. El número se normaliza a formato internacional antes de la petición, y un número que no se puede normalizar se rechaza.
Con cualquiera de los dos proveedores, cuando falta una llave o el perfil, o el proveedor responde con error, la persona ve el diálogo "No se pudo enviar el código. No pudimos enviar el código de verificación a su teléfono. Por favor, inténtelo de nuevo." y el error se reporta a tu log. Dar de alta cada proveedor, y los SMS que el kit envía fuera de la verificación, se cubren en /help/email-and-sms-delivery.
Lo que ve la persona
En el registro y en el inicio de sesión la tarjeta completa se reemplaza: el título "Por favor confirma tu correo electrónico" o "Por favor confirma tu teléfono", una línea "Se envió un código a tu correo electrónico", un campo "Código de validación", un botón "Confirmar correo electrónico" o "Confirmar código" y la cuenta regresiva. Al confirmar el código, el flujo retoma donde se detuvo: la cuenta se crea, o la sesión abre.
En el perfil, y dentro del registro para el teléfono, la verificación abre como una ventana modal: "Verificar nuevo correo electrónico" o "Verificar nuevo teléfono", el mismo campo, botón y cuenta regresiva. Al confirmar, la ventana cierra, el campo muestra el nuevo valor con una insignia verde "Verificado", y el perfil lo guarda de inmediato.
Los componentes <x-email-input> y <x-phone-input>
Ambos son componentes Blade que envuelven un campo con una insignia de verificación y el enlace "Verificar ahora", y ambos son los campos que el propio kit usa en el registro y en el perfil. Colócalos en cualquier formulario Livewire:
<x-email-input :label="__('Email address')" wire:model.live="user.email" />
<x-phone-input
:label="__('Phone (Include country code)')"
wire:model.live="user.phone"
:validation-required="true"
:verified-at="$user->phone_verified_at"
dispatch-context="profile"
/>
wire:model, o wire:model.live, es el único atributo obligatorio: nombra la propiedad de tu componente que recibe el valor verificado. label y placeholder llegan al campo; cualquier otro atributo se acepta y se ignora.
| Atributo | Componente | Qué hace |
|---|---|---|
validation-required |
teléfono | true muestra el enlace "Verificar ahora". Por omisión false: la insignia se muestra, pero el enlace nunca aparece y el campo dice "Teléfono no válido" bajo cualquier valor sin verificar. |
verified-at |
teléfono | La marca de tiempo que decide si el valor actual empieza como "Verificado". Pasa el phone_verified_at del modelo, o null cuando el valor en pantalla difiere del guardado. |
dispatch-context |
teléfono | Una cadena que vuelve en el evento identity-verified para que tu listener sepa qué formulario preguntó. Por omisión, la ruta del wire:model. |
El componente de correo no tiene esos atributos. Su enlace "Verificar ahora" siempre se muestra, empieza como "Verificado" cuando la propiedad enlazada ya tiene un valor, y el contexto de su evento es siempre la ruta del wire:model, user.email en el ejemplo.
Comportamiento compartido por ambos:
- Bajo el campo, una insignia dice "Verificado" en verde o "No verificado" en ámbar. Escribir un valor distinto del inicial la cambia a "No verificado".
- "Verificar ahora" aparece cuando el valor está bien formado: un correo válido, o un teléfono con al menos once dígitos. Antes de eso se muestra en su lugar "Formato de correo electrónico no válido" o "Teléfono no válido".
- Antes de enviar, el componente revisa que ninguna otra cuenta tenga el valor y muestra el error de unicidad si la hay.
- Tu propiedad enlazada recibe el valor sólo cuando el código se confirma. Mientras la persona escribe, conserva su valor anterior, o pasa a
nullen el correo en cuanto cambia el valor inicial. Por eso una reglarequiredsobre esa propiedad es lo que vuelve obligatoria la verificación; así lo exige el formulario de registro.
Reaccionar a una verificación
Cuando un código se confirma, la ventana modal despacha identity-verified con type, email o phone, value, verified_at y context; el evento del teléfono lleva además column, la ruta del wire:model. Escúchalo cuando necesites guardar la marca de tiempo:
use Livewire\Attributes\On;
#[On('identity-verified')]
public function onIdentityVerified($data)
{
if ($data['context'] !== 'profile') {
return;
}
if ($data['type'] === 'phone') {
$this->user->phone = $data['value'];
$this->user->phone_verified_at = $data['verified_at'];
$this->user->save();
}
}
Revisa context primero: la ventana modal es compartida y una página puede tener varios de estos campos. El contexto del correo es su ruta de wire:model, así que un listener para él compara contra 'user.email' y no contra un nombre que tú elijas.
Desarrollo local
El kit no registra los códigos en ningún lado, así que dales un lugar donde caer:
- Correo: pon
MAIL_MAILER=log. El mensaje completo, código incluido, se escribe enstorage/logs/laravel.log, o en el canal deMAIL_LOG_CHANNEL. Recuerda que un reenvío avanza amail_fallbacks, que apunta a Mailgun: sin credenciales de Mailgun el reenvío falla con error, así que vacía el arreglo en local o pide el código una sola vez. Un capturador SMTP local como Mailpit funciona igual conMAIL_MAILER=smtp. - Teléfono: no hay atajo local. Los SMS y las llamadas pasan por el proveedor real, así que usa credenciales reales y tu propio número, o desarrolla con una identidad de correo y deja el teléfono para una pasada posterior.
- La suite de pruebas corre con
MAIL_MAILER=array, definido enphpunit.xml, así que nada sale de la máquina durante las pruebas.