If I change the request mode to 'no-cors' in my Firebase cloud function, how will it impact the outcome?

After encountering an issue with the Firebase inbuilt password reset functionality, I created a Firebase function to handle OTP verification and password changes based on the correctness of the OTP. The function is designed to validate the OTP provided, check if it matches the stored OTP in Firestore, retrieve the corresponding user's email address, and then update the user's password. Below is the code snippet of the function:

exports.resetPassword = functions.https.onCall((data, context) => {
    return new Promise((resolve, reject) => {
        // Function logic here
    })
})

Despite observing execution logs in the console, when trying to run the function, I encountered the following client-side error message:

Access to fetch at 'https://us-central1-project-name.cloudfunctions.net/functionName' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

and 

{"code":"internal"}

I'm now seeking advice on resolving this CORS (Cross-Origin Resource Sharing) issue that seems to be causing problems with the API call.


Part 2 (unrelated inquiry)

In lines 11 and 12 of my function, I'm using

admin.auth().getUserByEmail(data.email).then(user => {
  admin.auth().updateUser(user.uid, {password: data.password})
})

Could you please verify if this code snippet correctly handles updating user passwords?


To seek solutions for the CORS problem, I consulted this thread on Stack Overflow, but unfortunately, it lacked any actionable answers.

Answer №1

Take a look at the documentation for Callable Cloud Functions:

  1. No need to wrap it in
    return new Promise((resolve, reject) => {})
    ;
  2. Data returned should be JSON encoded;
  3. Error management is crucial, make sure to throw (or return a Promise rejected with) an instance of functions.https.HttpsError when necessary;
  4. All promises from asynchronous methods must be properly chained.

I've attempted to organize your code based on these points, but due to the complexity of your business logic, I wasn't able to test it thoroughly. There might be other approaches to handle all cases effectively. Feel free to refine this initial attempt! Hopefully, it provides some guidance.

