简体   繁体   中英

Generate undo email change link in firebase cloud functions

How can I generate a link to undo the email change in firebase cloud functions?

So when a user changes their email address, I want to generate a link to include in an automated email for them to click to undo this email change. Firebase sends an email when an email changes, but I want to be able to do that myself with my own code.

Currently, I can find that there are ways you can generate a link to change the user password, verify email, etc. However, I cannot find a method that I can use to generate a link to undo email change when the user changes their email.

When writing Cloud Functions for Firebase, one uses the Admin Node.js SDK.

AFAIK it is not possible, with this Admin SDK, to generate an email action link to undo an email change, as we can we can do, for example, for email verification with the generateEmailVerificationLink() method.

You will need to build your own mechanism yourself. You'll probably have to save somewhere (eg in Firestore) the previous email and expose an HTTP endpoint to trigger the action (HTTPS Cloud Function? Call to the Firestore REST API?). In any case you'll have to check the identity of the calling user (by either checking the Firebase ID token as a Bearer token in the Authorization header of the HTTP request or via a dedicated Firestore Security Rule).

There isn't enough details in your question to understand the exact flow of your complete use case (ie from the request to change email up to the action of undoing an effective change) and propose a sensible approach.

When a user changes the email, you can store a document in Firestore containing their old email, a token and some metadata if you need to. That being said, you should update user's email from a Cloud function or your server using the Admin SDK only as there are no triggers on E-Mail change.

import jwt from "jsonwebtoken"
import {v4} from "uuid"

exports.changeEmail = functions.https.onCall(async (data, context) => {
  const {newEmail} = data;
  const {uid} = context.auth;

  // change user's email
  // send an email to verify new email is required

  // generate a JWT
  const token = jwt.sign({ uid, eventId: v4() }, 'jwt_signing_secret', { expiresIn: '24h' });
  
  // add a document in Firestore containing details about this event
  await admin.firestore().collection("emailChanges").doc(eventId).set({
    uid, changedAt: Date.now()
  })

  const undoURL = `https://[YOUR_DOMAIN]/revert-email-change?token=${token}`

  // E-Mail this URL to user
  // Terminate this function
})

Replace [YOUR_DOMAIN] will the URL of your website. Once the user visits /revert-change-email email page of your website, call another function that verifies this token.

exports.revertEmailChange = functions.https.onCall((data, context) => {
  // pass the token from frontend by checking URL params
  const {token} = data

  // Verify the token
  const decoded = jwt.verify(token, 'jwt_signing_secret');
  console.log(decoded)
  const {uid, eventId} = decoded
  
  // token is valid 
  // read the Firestore document using stateId and check old email
  const snap = await admin.firestore().collection("emailChanges").doc(eventId).get()
  if (!snap.exists) return {error: "Invalid Token"}
  const {email} = snap.data()

  // use updateUser() method to change email back
  // delete that document from Firestore
  return {data: "Email changed back successfully"}
});

You can change the lifespan of JWT token ie how long the URL should be valid. You can read more about JWT at jwt.io . The additional eventId token is just to prevent that JWT token so it cannot be reused.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM