Autentica mediante el Acceso con Facebook y JavaScript

Puedes permitir que tus usuarios se autentiquen con Firebase mediante sus cuentas de Facebook si integras el Acceso con Facebook en tu app. Puedes hacerlo si usas el SDK de Firebase para ejecutar el flujo de acceso o ejecutar el flujo del Acceso con Facebook de forma manual y pasar el token de acceso a Firebase.

Antes de comenzar

  1. Agrega Firebase a tu proyecto de JavaScript.
  2. En el sitio Facebook for Developers, obtén el ID de app y un Secret de app para tu aplicación.
  3. Habilita el Acceso con Facebook:
    1. En Firebase console, abre la sección Authentication.
    2. En la pestaña Método de acceso, habilita el método de acceso con Facebook y especifica el ID de app y la clave secreta de la app que obtuviste de Facebook.
    3. Luego, asegúrate de que tu URI de redireccionamiento de OAuth (p. ej., my-app-12345.firebaseapp.com/__/auth/handler) aparezca en la lista de URI de redireccionamiento de OAuth en la página de configuración de tu app en Facebook, en la sección Configuración, en Productos > Acceso con Facebook, del sitio Facebook for Developers.

Maneja el flujo de acceso con el SDK de Firebase

Si estás creando una aplicación web, la manera más fácil de autenticar a tus usuarios en Firebase con sus cuentas de Facebook es administrar el flujo de acceso con el SDK de Firebase JavaScript. Si deseas autenticar a un usuario en Node.js o en cualquier otro entorno que no sea de un navegador, debes manejar el flujo de acceso de forma manual.

Para manejar el flujo de acceso con el SDK de Firebase JavaScript, sigue estos pasos:

  1. Crea una instancia del objeto proveedor de Facebook:
    WebWeb
    import { FacebookAuthProvider } from "firebase/auth";
    
    const provider = new FacebookAuthProvider();
    var provider = new firebase.auth.FacebookAuthProvider();
  2. Opcional: Especifica los permisos adicionales de OAuth 2.0 que deseas solicitarle al proveedor de autenticación. Para agregar un permiso, llama a addScope. Por ejemplo:
    WebWeb
    provider.addScope('user_birthday');
    provider.addScope('user_birthday');
    Consulta la documentación del proveedor de autenticación.
  3. Opcional: Para ajustar el flujo de OAuth del proveedor según su idioma de preferencia sin pasar de forma explícita los parámetros OAuth personalizados pertinentes, actualiza el código de idioma en la instancia Auth antes de iniciar el flujo de OAuth. Por ejemplo:
    WebWeb
    import { getAuth } from "firebase/auth";
    
    const auth = getAuth();
    auth.languageCode = 'it';
    // To apply the default browser preference instead of explicitly setting it.
    // auth.useDeviceLanguage();
    firebase.auth().languageCode = 'it';
    // To apply the default browser preference instead of explicitly setting it.
    // firebase.auth().useDeviceLanguage();
  4. Opcional: Especifica los parámetros personalizados adicionales del proveedor de OAuth que quieres enviar junto con la solicitud de OAuth. Para agregar un parámetro personalizado, llama a setCustomParameters en el proveedor inicializado con un objeto que contenga la clave que se indica en la documentación del proveedor de OAuth y su valor correspondiente. Por ejemplo:
    WebWeb
    provider.setCustomParameters({
      'display': 'popup'
    });
    provider.setCustomParameters({
      'display': 'popup'
    });
    No se permiten los parámetros de OAuth necesarios reservados y se ignorarán. Consulta la referencia del proveedor de autenticación para obtener más información.
  5. Autentica con Firebase a través del objeto proveedor de Facebook. Puedes pedirles a los usuarios que accedan con sus cuentas de Facebook a través de una ventana emergente o redireccionándolos a la página de acceso. En dispositivos móviles, se prefiere el método de redireccionamiento.
    • Para acceder con una ventana emergente, llama a signInWithPopup:
      WebWeb
      import { getAuth, signInWithPopup, FacebookAuthProvider } from "firebase/auth";
      
      const auth = getAuth();
      signInWithPopup(auth, provider)
        .then((result) => {
          // The signed-in user info.
          const user = result.user;
      
          // This gives you a Facebook Access Token. You can use it to access the Facebook API.
          const credential = FacebookAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
      
          // IdP data available using getAdditionalUserInfo(result)
          // ...
        })
        .catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.customData.email;
          // The AuthCredential type that was used.
          const credential = FacebookAuthProvider.credentialFromError(error);
      
          // ...
        });
      firebase
        .auth()
        .signInWithPopup(provider)
        .then((result) => {
          /** @type {firebase.auth.OAuthCredential} */
          var credential = result.credential;
      
          // The signed-in user info.
          var user = result.user;
          // IdP data available in result.additionalUserInfo.profile.
            // ...
      
          // This gives you a Facebook Access Token. You can use it to access the Facebook API.
          var accessToken = credential.accessToken;
      
          // ...
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
      
          // ...
        });
      Además, ten en cuenta que puedes recuperar el token OAuth del proveedor de Facebook que se puede usar para obtener datos adicionales mediante las API de Facebook.

      Aquí también puedes detectar y resolver errores. Para obtener una lista de códigos de error, consulta los documentos de referencia de autenticación.

    • Para acceder mediante el redireccionamiento a la página de acceso, llama a signInWithRedirect: Sigue las prácticas recomendadas cuando uses “signInWithRedirect”.
      WebWeb
      import { getAuth, signInWithRedirect } from "firebase/auth";
      
      const auth = getAuth();
      signInWithRedirect(auth, provider);
      firebase.auth().signInWithRedirect(provider);
      Luego, para recuperar el token de OAuth del proveedor de Facebook, puedes llamar a getRedirectResult cuando se cargue tu página:
      WebWeb
      import { getAuth, getRedirectResult, FacebookAuthProvider } from "firebase/auth";
      
      const auth = getAuth();
      getRedirectResult(auth)
        .then((result) => {
          // This gives you a Facebook Access Token. You can use it to access the Facebook API.
          const credential = FacebookAuthProvider.credentialFromResult(result);
          const token = credential.accessToken;
      
          const user = result.user;
          // IdP data available using getAdditionalUserInfo(result)
          // ...
        }).catch((error) => {
          // Handle Errors here.
          const errorCode = error.code;
          const errorMessage = error.message;
          // The email of the user's account used.
          const email = error.customData.email;
          // AuthCredential type that was used.
          const credential = FacebookAuthProvider.credentialFromError(error);
          // ...
        });
      firebase.auth()
        .getRedirectResult()
        .then((result) => {
          if (result.credential) {
            /** @type {firebase.auth.OAuthCredential} */
            var credential = result.credential;
      
            // This gives you a Facebook Access Token. You can use it to access the Facebook API.
            var token = credential.accessToken;
            // ...
          }
          // The signed-in user info.
          var user = result.user;
          // IdP data available in result.additionalUserInfo.profile.
            // ...
        }).catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
          // ...
        });
      Aquí también puedes detectar y resolver errores. Para obtener una lista de códigos de error, consulta los documentos de referencia de autenticación.

