Repository navigation
Feature Request: Cloud Function should support user.sendEmailVerification() like client sdk #46
Description
Activity
Hey there! I couldn't figure out what this issue is about, so I've labeled it for a human to triage. Hang tight.
Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.
The issue/new feature request is that the
user.sendEmailVerification()function is not available on the firebase admin (firebase cloud functions), but it is available in the client sdk like the one used in angular 4.From the Documentation when you create a New user. I added the sendEmailVerification() which this function is not available. But it's a must to allow at this time for the new user to verify their email before we allow access to our apps.
admin.auth().createUser({ email: "user@example.com", emailVerified: false, password: "secretPassword", displayName: "John Doe", photoURL: "http://www.example.com/12345678/photo.png", disabled: false }) .then(function(userRecord) { // See the UserRecord reference doc for the contents of userRecord. console.log("Successfully created new user:", userRecord.uid); // **************************************************************** // Cannot request/call the sendEmailVerification() function, not available // Send Email Verification user.sendEmailVerification() .then(function (emailSent) { console.log('emailSent ', emailSent); }) .catch(function (error) { console.log('emailSent error ', error); }); // End send email verification not available // **************************************************************** }) .catch(function(error) { console.log("Error creating new user:", error); });Please let me know if this explains the issue.
Thanks.Reacted by Pankaj Parkar, Remy Panicker, sur97c, Ruben, hoseyneil and capionoYes, would like this feature in cloud functions. user.sendEmailVerification()
Reacted by Sun, Darren Furr, Jacob Bare, Josh Worden, burhanyldz, larrylegend, Alexey Pronevich, Jorge Barrios, Jon Walsh, Corey Butler and 36 moreThe docs make it seem like its possible to verify a new user's email address with the firebase email validation using a cloud function. Lack of this feature forces developers to use an external service (which requires an upgraded paid plan). Requiring a third party dependency for something Firebase already does well is clunky for developers and confusing.
Reacted by Joe Lowinske, Mark Pieszak, Ruben, Dinarte Jesus, Terry Yuen, MetalMonkey and Lucas FreixieiroHey @coreybutler, the email verification Firebase Auth sends is not a welcome nor a goodbye email (the link you pointed it out). Nor should it be used for that.
You also have the option to send an email verification client side for free. So if you want to send an email verification, you can always do it for free.
Let's keep these issues separate (sending email verifications, vs sending other personalized emails for non-auth specific reasons). We acknowledge the value of sending an email verification, server side via the admin SDK, and we are looking into it.
Reacted by Lays Dragon, MetalMonkey, samasthwafer, fuwapenguin and beevor@bojeil-google - thanks.
Purely for context, my "app" doesn't have a front end. In my case, I'm using a cloud function to serve as a Docker Authentication Proxy... 100% server-side. Users are added directly through the Firebase console.
If this is a separate issue (which is fine), the docs should clarify. Perhaps indicate what limitations exist. A document titled "Extend Firebase Authentication with Cloud Functions" and a subtitle of "Trigger a function on user creation" seems like it would encompass email verification.
Reacted by Andy F and Daniel VilelaHey @coreybutler, to help unblock you, you can always use the client SDK to send the email verification from a Firebase Function. You'd need to require firebase module.
On user creation, you do the following:- get the
uidof the user created from the onCreate trigger. - Using admin SDK, mint custom token via
createCustomTokenfor that user. - Using client SDK,
signInWithCustomTokenusing that custom token. - Send email verification via
currentUser.sendEmailVerification.
Reacted by Jon Walsh, Andriy Gordiychuk, Pankaj Parkar, Jared Potter, ahmedcs95, yzalvov and Dinarte Jesus- get the
+1, for now, I'm sending verification email by hitting the restful api. What a mess..
Reacted by yzalvov, Luis Pais, Nikos, Kirill Pertsev and Kapil JhajhriaBTW, I'm trying to catch examples of sub-optimal Promise usage in the wild and wanted to point out the one in this thread, CC @Sun3 Promise code should almost never repeatedly nest. These aren't callbacks anymore:
admin.auth().createUser({ email: emailAddress, emailVerified: false, password: password, displayName: '', //name, disabled: false }).then(function (user) { // A error representation of the newly created user is returned console.log("Created Firebase User successfully with id: ", user.uid); console.log("user.emailVerified:", user.emailVerified); // Send Email Verification return user.sendEmailVerification(); }).then(function (emailSent) { console.log('emailSent ', emailSent); }).catch(function (error) { console.log('emailSent error ', error); }); // ... Additional code below
This code should hopefully be more readable. It also fixes two bugs:
user.sendEmailVerificaitonwasn't being returned, so the outer promise was resolving early toundefined- Because the
catchblock was on the outer promise, there was no handler for a failure to create the new user (may have been intentional from the error message, but you should always handle rejection.
Reacted by rekodr@bojeil-google While that would work to unblock developers who need this urgently, its an incredibly elaborate workaround once you figure in the need for service account certs for minting custom tokens... in my case where i have multiple environments where i would need to manage certs based on environment, its just a ton of mental overhead. It would be nice if cloud functions didn't need service account certs anyway.
Any word if this feature is being worked on?
Reacted by Joe Lowinske and NikosThe feature is on our list and we acknowledge its importance. We just have a lot of feature requests and many are currently critical to developers and not possible client side or admin side. I would prioritize those higher.
If you are having a hard time minting custom tokens, you can just send the ID token to an HTTP endpoint you host in Firebase Functions and use the REST API to send the email verifications:
https://firebase.google.com/docs/reference/rest/auth/#section-send-email-verificationReacted by Corey Howell, Emerson Jair Reis Oliveira da Silva, Moshe Brevda, Richard William, lalo-clicky, Subrahmanya S M, Mark Pieszak, John Shortland, Hieu Ho and beevor@bojeil-google Thanks a ton!
42 remaining items
A few years ago I did exactly that, I guess that still works but I can confirm it used to work around 3 years ago. (Using the client SDK)
Has anyone who has been waiting all this time tried just using the client SDK from the server side?
Isn't the client sdk rate limited for client use ?
Rate limiting shouldn't be a problem AFAICT.
So you are saying that a public facing lib is not rate limited by IP ?
Doesn't sound very realistic, I'd search the docs but they usually aren't very explicit about these things.I see a ratelimit error in their service definition, but don't know (and probably shouldn't say) what the limit is. Generally even IP ratelimts are set to "reasonable" levels because ISPs in some countries NAT massive numbers of clients to the same IPv4. Either way, the rate limit is guaranteed to be greater than 0, so this is better than waiting for an architecture rewrite.
@inlined , in that case, this should be a better solution #46 (comment), since it shouldn't be rate limited the same way a public facing lib is.
Unless they are using the same underlying endpoints.So, I have #46 (comment) working in local emulators when I manually specify the REST API key (
const apikey = functions.config().project.apikey;).Is there a way in a production environment to get the REST API key? or will I need to manually add that to the functions config via
firebase functions:config:set?The Firebase Config does not include an API key since the Firebase Config is for backend development and the API key is ostensibly to label a client. You can inject it with
functions:config:setthough.+1, we want to see this!
I found a method on the Firebase Auth documentation where you can generate a
email verification link,email password linkoremail link for sign-in.You can also pass a redirect URL (and other info) where you can handle any callbacks once the use clicks on the link.
You just need to send the email yourself.
This is what I have done:
let displayName = 'John Doe' let email = 'to@mail.com' //Generate the email verification link let emailVerificationLink = await admin.auth().generateEmailVerificationLink(email, { url: `SOME_REDIRECT_URL?with=params` }) let mail = JSON.parse(process.env.FIREBASE_CONFIG).mail //construct the email const mailTransport = nodemailer.createTransport({ service: 'gmail', auth: { user: mail.email, pass: mail.password, }, }) const mailOptions = { from: `"${APP_NAME}" <${mail.email}>`, to: email, subject: `Email verification for ${APP_NAME}`, text: `Hello ${displayName})} Please follow this link to verify your email address for the ${APP_NAME} ${emailVerificationLink} Thanks Your ${APP_NAME} team `, html: ` <p>Hello ${displayName}</p> <p>Please follow this link to verify your email address for the ${APP_NAME}</p> <p><a href='${emailVerificationLink}'>Verify Email</a></p> <p>Thanks</p> <p>Your ${APP_NAME} team</p> ` }; try { //send the email await mailTransport.sendMail(mailOptions); } catch(error) { console.error('send email error', error) }
I am using the NodeMailer package for sending the email
Reacted by Emerson Jair Reis Oliveira da Silva, Gala Miteva, MetalMonkey, samasthwafer and Emre Boz7 years later and no feature still?
Reacted by Daniel Vilela, Daniil Moshkov, fuwapenguin, beevor, Madhav Kanna Thenappan and NikosPossible solution is to install the firebase client and initiate the auth with a custom token from the admin sdk and then invoke an email request on that user instance
I really do need this, guess I'll just have to implement the workaround. Any updates on when the solution should come out?
I really do need this, guess I'll just have to implement the workaround. Any updates on when the solution should come out?
something like this can be done:
(doesn't need the client sdk)const admin = require('firebase-admin'); const axios = require('axios'); admin.initializeApp({ credential: admin.credential.applicationDefault(), }); const generateCustomToken = async (uid) => { try { const customToken = await admin.auth().createCustomToken(uid); console.log('Custom Token:', customToken); return customToken; } catch (error) { console.error('Error creating custom token:', error); } }; const authenticateWithCustomToken = async (customToken) => { const url = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${process.env.FIREBASE_API_KEY}`; try { const response = await axios.post(url, { token: customToken, returnSecureToken: true, }); console.log('ID Token:', response.data.idToken); return response.data.idToken; } catch (error) { console.error('Error authenticating with custom token:', error); } }; const sendVerificationEmail = async (idToken) => { const url = `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${process.env.FIREBASE_API_KEY}`; try { const response = await axios.post(url, { requestType: 'VERIFY_EMAIL', idToken: idToken, }); console.log('Verification email sent:', response.data); } catch (error) { console.error('Error sending verification email:', error); } }; // Replace with your user's UID const uid = 'your-user-uid'; generateCustomToken(uid) .then(customToken => authenticateWithCustomToken(customToken)) .then(idToken => sendVerificationEmail(idToken));
When you use sendPasswordResetEmail from the frontend, it's possible to determine whether an email address is registered in the Firebase project. This exposes a security vulnerability. Furthermore, if the email does belong to a registered user, a password reset email is actually sent to that address.
Client-side protections can easily be bypassed, which is why the sendPasswordResetEmail function should ideally be available on the backend, where proper validation and rate limiting can be enforced securely.
This is not merely a feature request. It is a critical necessity.
[Refiling for user @Sun3 from https://github.com/firebase/functions-samples/issues/181]
Feature Request:
The
user.sendEmailVerification()needs to be supported by Firebase Cloud Functions. This is available in client side but not server side. When using Cloud Functions to create new users we also need to automatically send Email Verification before new user can use our apps. This is currently as stopping block for our apps.At this point the
user.sendEmailVerification()gives error that function is not found.Thank you and I am open to any suggestions.