firebase admin node, insufficient permissions - node.js

I've checked the other stacks about this but still not sure why i'm getting insufficient permissions error. Probably I'm being insecure.
I'm trying to sync users from 2 different firebase accounts. The first account calls a firebase function on the second account. If a user does not exist, it creates and does some databasing. If user exists, then it creates a custom token and passes it back to the first account to use in an iframe query parameter.
I've created IAM service account, created keys and saved to file, and edited the service token permissions like the other stacks explain but i'm getting the error nonetheless. Here's my function start:
const firebaseConfig = {
credential: admin.credential.applicationDefault(),
apiKey: "xxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "itsli7-87384.firebaseapp.com",
databaseURL: "https://itsli7-87384.firebaseio.com",
projectId: "itsli7-87384",
storageBucket: "itsli7-87384.appspot.com",
messagingSenderId: "503897448704",
appId: "1:503897448704:web:45773bfb231a24bbe213e5"
}
fb.initializeApp(firebaseConfig);
admin.initializeApp(firebaseConfig);
And the function is running this.
return admin.auth().getUser(data.user.uid)
.then(async function () {
return admin.auth().createCustomToken(data.user.uid)
.then(function (customToken) {
res.send(customToken);
})
.catch(function (error) {
console.log('Error creating custom token:', error);
});
The error
code: auth/insufficient-permission
Error creating custom token: FirebaseAuthError: The caller does not
have permission; Please refer to
https://firebase.google.com/docs/auth/admin/create-custom-tokens for
more details on how to use and troubleshoot this feature.

Instead of using the prescribed method of adding cred.json to admin.credential.applicationDefault(), and passing in the same firebase init config object to admin init, it is working with:
var serviceAccount = JSON.parse(fs.readFileSync("cred.json"));
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://itsli7-87384.firebaseio.com"
});
fb.initializeApp(firebaseConfig);

Related

How to manage tenants programatically in Google Cloud Platform

I am writing a backend service to manage my tenants in gcp. Specifically, I’d like to be able to create/delete and list tenants, on my node server.
The Firebase admin-sdk should enable me to do so. When I try to run it I get this error:
Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Error fetching access token: Error while making request: getaddrinfo ENOTFOUND metadata.google.internal. Error code: ENOTFOUND".
I followed this documentation to set up install the admin sdk. (tried windows and linux, using an environment variable)
I used this documentation (Getting an existing tenant)
This is my code:
var admin = require('firebase-admin');
var app = admin.initializeApp({
credential: admin.credential.applicationDefault(),
projectId: 'myProject'
});
admin.auth().tenantManager().getTenant("myTenant")
.then((tenant) => {
console.log(tenant.toJSON());
})
.catch((error) => {
// Handle error.
console.log(error.message)
});
const someOtherStuff = () =>...
module.exports = {
someOtherStuff
}
Edit: I am running this code locally on a node server with Express. I am using a Windows computer and a Linux computer. The result is the same on both systems.
I was able to work around the problem by changing the initialization. Instead of using environment variables, I used the service account key file directly, as described here
Some sample code of how I use it:
var admin = require('firebase-admin');
var {getAuth} = require('firebase-admin/auth');
var serviceAccount = require('/path/to/serviceAccountKey.json');
// Initialize the default app using seriveAccount instead of environment variables
var app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const createTenant = async (tenantName) => getAuth(app).tenantManager().createTenant({
displayName: tenantName,
emailSignInConfig: {
enabled: true,
passwordRequired: true, // Email link sign-in enabled.
}
}).then((createdTenant) => {
return createdTenant.toJSON();
}).catch((error) => {
console.log("tenant could not be created. " + error.message);
});
//some other stuff...
module.exports = {
createTenant,
someOtherStuff,
}

DB.collection is not a function in firebase?

I am trying to connect to firebase realtime database (not firestore) but I get the error that db.collection is not a function. Other answers in StackOverflow are mentioned with respect to Firestore. Thanks for your help.
const admin = require('firebase-admin');
// Firebase configuration - this should not be public.
// Please use your own config if you intend to use this code.
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxxxx",
}
// Initialize Firebase
admin.initializeApp(firebaseConfig)
const db = admin.database();
console.log("Database setup");
(async () => {
try {
let query = db.collection('users');
console.log("Doing database query now");
await query.get().then(querySnapshot => {
console.log(querySnapshot);
});
} catch (error) {
console.log(error);
}
})();
const db = admin.database() is an instance of Firebase realtime database and not Firestore. To get an instance of Firestore, use admin.firestore().
const admin = require('firebase-admin');
admin.initializeApp(/* service account */)
const db = admin.firestore();
console.log("Firestore setup");
Admin SDK uses a service account and not the same public credentials. You can refer to the documentation for detailed information. You can get a service account from project settings.
Do note that if you are using Cloud functions then you can leave initializeApp() empty.

Cloud function not found from SDK but callable via HTTPS

