firebasegoogle-cloud-platformfirebase-authenticationgoogle-identity-toolkit

Firebase Auth - Passing REST response to JS SDK to log user in


I wanted to check if there is a way to obtain user login info from the REST API first, then hand that result over to the Firebase JS SDK as if I used the SDK method to sign the user in?

Using the REST API here on Google Cloud docs, which is the same as the Firebase REST documentation here. I will get a JSON when successful looking like this:

{ "idToken": string, "email": string, ... }

But in the JS SDK (v9), the flow looks like this, which returns a UserCredential promise:

 signInWithEmailLink(auth, email, window.location.href)
    .then((result) => {
      window.localStorage.removeItem('emailForSignIn');
      console.log(result.user)
    })

So if I used the REST API and get a JSON, how do I then let the SDK know this is the signed in user? So that I could use methods like this?

const auth = getAuth();
const user = auth.currentUser;

The reason why I'm doing this is on top of the Auth system, I'm implementing a cross-device email link sign in feature, so the email link sent is not Firebase Auth's generated one, but a link to a point on my own server, which will sign the user in on the server side, and then pass this result back to the initiating client.


Solution

  • I think you are trying to log in user on the same device where they entered their email instead of the device where they open the sign in link sent by Firebase. In that case, you must authenticate the users yourself and then log them in using Firebase SDK.

    The authentication flow will be like:

    1. User enters their email and your server sends a custom link to their email containing some kind of identifier.
    2. User clicks on that link and sends a response to server that user has been verified.
    3. You generate a custom token using Firebase Admin SDK and send it back to the device where user started the login/signup process.
    4. Then you use Firebase Client SDK to log them in using the custom token.

    I'm not sure how you respond to the first device after the link has been clicked but I've written this feature with socket.io and it works perfectly and fast. (Although you need to store the socket ID somewhere so you emit to correct one). However this should not be a concern as long as you are able to notify the user.

    // After user has clicked the link
    const uid = 'some-uid';
    
    admin
      .auth()
      .createCustomToken(uid)
      .then((customToken) => {
        // Send token back to client (original device)
      })
      .catch((error) => {
        console.log('Error creating custom token:', error);
      });
    

    Once the token is sent back to the user, you can use Javascript SDK instead of REST API to log them in.

    firebase.auth().signInWithCustomToken(token)
      .then((userCredential) => {
        // Signed in
        var user = userCredential.user;
        // ...
      })
    

    Just make sure you are authenticating the user correctly as there's no Firebase involved there as you generate your custom links and you are sending back the token to right client.