Si habilitaste la configuración Una cuenta por dirección de correo electrónico en Firebase console, aparecerá el error auth/account-exists-with-different-credential junto con un objeto AuthCredential (token de acceso de Facebook) cuando un usuario trate de acceder a un proveedor (como Facebook) con un correo electrónico que ya está vinculado al proveedor de otro usuario de Firebase (como Google). Para completar el acceso al proveedor deseado, el usuario primero debe acceder al proveedor existente (Google) y luego establecer el vínculo con la AuthCredential anterior (token acceso de Facebook).

Si usas signInWithPopup, puedes manejar los errores auth/account-exists-with-different-credential con un código como el siguiente:

import {
  getAuth,
  linkWithCredential,
  signInWithPopup,
  FacebookAuthProvider,
} from "firebase/auth";

try {
  // Step 1: User tries to sign in using Facebook.
  let result = await signInWithPopup(getAuth(), new FacebookAuthProvider());
} catch (error) {
  // Step 2: User's email already exists.
  if (error.code === "auth/account-exists-with-different-credential") {
    // The pending Facebook credential.
    let pendingCred = error.credential;

    // Step 3: Save the pending credential in temporary storage,

    // Step 4: Let the user know that they already have an account
    // but with a different provider, and let them choose another
    // sign-in method.
  }
}

// ...

try {
  // Step 5: Sign the user in using their chosen method.
  let result = await signInWithPopup(getAuth(), userSelectedProvider);

  // Step 6: Link to the Facebook credential.
  // TODO: implement `retrievePendingCred` for your app.
  let pendingCred = retrievePendingCred();

  if (pendingCred !== null) {
    // As you have access to the pending credential, you can directly call the
    // link method.
    let user = await linkWithCredential(result.user, pendingCred);
  }

  // Step 7: Continue to app.
} catch (error) {
  // ...
}

Modo de redireccionamiento

