1

I am pretty new in Angular and Firebase and I am finding a strange behavior related to CORS trying to call a Firebase Cloud Function from a service defined into my Angular application.

Basically I have this component class:

import { Component, OnInit } from '@angular/core';
import {PickListModule} from 'primeng/picklist';
import { PeopleService } from 'src/app/service/PeopleService';

@Component({
  selector: 'app-user-manager',
  templateUrl: './user-manager.component.html',
  styleUrls: ['./user-manager.component.scss']
})
export class UserManagerComponent implements OnInit {

  //sourceProducts: any[];
  //targetProducts: any[];

  sourceUsers: any[];
  targetUsers: any[];

  constructor(private peopleService: PeopleService) { }

    ngOnInit() {
        //this.sourceProducts = ["USER-1", "USER-2", "USER-3"];
        //this.targetProducts = [];

        let users: any[];

        this.peopleService.getAllUsersFromFirebaseAuth().subscribe(
          data => {
            users = data;
            console.log("USERS LIST RETRIEVED FROM Angular Fire Auth: ", users);
            this.sourceUsers = users;
          }
        );

        this.sourceUsers = []
        this.targetUsers = []
    }
}

As you can see into the ngOnInit() method it is subscribing on the getAllUsersFromFirebaseAuth() method of my service class.

The code of this method is:

getAllUsersFromFirebaseAuth(): Observable<any[]> {
  return this.http.get<any> ('https://MY-FIREBASE-PROJECT.cloudfunctions.net/getAllUsersOnFirebaseAuthentication');
}

That call an API defined into this Cloude Storage Function:

  export const getAllUsersOnFirebaseAuthentication = functions.https.onRequest((req, res) => {
    admin.initializeApp();
    const auth = admin.auth();

    const maxResults = 10; // optional arg.

    let usersList: any = [];
    let usersListJsonObj: any = {};


    auth.listUsers(maxResults).then((userRecords) => {
      userRecords.users.forEach((user) => {
        console.log(user.toJSON());
        usersList.push(user.toJSON());
      });

      usersListJsonObj["users_list"] = usersList;

      res.set('Access-Control-Allow-Origin', '*');
      res.status(200).json(usersListJsonObj);
    }).catch((error) => console.log(error));

  });

As you can see in this function, in theory, I enabled the CORS access by:

res.set('Access-Control-Allow-Origin', '*');

but now something strange it happening when the call is executed by my service.

If I am in debug mode and I put a breakpoint into the service arrow function subscription, here:

    this.peopleService.getAllUsersFromFirebaseAuth().subscribe(
      data => {
        users = data;
        console.log("USERS LIST RETRIEVED FROM Angular Fire Auth: ", users);
        this.sourceUsers = users;
      }
    );

the data seems correctly retrieved, infact tine this.sourceUsers list contains an array of 2 objects (as expected).

But performing it without debug mode (simply accessing to the page) in the Chrome console I obtain the following errors messages that seems related to CORS:

  • Access to XMLHttpRequest at 'https://MY-PROJECT-NAME/getAllUsersOnFirebaseAuthentication' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. us-central1-color-patch.cloudfunctions.net/getAllUsersOnFirebaseAuthentication:1
  • Failed to load resource: net::ERR_FAILED vendor.js:28282
  • ERROR HttpErrorResponse defaultErrorLogger @ vendor.js:28282

How is it possible that in debug mode, putting a break point into my subscribe I can obtain data from my Firebase Cloud Function API printing the output in the console but I obtain this error accessing at the same page without using debugger?

What is wrong? What am I missing? How can I try to solve this issue?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
AndreaNobili
  • 40,955
  • 107
  • 324
  • 596

2 Answers2

2

The issue looks to be inside your getAllUsersOnFirebaseAuthentication Cloud Functions code.

export const getAllUsersOnFirebaseAuthentication = functions.https.onRequest((req, res) => {
    admin.initializeApp();
    const auth = admin.auth();

    const maxResults = 10; // optional arg.

    let usersList: any = [];
    let usersListJsonObj: any = {};


    auth.listUsers(maxResults).then((userRecords) => {
      userRecords.users.forEach((user) => {
        console.log(user.toJSON());
        usersList.push(user.toJSON());
      });

      usersListJsonObj["users_list"] = usersList;

      res.set('Access-Control-Allow-Origin', '*');
      res.status(200).json(usersListJsonObj);
    }).catch((error) => console.log(error));

  });

I suggest to run admin.initializeApp(); globally by moving it outside the cloud functions body.

MisaelSab
  • 218
  • 2
  • 7
0

There was a similar Q&A on Stack a while back:

firebase cloud function CORS error with axios request

I made a angular app with async calls. I resolved my cors error through angularfire/cloud functions after seeing that headers and methods were needed. Hope this might help.

Index.js

````
const cors = require('cors');

exports.YourPropertyInputHere = functions.https.onRequest(async (req, 
res) => {
res.set('Access-Control-Allow-Origin', '*')
res.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,DELETE,PUT')
res.set('Access-Control-Allow-Headers', 'Content-Type')