How to manage tenants programatically in Google Cloud Platform - node.js

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,
}

Related

Error trying to authenticate with FCM servers when sending message using Firebase Admin SDK in node.js

When I try to send to send an FCM notification to a topic I get the following error...
Error: An error occurred when trying to authenticate to the FCM
servers. Make sure the credential used to authenticate this SDK has
the proper permissions.
I am using a brand new generated service account key and pointing to it correctly. I have confirmed that the path to the key is correct. I have also enabled Cloud Messaging for the project.
const { messaging } = require('firebase-admin');
var admin = require('firebase-admin');
console.log(process.cwd());
async function run() {
try {
var serviceAccount = require("/Users/myUser/src/my_project/node_admin/my_project-5617a-firebase-adminsdk-lwpk6-5dad9000e0.json");
const topic = 'all';
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
const payload = {
notification: {
title: "Test1234",
body: "body",
sound: 'test-sound.wav'
}
};
var options = {
priority: "high"
}
await admin.messaging().sendToTopic(topic , payload , options);
} catch (e) {
console.log(e);
}
}
run();
Hello i was copy code and run --> it working
so i think you can check path of file auth json
var serviceAccount = require("/Users/myUser/src/my_project/node_admin/my_project-5617a-firebase-adminsdk-lwpk6-5dad9000e0.json");
good luck!

Firebase can't find project ID Firebase Admin SDK cloud messaging

I want to my Node.js server to be able to automatically send firebase cloud messages to devices with specific registration tokens. The docs discuss several ways I can authorize my Node.js server, including relying on the default project authorization if I am deploying with Google Cloud (which I am). However, while I'm testing my Node.js server on my local machine, it seems like I need to set an environment variable with the path of a downloaded configuration .json.
I did this with:
export GOOGLE_APPLICATION_CREDENTIALS="/Users/johnsorensen/Documents/Ops Docs/notificationsmrp-firebase-adminsdk-h86ml-cd2d8d8f7a.json"
I can verify that this indeed the correct file path, as I had Mac's finder return it to me.
When I run my app, however, I get this error:
errorInfo: {
code: 'app/invalid-credential',
message: 'Failed to determine project ID: Error while making request: getaddrinfo
ENOTFOUND metadata.google.internal. Error code: ENOTFOUND'
},
codePrefix: 'app'
Node.js code:
const admin = require("firebase-admin")
admin.initializeApp({ credential: admin.credential.applicationDefault(),})
const registrationToken = 'ePdAwFHd_EBJufZC6XQU8l:APA91bEYD5pFKIMuPwO7oAlKWqbENUXXG_TsLf67IS1Lyf-ge9szJ5Eqo0W8GTqgyheXSyNrNY6_QbU5V8nq39hj42cgphRG9PClgKOY8Ugc6aOFMTTY9t5pWrV_suzvzEXH2cprm3Nv';
const message = {
data: {
score: '850',
time: '2:45'
},
token: registrationToken
};
admin.messaging().send(message)
.then((response) => {
console.log("Success")
console.log(response)
})
.catch((error) => {
console.log("Error Sending Message", error)
})
After following the docs provided in the comments, it seemed like I was on the right track. But now gcloud is throwing an error about my .json:
(gcloud.auth.application-default.login) Invalid file format. See https://developers.google.com/api-client-library/python/guide/aaa_client_secrets Expected a JSON object with a single property for a "web" or "installed" application
I downloaded the json from the specified source in the docs... what's going wrong now?
I think the docs I was reading was misleading. I can successfully authenticate a node application by simply downloading the private key from firebase, then using the following code:
const admin = require("firebase-admin");
const serviceAccount = require("/filepath/to/private/key");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

Could not load the default credentials? (Node.js Google Compute Engine)