exports.resetPassword = functions.https.onCall((data, context) => {

        if(data.sesId && data.otp){

            let dataOptCorresponds = true;

            return admin.firestore().collection('verification').doc(data.sesId).get()
            .then(verSnp => {
                if(verSnp.data().attempt != 'verified'){

                    var now = new Date().getTime()

                    if(verSnp.data().expiring > now){
                        if(data.email == verSnp.data().email){
                            if(verSnp.data().attempt > 0){
                                if(data.otp == verSnp.data().otp){
                                    return admin.auth().getUserByEmail(data.email);
                                } else {
                                    dataOptCorresponds = false;
                                    var redAttempt = verSnp.data().attempt - 1
                                    return admin.firestore().collection('verification').doc(data.sesId).update({
                                        attempt: redAttempt
                                    })
                                }
                            } else {
                                throw new Error('Incorrect OTP. You have exhausted your attempts. Please request a new OTP.')
                            }
                        } else {
                            throw new Error('Incorrect email. How did you get here?')
                        }
                    } else {
                        throw new Error('OTP is expired. Please request a new OTP.')
                    }
                } else {
                    throw new Error('OTP is invalid. Please request a new OTP.')
                }
            })
            .then(user => {
                if(dataOptCorresponds) {
                    return admin.auth().updateUser(user.uid,{
                        password: data.password
                    })
                } else {
                    throw new Error(`Incorrect OTP. You have xxxx attempts remaining.`)
                }
            })
            .then(() => {
                return admin.firestore().collection('verification').doc(data.sesId).update({
                    attempt: 'verified'
                })
            .then(() => {
                return {result: "success"}                      
            })          
            .catch(error => {
                throw new functions.https.HttpsError('internal', error.message);

            })

        } else {

            throw new functions.https.HttpsError('invalid-argument', 'Enter OTP');
        }

})

UPDATE following Bergi's comment below:

If you want to distinguish between different types of errors sent back to the front-end (such as returning an invalid-argument HttpsError for incorrect, expired, or invalid OTPs and emails), you can utilize a second argument in the then() method.

exports.resetPassword = functions.https.onCall((data, context) => {

        if(data.sesId && data.otp){

            let dataOptCorresponds = true;

            return admin.firestore().collection('verification').doc(data.sesId).get()
            .then(

                verSnp => {
                    if(verSnp.data().attempt != 'verified'){

                        var now = new Date().getTime()

                        if(verSnp.data().expiring > now){
                            if(data.email == verSnp.data().email){
                                if(verSnp.data().attempt > 0){
                                    if(data.otp == verSnp.data().otp){
                                        return admin.auth().getUserByEmail(data.email);
                                    } else {
                                        dataOptCorresponds = false;
                                        var redAttempt = verSnp.data().attempt - 1
                                        return admin.firestore().collection('verification').doc(data.sesId).update({
                                            attempt: redAttempt
                                        })
                                    }
                                } else {
                                    throw new Error('Incorrect OTP. You have exhausted your attempts. Please request a new OTP.')
                                }
                            } else {
                                throw new Error('Incorrect email. How did you get here?')
                            }
                        } else {
                            throw new Error('OTP is expired. Please request a new OTP.')
                        }
                    } else {
                        throw new Error('OTP is invalid. Please request a new OTP.')
                    }
                },

                error => {

                    throw new functions.https.HttpsError('invalid-argument', error.message);

                }

            )
            .then(user => {
                if(dataOptCorresponds) {
                    return admin.auth().updateUser(user.uid,{
                        password: data.password
                    })
                } else {
                    throw new Error(`Incorrect OTP. You have xxxx attempts remaining.`)
                }
            })
            .then(() => {
                return admin.firestore().collection('verification').doc(data.sesId).update({
                    attempt: 'verified'
                })
            .then(() => {
                return {result: "success"}                      
            })          
            .catch(error => {
                throw new functions.https.HttpsError('internal', error.message);

            })

        } else {

            throw new functions.https.HttpsError('invalid-argument', 'Enter OTP');
        }

})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In Next.js, the elements inside the div created by glider-js are not properly loaded

I'm currently working on setting up a carousel in nextjs using the data retrieved from an API and utilizing glider-js for this purpose. However, I'm facing an issue where the div created by glinder-js does not include the elements that are render ...

Is it unwise to rely on Sequelize for validating objects that are not stored in a database?

Currently, I am utilizing Sequelize as my ORM and find the powerful built-in model validation to be quite impressive. I am contemplating leveraging Sequelize as a schema validator in specific scenarios where there would not be any actual database writes. E ...

The reference to the Material UI component is not functioning

I am currently working on a chat application and have implemented Material UI TextField for user message input. However, I am facing an issue with referencing it. After researching, I found out that Material UI does not support refs. Despite this limitatio ...

Retrieve webpage using HTML stored in web storage

I am exploring a new idea for an application that utilizes local storage, and I am seeking guidance on the most effective way to load content after it has been stored. The basic concept of the app involves pre-fetching content, storing it locally, and the ...

Maintain checkbox state through page reloads using ajax

Currently, I am troubleshooting a script that is intended to keep checkbox values checked even after the page is reloaded or refreshed. The code snippet below was implemented for this purpose, but unfortunately, it doesn't seem to be functioning corre ...

What is the best way to have a text field automatically insert a hyphen after specific numbers?

Is there a way to make a text field insert hyphens automatically after certain numbers? For example, when typing a date like 20120212, could we have the input automatically formatted with hyphens after the first 4 digits and the second two, so it displays ...

Guide to adding a line break following each set of 200 characters utilizing jQuery

I have a text input field where I need to enter some data. My requirement is to automatically add a line break after every 200 characters using JavaScript or jQuery. For example: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ...

Convert a JSON array into a new format

Here is the JSON data input provided: "rows": [ [ 1, "GESTORE_PRATICHE", 1, "GESTORE PRATICHE", "canViewFolderManagement" ], [ 2, "ADM ...

Every character entered in JSP should trigger an instant retrieval of the corresponding string in the servlet

Having a JSP file that contains a text field: <form action="someServlet" method=post> <input type ="text" name="user" id="uname"> <button type="submit" id="submit">Submit</button> </form> When typing each letter in the JSP, ...

Is there a way to continuously send out this ajax request?

My attempt to use setInterval for sending an AJAX request every 2 seconds is causing the page to crash. It seems like there is something wrong in my code! Check out the code below: var fburl = "http://graph.facebook.com/http://xzenweb.co.uk?callback=?" ...

Strategies for dynamically altering Vue component props using JavaScript

for instance: <body> <div id="app"> <ro-weview id="wv" src="http://google.com"></ro-weview> </div> <script> (function () { Vue.component("ro-webview", { props: ["src"], template: ` <input type="t ...

Creating new components within A-frame

I've been attempting to implement the bubble function into my scene to generate a sphere, but unfortunately nothing is showing up. Even when I try creating a sphere without using the bubble function, it still doesn't appear in the scene. func ...

Issues with websockets functionality have been reported specifically in Firefox when trying to connect to multiple

I am currently working on a websocket client-server application. The client code is as follows: const HOST = "wss://localhost:8000"; const SUB_PROTOCOL= "sub-protocol"; var websocket = new WebSocket(HOST, SUB_PROTOCOL); websocket.onopen = function(ev ...

What could be preventing me from exporting and applying my custom JavaScript styles?

This is my primary class import React, { Component } from 'react'; import { withStyles } from '@material-ui/core/styles'; import styles from './FoodStyles'; class Food extends Component { render () { return ( & ...

"Troubleshooting a problem with Mongoose's findOne.populate method

There is an array of user IDs stored in the currentUser.follow property. Each user has posts with a referenceId from the PostSchema. I am trying to populate each user's posts and store them in an array called userArray. However, due to a scope issue, ...

"Is there a way to retrieve the CSS of all elements on a webpage by providing a URL using

Currently, I am in the process of creating a script that can crawl through all links provided with a site's URL and verify if the font used on each page is helvetica. Below is the code snippet I have put together (partially obtained online). var requ ...

in node.js, virtual machine scripts can import modules using the require function

I am currently developing a command-line interface using node.js that runs an external script > myapp build "path/to/script.js" myapp is a node.js application that executes the script provided as a command-line argument. In simple terms, it performs ...

Unable to transfer an array from getStaticProps method in Next.js

Whenever I pass a JSON array from getStaticProps in Next.js, I encounter this specific error message when trying to access it. TypeError: Cannot read property 'contentBody' of undefined module.exports../pages/[author]/[article].js.__webpack_expo ...

Issues persist with Ajax form submissions; the submitted data never seems to go through

I have encountered variations of this issue multiple times, but despite analyzing numerous examples, I am unable to determine why my code is not functioning properly. <script> $('document').ready(function(){ $('datafixForm' ...

When React object state remains unchanged, the page does not update automatically

i have a state object with checkboxes: const [checkboxarray_final, setCheckboxarray_final] = useState({ 2: ",4,,5,", 9: ",1,", }); i'm working on enabling check/uncheck functionality for multiple checkboxes: these are ...