Cómo restringir el login con Google a un dominio institucional en Laravel
Cuando una organización quiere que solo su gente entre a una aplicación (por ejemplo, el correo @universidad.edu.co), la tentación es confiar en el selector de cuentas de Google. Es un error común: restringir el dominio en el botón no protege la aplicación. Este artículo muestra cómo hacerlo bien con Laravel Socialite.
1. El parámetro hd es solo una pista
Google acepta el parámetro hd (hosted domain) para que el selector de cuentas muestre primero las cuentas de ese dominio. Pero quien arma la URL de autorización a mano puede quitarlo o cambiarlo, así que no es una barrera de seguridad.
return Socialite::driver('google')
->with(['hd' => 'universidad.edu.co'])
->redirect();
Úsalo por comodidad de usuario, nunca como control de acceso.
2. Valida el dominio en el callback
La comprobación que importa ocurre en el servidor, con los datos que devuelve Google:
$googleUser = Socialite::driver('google')->user();
$email = strtolower($googleUser->getEmail());
$allowedDomain = 'universidad.edu.co';
abort_unless(str_ends_with($email, '@'.$allowedDomain), 403);
Dos detalles que evitan fallos sutiles:
- Compara contra
'@'.$dominio, no solo contra el dominio. Constr_ends_with($email, 'universidad.edu.co')también pasaríaalguien@falsouniversidad.edu.co. - Normaliza a minúsculas antes de comparar.
3. Comprueba que el correo esté verificado
La respuesta de Google incluye si el correo fue verificado. Exígelo antes de crear o asociar la cuenta:
abort_unless(($googleUser->user['email_verified'] ?? false) === true, 403);
4. Crea o actualiza el usuario y asigna el rol
Una vez validado, busca al usuario por correo y asígnale un rol por defecto con el mínimo de privilegios. Los permisos elevados se conceden después de forma explícita, no se deducen del correo.
$user = User::firstOrCreate(
['email' => $email],
['name' => $googleUser->getName(), 'password' => Str::random(40)],
);
Auth::login($user);
5. Pruébalo
Escribe al menos tres pruebas: un correo del dominio permitido entra, un correo de otro dominio recibe 403 y un correo con dominio parecido (falsouniversidad.edu.co) también recibe 403. Son las que protegen de regresiones cuando alguien refactorice el callback.
Resumen
| Capa | Para qué sirve | ¿Es seguridad? |
|---|---|---|
Parámetro hd |
Mejorar la experiencia del selector | No |
| Validación del dominio en el servidor | Control de acceso real | Sí |
email_verified |
Evitar correos no confirmados | Sí |
| Rol por defecto sin privilegios | Limitar el daño | Sí |