I am trying to create a new vm using Nodejs client libraries of GCP, I followed the below link,
https://googleapis.dev/nodejs/compute/latest/VM.html#create
and below is my code
const Compute = require('#google-cloud/compute');
const {auth} = require('google-auth-library');
const compute = new Compute();
var cred = "<<<credential json content as string>>>";
auth.scopes = ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute'];
auth.jsonContent = JSON.parse(cred);
const config = {
machineType: 'n1-standard-1',
disks: [ {
boot: true,
initializeParams: { sourceImage: '<<<image url>>>' }
} ],
networkInterfaces: [ { network: 'global/networks/default' } ],
tags: [ { items: [ 'debian-server', 'http-server' ] } ],
auth: auth,
};
async function main() {
// [START gce_create_vm]
async function createVM() {
const zone = compute.zone('us-central1-c');
const vm = zone.vm('vm-name');
await vm.create(config).then(function(data) {
const vm = data[0];
const operation = data[1];
const apiResponse = data[2];
});
console.log(vm);
console.log('Virtual machine created!');
}
createVM().catch(function (err) {
console.log(err);
});
// [END gce_create_vm]
}
main();
when i run this, the error I am getting is
Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
at GoogleAuth.getApplicationDefaultAsync (D:\Click to deploy\src\c2dNodeGCP\node_modules\google-auth-library\build\src\auth\googleauth.js:155:19)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async GoogleAuth.getClient (D:\Click to deploy\src\c2dNodeGCP\node_modules\google-auth-library\build\src\auth\googleauth.js:487:17)
at async GoogleAuth.authorizeRequest (D:\Click to deploy\src\c2dNodeGCP\node_modules\google-auth-library\build\src\auth\googleauth.js:528:24)
My scenario is to take the service account credential from string variable rather than from env var or some other thing.
I can see that it is trying to take the default credential which is not there in my case.
I was able to achieve this in java, but here i am not able to do it. Any help will be appreciated.
In order to execute your local application using your own user credentials for API access temporarily you can run:
gcloud auth application-default login
You have to install sdk into your computer, that will enable you to run the code.
Then log in to your associated gmail account and you will be ready.
You can check the following documentation, to get more information.
Another option is to set GOOGLE_APPLICATION_CREDENTIALS to provide authentication credentials to your application code. It should point to a file that defines the credentials.
To get this file please follow the steps:
Navigate to the APIs & Services→Credentials panel in Cloud Console.
Select Create credentials, then select API key from the dropdown menu.
The API key created dialog box displays your newly created key.
You might want to copy your key and keep it secure. Unless you are using a testing key that you intend to delete later.
Put the *.json file you just downloaded in a directory of your choosing.
This directory must be private (you can't let anyone get access to this), but accessible to your web server code.
You can write your own code to pass the service account key to the client library or set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the path of the JSON file downloaded.
I have found the following code that explains how you can authenticate to Google Cloud Platform APIs using the Google Cloud Client Libraries.
/**
* Demonstrates how to authenticate to Google Cloud Platform APIs using the
* Google Cloud Client Libraries.
*/
'use strict';
const authCloudImplicit = async () => {
// [START auth_cloud_implicit]
// Imports the Google Cloud client library.
const {Storage} = require('#google-cloud/storage');
// Instantiates a client. If you don't specify credentials when constructing
// the client, the client library will look for credentials in the
// environment.
const storage = new Storage();
// Makes an authenticated API request.
async function listBuckets() {
try {
const results = await storage.getBuckets();
const [buckets] = results;
console.log('Buckets:');
buckets.forEach((bucket) => {
console.log(bucket.name);
});
} catch (err) {
console.error('ERROR:', err);
}
}
listBuckets();
// [END auth_cloud_implicit]
};
const authCloudExplicit = async ({projectId, keyFilename}) => {
// [START auth_cloud_explicit]
// Imports the Google Cloud client library.
const {Storage} = require('#google-cloud/storage');
// Instantiates a client. Explicitly use service account credentials by
// specifying the private key file. All clients in google-cloud-node have this
// helper, see https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/docs/authentication.md
// const projectId = 'project-id'
// const keyFilename = '/path/to/keyfile.json'
const storage = new Storage({projectId, keyFilename});
// Makes an authenticated API request.
async function listBuckets() {
try {
const [buckets] = await storage.getBuckets();
console.log('Buckets:');
buckets.forEach((bucket) => {
console.log(bucket.name);
});
} catch (err) {
console.error('ERROR:', err);
}
}
listBuckets();
// [END auth_cloud_explicit]
};
const cli = require(`yargs`)
.demand(1)
.command(
`auth-cloud-implicit`,
`Loads credentials implicitly.`,
{},
authCloudImplicit
)
.command(
`auth-cloud-explicit`,
`Loads credentials explicitly.`,
{
projectId: {
alias: 'p',
default: process.env.GOOGLE_CLOUD_PROJECT,
},
keyFilename: {
alias: 'k',
default: process.env.GOOGLE_APPLICATION_CREDENTIALS,
},
},
authCloudExplicit
)
.example(`node $0 implicit`, `Loads credentials implicitly.`)
.example(`node $0 explicit`, `Loads credentials explicitly.`)
.wrap(120)
.recommendCommands()
.epilogue(
`For more information, see https://cloud.google.com/docs/authentication`
)
.help()
.strict();
if (module === require.main) {
cli.parse(process.argv.slice(2));
}
You could obtain more information about this in this link, also you can take a look at this other guide for Getting started with authentication.
Edit 1
To load your credentials from a local file you can use something like:
const Compute = require('#google-cloud/compute');
const compute = new Compute({
projectId: 'your-project-id',
keyFilename: '/path/to/keyfile.json'
});
You can check this link for more examples and information.
This other link contains another example that could be useful.

app.auth(...).signInWithCredential is not a function firebase error

I'm trying to add google login to my node js firebase app. I'm getting the following error:
app.auth(...).signInWithCredential is not a function
Here's the code on the server
var credential = firebase.auth.GoogleAuthProvider.credential(id_token);
return app.auth().signInWithCredential(credential);
On the client
// We need to register an Observer on Firebase Auth to make sure auth is initialized.
var unsubscribe = app.auth().onAuthStateChanged((firebaseUser) => {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
// Build Firebase credential with the Google ID token.
var credential = firebase.auth.GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
// Sign in with credential from the Google user.
firebase.auth().signInWithCredential(credential).catch( (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;
console.dir(errorMessage);
}).then( (success) => {
console.dir(success);
var id_token = googleUser.getAuthResponse().id_token;
axios.post('/auth/google-login', {
id_token: id_token
}).then(response => {
var result = response.data;
if (result.status === "ok") {
this.setState({complete: true});
} else if (result.error) {
this.setState({error: result.error});
}
}).catch(error => {
console.dir(error);
this.setState({error: "error"});
});
});
});
What I'm I doing wrong?
At the top of the nodejs file, I have
var app = require('./base');
where base :
var serviceAccount = require("./service-account-file.json");
const app = fadmin.initializeApp({
credential: fadmin.credential.cert(serviceAccount),
databaseURL: "https://test.firebaseio.com"
});
module.exports = app;
Hi there are hints that the problem starts with node version 6.21. that
app.auth().signInWithCredential(credential)
Don't work
It works in v6.2.0.
Try signInWithEmailAndPassword
Use latest version of node
The function signInWithCredential is part of the Firebase JavaScript SDK
The Firebase JavaScript SDK implements the client-side libraries used by applications using Firebase services.
The Firebase Admin SDK is intended to run on a server or other privileged environment. The Admin SDK does not include sign-in functions.

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