Firebase CLI: execute arbitrary Firebase Authentication requests to Firebase Emulator - firebase

Using the Firebase CLI, I'm executing arbitrary JavaScript that's stored in a file. In that script, I'm trying to make calls to admin.auth().something(), but it doesn't work against the Firebase Emulator. This is in contrast to making calls to Firestore, which works perfectly fine with the Emulator.
Firestore (everything works)
GCP
This makes calls to Firestore on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
const db = admin.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Emulator
This also succeeds:
const admin = require('#firebase/testing');
const db = admin
.initializeAdminApp({ projectId: 'my-project' })
.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Firebase Auth (GCP works but Emulator does not)
GCP
This makes calls to Firebase Auth on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
(async () => {
const user = await admin
.auth()
.getUser('user123456789');
console.log(user.email);
})();
Emulator
This fails:
const admin = require('#firebase/testing');
const auth = admin
.initializeAdminApp({ projectId: 'my-project' })
.auth();
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();
The error message is:
C:\Users\...\node_modules\#firebase\testing\node_modules\#firebase\component\dist\index.cjs.js:134
throw e;
^
[t [Error]: Your API key is invalid, please check you have copied it correctly.] {
code: 'auth/invalid-api-key',
a: null
}
I'm not sure what API key they're referring to, as the request is against the Emulator. How can I execute Firebase Auth requests against the Emulator using Firebase CLI?

To send requests against Firebase Emulator Auth, set the following environment variables and use the standard Firebase Admin SDK (firebase-admin) instead of using #firebase/testing:
process.env.FIREBASE_AUTH_EMULATOR_HOST = 'localhost:9099';
process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080';
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'emulator projectId' });
Now this works:
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();

Related

Testing Firebase Cloud Functions: Using admin SDK with jest

What is the best way to use the Firebase admin SDK in jest script to get Firestore information?
I am unable to use the admin SDK in my jest scripts. Running admin.firestore() throws:
Total timeout of API google.firestore.v1.Firestore exceeded 600000 milliseconds before any response was received.
My code:
let issueRefundWix: HttpsCallable<unknown, unknown>,
initApp = async () => {
const serAcc: ServiceAccount = await import(GOOGLE_APPLICATION_CREDENTIALS);
const app = initializeApp(firebaseConfig);
const functions = getFunctions(app, "us-central1");
const db = getFirestore(app);
const auth = getAuth(app);
admin.initializeApp({
credential: admin.credential.cert(serAcc),
storageBucket: "gs://**.appspot.com/",
});
return {
app: app,
functions: functions,
db: db,
auth: auth,
};
};
beforeAll(async () => {
const app = await initApp();
const functions = app.functions;
issueRefundWix = httpsCallable(functions, "issueRefundWix");
db = admin.firestore();
uid = await createWixUser();
exampleSubscription.wixId = uid;
console.log("Finished beforeAll()");
});
This set up works fine when I am running tests on the Firebase Emulator. Can I test functions the same on the emulator as when they are deployed? All tests work fine if I remove any dependencies on admin.firestore().
What is the best way to use the admin SDK to query firestore in jest tests?
Thank you

using Cloud Firestore in cloud function

Cloud Function Documentation says
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
I am using Cloud Firestore, not Realtime Database. How do I access it?
Use admin.firestore() like for example:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = requi re('firebase-functions');
// The Firebase Admin SDK
const admin = require('firebase-admin');
admin.initializeApp();
//Write a function that uses Firestore, e.g.:
exports.anHttpCloudFunction = functions.https.onRequest((req, res) => {
admin.firestore().collection('XYZ').doc('ABC').set(....)
.then(() => {
res.send({ msg: 'Success' });
})
.catch(err => {....})
});

Accessing Firebase Firestore on AWS Lambda