Este error se maneja de manera similar en el modo de redireccionamiento, con la diferencia de que la credencial pendiente debe almacenarse en caché entre acciones de redireccionamiento de páginas (por ejemplo, el uso de almacenamiento de sesión).

También puedes autenticar con Firebase mediante una cuenta de Facebook. Para ello, debes administrar el flujo de acceso con el SDK de JavaScript del Acceso con Facebook:

  1. Para integrar el servicio de Acceso con Facebook en tu app, sigue las indicaciones de los documentos para programadores. Asegúrate de configurar el Acceso con Facebook con tu ID de la app de Facebook:
    <script src="//connect.facebook.net/en_US/sdk.js"></script>
    <script>
      FB.init({
        /**********************************************************************
         * TODO(Developer): Change the value below with your Facebook app ID. *
         **********************************************************************/
        appId: '<YOUR_FACEBOOK_APP_ID>',
        status: true,
        xfbml: true,
        version: 'v2.6',
      });
    </script>
  2. También se configura un objeto de escucha en el estado de autenticación de Facebook:
    FB.Event.subscribe('auth.authResponseChange', checkLoginState);
  3. Después de integrar el Acceso con Facebook, agrega un botón de acceso con Facebook a tus páginas web:
    <fb:login-button
      data-auto-logout-link="true"
      scope="public_profile,email"
      size="large"
    ></fb:login-button>
  4. En la devolución de llamada de estado de la autenticación con Facebook, intercambia el token de autenticación de la respuesta de autenticación de Facebook por una credencial de Firebase y accede con Firebase:
    WebWeb
    import { getAuth, onAuthStateChanged, signInWithCredential, signOut, FacebookAuthProvider } from "firebase/auth";
    const auth = getAuth();
    
    function checkLoginState(response) {
      if (response.authResponse) {
        // User is signed-in Facebook.
        const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
          unsubscribe();
          // Check if we are already signed-in Firebase with the correct user.
          if (!isUserEqual(response.authResponse, firebaseUser)) {
            // Build Firebase credential with the Facebook auth token.
            const credential = FacebookAuthProvider.credential(
                response.authResponse.accessToken);
    
            // Sign in with the credential from the Facebook user.
            signInWithCredential(auth, credential)
              .catch((error) => {
                // Handle Errors here.
                const errorCode = error.code;
                const errorMessage = error.message;
                // The email of the user's account used.
                const email = error.customData.email;
                // The AuthCredential type that was used.
                const credential = FacebookAuthProvider.credentialFromError(error);
                // ...
              });
          } else {
            // User is already signed-in Firebase with the correct user.
          }
        });
      } else {
        // User is signed-out of Facebook.
        signOut(auth);
      }
    }
    function checkLoginState(response) {
      if (response.authResponse) {
        // User is signed-in Facebook.
        var unsubscribe = firebase.auth().onAuthStateChanged((firebaseUser) => {
          unsubscribe();
          // Check if we are already signed-in Firebase with the correct user.
          if (!isUserEqual(response.authResponse, firebaseUser)) {
            // Build Firebase credential with the Facebook auth token.
            var credential = firebase.auth.FacebookAuthProvider.credential(
                response.authResponse.accessToken);
    
            // Sign in with the credential from the Facebook user.
            firebase.auth().signInWithCredential(credential)
              .catch((error) => {
                // Handle Errors here.
                var errorCode = error.code;
                var errorMessage = error.message;
                // The email of the user's account used.
                var email = error.email;
                // The firebase.auth.AuthCredential type that was used.
                var credential = error.credential;
                // ...
              });
          } else {
            // User is already signed-in Firebase with the correct user.
          }
        });
      } else {
        // User is signed-out of Facebook.
        firebase.auth().signOut();
      }
    }
    Aquí también puedes detectar y resolver errores. Para obtener una lista de códigos de error, consulta los documentos de referencia de autenticación.
  5. También debes verificar que el usuario de Facebook no haya accedido previamente a Firebase, para evitar una nueva autorización innecesaria:
    WebWeb
    import { FacebookAuthProvider } from "firebase/auth";
    
    function isUserEqual(facebookAuthResponse, firebaseUser) {
      if (firebaseUser) {
        const providerData = firebaseUser.providerData;
        for (let i = 0; i < providerData.length; i++) {
          if (providerData[i].providerId === FacebookAuthProvider.PROVIDER_ID &&
              providerData[i].uid === facebookAuthResponse.userID) {
            // We don't need to re-auth the Firebase connection.
            return true;
          }
        }
      }
      return false;
    }
    function isUserEqual(facebookAuthResponse, firebaseUser) {
      if (firebaseUser) {
        var providerData = firebaseUser.providerData;
        for (var i = 0; i < providerData.length; i++) {
          if (providerData[i].providerId === firebase.auth.FacebookAuthProvider.PROVIDER_ID &&
              providerData[i].uid === facebookAuthResponse.userID) {
            // We don't need to re-auth the Firebase connection.
            return true;
          }
        }
      }
      return false;
    }