I've deployed some cloud functions to my Firebase project. If I call them with a REST client (such as Postman) they work fine. I'm able to execute them and the output is just as expected.
However, I've tried calling them with both de Web SDK and the Android SDK and, in both cases, I'm getting a not-found error. For example, I tried calling my function createRoom with the following code (btw, quite similar to the official docs example):
var firebase = require("firebase/app");
require("firebase/functions");
let firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
};
firebase.initializeApp(firebaseConfig);
var cloudFunctions = firebase.functions();
const createRoom = cloudFunctions.httpsCallable("createRoom");
createRoom()
.then((result) => {
console.log(result);
})
.catch(function (error) {
console.log(error);
});
and I keep getting following error:
HttpsErrorImpl: not-found
at new HttpsErrorImpl (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/#firebase/functions/dist/index.node.cjs.js:62:28)
at _errorForResponse (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/#firebase/functions/dist/index.node.cjs.js:157:12)
at Service.<anonymous> (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/#firebase/functions/dist/index.node.cjs.js:574:33)
at step (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/tslib/tslib.js:141:27)
at Object.next (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/tslib/tslib.js:122:57)
at fulfilled (/home/pitazzo/Proyectos/maximiliana/firebase-mock/node_modules/tslib/tslib.js:112:62)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
code: 'not-found',
details: undefined
}
Using the Android SDK I get an equivalent error, also including the not-found error code. I can't see whats wrong, because calling the function directly works perfectly.
FYI, calls executed with the SDKs are not event registered in the Firebase console logs. Any help will be appreciated.
I found the problem: Cloud Functions are only avaible in those regions where them were deployed.
That means, you have to specify the region where you want to execute the function when calling it. If no region is specified, Firebase looks for it in us-central-1. If it can not be found there, it fails.

firestore node.js sdk stops responding on write

I am building a CLI app where I want to use firebase as the backend. I am using the firebase node.js sdk for this and I am running into a problem where after successful login, the firestore add / set functions stop responding and do not trigger either the "then" method or the "error" method.
const firebase = require('firebase');
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "<REDACTED>",
authDomain: "<REDACTED>",
databaseURL: "<REDACTED>",
projectId: "<REDACTED>",
storageBucket: "<REDACTED>",
messagingSenderId: "<REDACTED>",
appId: "<REDACTED>"
};
// Initialize Firebase
var app = firebase.initializeApp(firebaseConfig);
function main() {
firebase.auth().signInWithEmailAndPassword('username', 'somepassword').then((cred) => {
console.log('Successful sign in');
firebase.firestore().collection('UserData').doc(cred.user['uid']).collection('ShellCommands').add({'Hello': 'World'}).then(function() {
console.log("Document successfully written!");
terminate();
}).catch(function(error) {
console.log(error);
});
}).catch(function(error) {
console.log(error);
});
}
main();
Now when I run this, I do see the successful sign in console log but after that the app stops and doesn't respond. It seems like its waiting for user input since the keyboard is active.
My firestore rules are open (for testing).
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
Am wondering if I messed up chaining the promise or is there something fundamentally wrong with doing it this way. Note, this will not be a server but a CLI app.
[EDITED]: The CLI app gets passed a string which it writes to firestore and exits. So everytime, the CLI is run, it would login and write the string. However, the CLI would be per user, so the user is only allowed to write to their collection. something like UserData/{UserID}/Data.

Firebase authentication (is not a function, is not a constructor)

I don't know what is wrong. I'm using Node.js and trying to log in using email/password and Google authentication. I have enabled all of them in Firebase console.
npm Firebase version - 3.1.0
part of code:
var firebase = require('firebase');
var config = {
apiKey: "AIzaSyAH27JhfgCQfGmoGTdv_VaGIaX4P-qAs_A",
authDomain: "pgs-intern.firebaseapp.com",
databaseURL: "https://pgs-intern.firebaseio.com",
storageBucket: "pgs-intern.appspot.com",
};
firebase.initializeApp(config);
app.post('/login', function(req, res) {
var auth = firebase.auth();
firebase.auth().signInWithEmailAndPassword(req.body.login, req.body.password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
}
Error: firebase.auth(...).signInWithLoginAndPassword is not a function
or
Error: firebase.auth(...).GoogleAuthProviders is not a constructor when I write
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
I just did exactly what is in documentation.
Your first error probably comes from a typo somewhere.
firebase.auth(...).signInWithLoginAndPassword is not a function
Notice it says signInWithLoginAndPassword, the function is called signInWithEmailAndPassword. In the posted code it's used correctly, so it's probably somewhere else.
firebase.auth(...).GoogleAuthProviders is not a constructor
You have not posted the code where you use this, but I assume this error happens when you create your provider variable, that you use in firebase.auth().signInWithPopup(provider)
That line should be var provider = new firebase.auth.GoogleAuthProvider();
Based on the error message, I think you might be doing new firebase.auth().GoogleAuthProvider(); Omit the brackets after auth, if that's the case.
Do not call GoogleAuthProvider via an Auth() function.
According to the documentation you have to create an instance of GoogleAuthProvider.
let provider = new firebase.auth.GoogleAuthProvider()
Please check the following link https://firebase.google.com/docs/auth/web/google-signin
There is no way to sign your node.js app into firebase with email+password or one of the social providers.
Server-side processes instead sign into Firebase using so-called service accounts. The crucial difference is in the way you initialize the app:
var admin = require('firebase-admin');
admin.initializeApp({
serviceAccount: "path/to/serviceAccountCredentials.json",
databaseURL: "https://databaseName.firebaseio.com"
});
See this page of the Firebase documentation for details on setting up a server-side process.

Resources