I have following problem
I am writing a lambda function which is gets a post value offer an API, than checks in firebase firestore if the value is there and than replies to the client. Simple.
This is my code:
const serverless = require("serverless-http")
const express = require("express")
const app = express()
const bodyParser = require("body-parser")
const cors = require("cors")
const admin = require("firebase-admin")
var login = require("./test.json")
admin.initializeApp({ credential: admin.credential.cert(login) })
const db = admin.firestore()
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.post("/", function(req, res) {
let result = req.body.code.toUpperCase()
db.collection("voucher")
.get()
.then(x => {
console.log("TEST")
console.log(x)
})
.catch(err => res.status(400).send({ err }))
})
module.exports.voucher = serverless(app)
The API works just fine, problem is connecting to the firestore, the error object I get always says:
{code: "MODULE_NOT_FOUND"}
I did it how it is shown in the tutorial here:
https://firebase.google.com/docs/firestore/quickstart
But it does not seem to work at all.
I downloaded the correct credentials, actually I gave myself admin access to everything. But still it does not work.
You guys have any suggestions?

Cloud Storage API doesn't work when deploy on Google Cloud Functions using Firebase

This work perfectly in local serve with firebase :
const gCloudConfig = {
projectId: 'XXXX-X1234',
keyFilename: './key.json'
}
const Storage = require('#google-cloud/storage')(gCloudConfig);
const storageBucket = Storage.bucket(bucketUrl);
storageBucket.upload(file.path, {destination: file.name})
.then(() => {
//
});
But this doesn't work when i deploy to firebase :
const Storage = require('#google-cloud/storage')();
const storageBucket = Storage.bucket(bucketUrl);
storageBucket.upload(file.path, {destination: file.name})
.then(() => {
//
});
I put this line after the admin.initializeApp(...), since i saw that it fixed the problem for someone, but it still doesn't work.
I've tried a lot of stuff :
const gCloudConfig = { projectId: 'XXXX-X1234' };
const gCloudConfig = { key: API_KEY };
const gCloudConfig = { key: API_KEY, projectId: 'XXXX-X1234' };
const gCloudConfig = functions.config().firebase;
I'm kinda lost, please help me !
It's easier if you just initialize the Firebase Admin SDK with its default credentials, then access the Cloud Storage APIs via that. There's no need to initialize Storage on its own.
const admin = require('firebase-admin')
admin.initializeApp()
const bucket = admin.storage().bucket()
bucket.upload(localPath, {
destination: remotePath
})
Here, bucket is your project default storage bucket, just like you would have gotten it from the Cloud Storage API.
Note that the no-argument init of the Admin SDK is available when using firebase-functions#1.0.0 or later (current 1.0.2).

firebase cloud functions failed to access google sheet api

I want to build an api service that use google sheet api to create, read and write the spreadsheets. The api service is deployed on firebase cloud functions with express.js, I have created the service account, and use JWT for authentication. The api works (i.e. can create, read and write spreadsheets) when test locally, but fails when I deployed to firebase cloud functions.
const functions = require('firebase-functions');
// firebase admin
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// google sheet api
const google = require('googleapis');
const key = require('./key/serviceKey.json');
const scopes = [
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive'
];
const authClient = new google.auth.JWT(
key.client_email, null, key.private_key, scopes, null
);
authClient.authorize((err, tokens) => {
if (err) {
console.log('error occurred when authorising with JWT');
} else {
console.log('auth success, tokens', tokens);
google.options({ auth: authClient });
}
});
const drive = google.drive('v2');
const sheets = google.sheets('v4');
The error message I get when I test it on firebase cloud functions:
Request is missing required authentication credential. Expected OAuth
2 access token, login cookie or other valid authentication credential.
Ultimately, I will have an ionic app that calls the api to perform certain actions (e.g. create and share spreadsheets with other user). So am I doing the right approach or I should use other types of authentication?
My function definitions:
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')({ origin: true });
const bodyParser = require('body-parser');
const app = express();
app.use(cors);
app.use(bodyParser.json({ type: 'application/json' }));
// some routing setup
exports.api = functions.https.onRequest(app);
Router setup:
const express = require('express');
const router = express.Router();
router.post('/createSheets', (req, res) => {
const request = { // }
sheets.spreadsheets.create(request, (err, sheetsResponse) => {
// some code
}
});

Resources