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

Utilizing a router to control a GET request for accessing an image file

Currently utilizing node.js in conjunction with the express framework, I am attempting to initiate a get request for an image by appending it to the body through $('body').append('<img src="images/image.gif?34567">'). Despite rece ...

Configuring babel-loader in webpack for optimal HMR functionality

Recently, I encountered an issue while trying to add Hot Module Replacement (HMR) to my project. Despite the console showing that HMR was enabled and detecting changes in files, the view was not re-rendering. The console would display: [HMR] Updated modul ...

Enhancing the level of abstraction in selectors within Redux using TypeScript

Here is a custom implementation of using Redux with TypeScript and the connect method. import { connect, ConnectedProps } from 'react-redux' interface RootState { isOn: boolean } const mapState = (state: RootState) =&g ...

Elements animated using intersection observer are inconsistently functioning on the current page

My current challenge involves animating elements with the intersection observer, but I am encountering strange behavior with elements that are already on the screen when the page loads. These elements sometimes animate correctly and other times they do no ...

Tips for extracting the most deeply nested object in a JSON file using JavaScript

Is it possible to access the innermost object without knowing the path names? Consider this JSON example: const data = { first: { second: { third: {innerObject} } } ...

Issue: The specific module is unable to be located, specifically on the Heroku platform

While my application performs well locally and on a Travis CI build server, it encounters issues when deployed on Heroku. The error message Error: Cannot find module is displayed, leading to app crashes. Here are some details about the npm module: It r ...

customize Form Modal Bootstrap with AJAX Chained Dropdown for pre-selected options

I am facing an issue with a chained dropdown on a bootstrap modal, Here is the code snippet: function changeDetail(id) { var id = id; $('#edit').prop('hidden', true); $('#modal_form').prop('hidden', fa ...

Tips on displaying an array of elements as a <Dialog> within a <List>

I am currently developing a <ElementList> component that is designed to accept an array of elements through props and create a <List>, with each <ListItem> representing an element in the array. I have also included a separate component ca ...

HeatMap Visualizations Data

I have a HeatMap calendar project () where I am attempting to populate it with dynamic data. My approach involves extracting various dates from a file and converting them into milliseconds in order to create the necessary key-value pair for the calendar. ...

rxjs iterates through an array executing each item in sequential order

Is there a way to make observables wait until the previous one has completed when they are created from an array? Any help is appreciated! export class AppComponent{ arr: number[] = [5, 4, 1, 2, 3]; fetchWithObs() { from(this.arr) ...

The issue of gallery image loading with the galleryView jQuery plugin is causing problems

Hi fellow developers, I could really use some assistance. I've been working on implementing the jquery galleryview plugin for my image gallery (check out my gallery here). Unfortunately, I'm running into an issue where the gallery is not loading ...

retrieve JSON object from deferred response of AJAX request

After utilizing Ajax to send an item to a SharePoint list, I aim to incorporate the jsonObject received in response into a list of items. Located in AppController.js $scope.addListItem = function(listItem){ $.when(SharePointJSOMService.addListIte ...

Utilizing Fullcalendar Qtip to display information on mouseover rather than utilizing the eventRender

I have a challenge with integrating Qtip to the eventMousever event instead of the eventRender event in fullcalendar. The main reason for this adjustment is due to the server hosting the data being located in another country, resulting in significant late ...

jQuery's Offset().left is experiencing some issues and not functioning correctly

Do you have a question about the jQuery offset() function? On my website, I utilize it to show an "email a friend" window when the email icon is clicked. However, the problem is that the window ends up stuck to the right side of the browser's window ...

Understanding the Functioning of a Digital Analog Clock Using JavaScript

As a new learner, I found the operation of a Digital analog clock to be quite puzzling. I was presented with an image called clock.png, and I specifically struggled with how the hands of the clock function. Javascript - const deg = 6; // defining the valu ...

What is the reason for Vue.js failing to refresh the DOM when utilizing the datepicker feature with Moment.js

Currently, I am working on a basic datepicker control in vue.js, utilizing moment.js for managing the date formatting and manipulation. The issue that I'm encountering is that despite modifying the date instance within the component upon clicking eit ...

How can I store a value or text to track view counts or a counter efficiently?

Recently, I've been trying to implement a view counter on my website, similar to what you see on YouTube. Currently, the number of views stands at 23. I managed to find some code that allows me to increment the view count every time I click on an imag ...

Manipulating a React table: Customizing a row in the table

Below is the code snippet: const [data, setData] = useState([ {id: 1, name: 'paper', qty: 10}, {id: 2, name: 'bottle', qty: 10}, ]); const [isEditable, setEditable] = useState([]); useEffect(()=>{ data.map(each=>{ ...

What is the best way to activate a JQ function with my submit button?

Is there a way to trigger a JQ function when clicking the submit button in a form? I managed to make Dreamweaver initiate an entire JS file, but not a particular function. ...

Display Partial View in MVC 4 using ajax success callback

Issue: Unable to load view on ajax success. Situation: I have two cascaded dropdowns where the second dropdown's options are based on the selection of the first dropdown. Upon selecting an option in the second dropdown, I want to display a list of re ...