Para autenticar con Firebase en una aplicación de Node.js:

  1. Inicia la sesión del usuario con su cuenta de Facebook y obtén su token de acceso de Facebook. Por ejemplo, inicia la sesión del usuario en un navegador, como se describe en la sección Administra el flujo de acceso manualmente, pero envía el token de acceso a tu aplicación de Node.js en lugar de usarlo en la app cliente.
  2. Después de obtener el token de ID de Facebook del usuario, úsalo para crear un objeto de credencial y haz que el usuario acceda con la credencial:
    WebWeb
    import { getAuth, signInWithCredential, FacebookAuthProvider } from "firebase/auth";
    
    // Sign in with the credential from the Facebook user.
    const auth = getAuth();
    signInWithCredential(auth, credential)
      .then((result) => {
        // Signed in 
        const credential = FacebookAuthProvider.credentialFromResult(result);
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The AuthCredential type that was used.
        const credential = FacebookAuthProvider.credentialFromError(error);
        // ...
      });
    // Sign in with the credential from the Facebook user.
    firebase.auth().signInWithCredential(credential)
      .then((result) => {
        // Signed in       
        var credential = result.credential;
        // ...
      })
      .catch((error) => {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
        // ...
      });

Autentica con Firebase en una extensión de Chrome

Si desarrollas una app de extensión de Chrome, consulta la guía de Documentos fuera de pantalla.

Cuando crees un proyecto, Firebase le otorgará un subdominio único: https://my-app-12345.firebaseapp.com.

También se usará como mecanismo de redireccionamiento para el acceso con OAuth. Todos los proveedores de OAuth admitidos deberían permitir el dominio. Sin embargo, es probable que los usuarios vean ese dominio cuando accedan a Facebook antes de que se los redireccione a la aplicación (p. ej.: Continúa a https://my-app-12345.firebaseapp.com).

Para evitar que se muestre el subdominio, puedes configurar un dominio personalizado con Firebase Hosting:

  1. Sigue los pasos 1 a 3 de Configura tu dominio para Hosting. Cuando verificas la propiedad de tu dominio, Hosting aprovisiona un certificado SSL para el dominio personalizado.
  2. Agrega tu dominio personalizado a la lista de dominios autorizados en Firebase console: auth.custom.domain.com.
  3. Incluye la URL de la página de redireccionamiento en la lista de entidades permitidas de la consola para desarrolladores de Facebook o en la página de configuración de OAuth. Podrás acceder a ella desde tu dominio personalizado: https://auth.custom.domain.com/__/auth/handler.
  4. Cuando inicialices la biblioteca JavaScript, especifica el dominio personalizado en el campo authDomain:
    var config = {
      apiKey: '...',
      // Changed from 'PROJECT_ID.firebaseapp.com'.
      authDomain: 'auth.custom.domain.com',
      databaseURL: 'https://PROJECT_ID.firebaseio.com',
      projectId: 'PROJECT_ID',
      storageBucket: 'PROJECT_ID.firebasestorage.app',
      messagingSenderId: 'SENDER_ID'
    };
    firebase.initializeApp(config);

Próximos pasos

Cuando un usuario accede por primera vez, se crea una cuenta de usuario nueva y se la vincula con las credenciales (el nombre de usuario y la contraseña, el número de teléfono o la información del proveedor de autenticación) que el usuario utilizó para acceder. Esta cuenta nueva se almacena como parte de tu proyecto de Firebase y se puede usar para identificar a un usuario en todas las apps del proyecto, sin importar cómo acceda.

  • En tus apps, para conocer el estado de autenticación del usuario, te recomendamos configurar un observador en el objeto Auth. Luego podrás obtener la información de perfil básica del usuario a partir del objeto User. Consulta Administra usuarios en Firebase.

  • En tus Reglas de seguridad de Firebase Realtime Database y Cloud Storage, puedes obtener el ID del usuario único que accedió a partir de la variable auth y usarlo para controlar a qué datos podrá acceder.

Para permitir que los usuarios accedan a tu app mediante varios proveedores de autenticación, puedes vincular las credenciales de estos proveedores con una cuenta de usuario existente.

Para salir de la sesión de un usuario, llama a signOut de la siguiente manera:

WebWeb
import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});
firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});