Firebase - create user on Node.js server - firebase

We have a large SPA using Firebase v2. We would like to upgrade to the new API, but we experience the following problem:
As the app is quite large, we have developed many integration tests, and for these tests we always need to reset the database and initialize it to a state, where some users exist. However, we found out there really is no such thing as creating a user on server anymore ( Firebase createUserWithEmailAndPassword method is undefined in node.js ), and we are quite unsure, how to upgrade the API and yet be able to reset and initialize the database from server.
Moreover, we are quite forced to do this upgrade, because we noticed that the Firebase v2, is still using the deprecated Graph API v2.0 for Facebook OAuth, and is not recommended for use after 8.8.2016. We understand that the Firebase v2 will probably not upgrade the calls to the Graph API, as the v2 is legacy. This, however, leaves us quite cornered for now.
Any help on this topic, please?

As of Firebase v3.3.0 you are able to create user accounts using Node, but the documentation isn't great on how to expose these methods.
In order to use the user management methods, you need to initialize an application in node using your Web API key, and not the Service Account config that is walked through in the setup guide.
// The Usual Service Account Init
// This will not contain any user management methods on firebase.auth()
this.app = firebase.initializeApp(
{
serviceAccount: 'path/to/serviceaccount/file.json',
databaseURL: 'https://mydbfb.firebaseio.com'
},
'MyAppName');
// Web Client Init in Node.js
// firebase.auth() will now contain user management methods
this.app = firebase.initializeApp(
{
"apiKey": "my-api-key",
"authDomain": "somedomain.firebaseapp.com",
"databaseURL": "https://mydbfb.firebaseio.com",
"storageBucket": "myfbdb.appspot.com",
"messagingSenderId": "SomeId"
},
'MyAppName');
You can grab your client api key from your Firebase console from the Web Setup guide
https://firebase.google.com/docs/web/setup
This is the only reference I could find that explicitly referenced the need to init with api key to get this to work.
https://groups.google.com/forum/#!msg/firebase-talk/_6Rhro3zBbk/u8hB1oVRCgAJ

Given below is a working example of creating Firebase user through Node.js
exports.addUser = function(req, res) {
var wine = req.body;
var email = req.body.email;
console.log(req.body);
var password = req.body.password;
var name = req.body.name;
console.log(“Creating user for -“+email+”-“+password);
var defaultAuth = admin.auth();
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
displayName: name,
disabled: false
})
.then(function(userRecord) {
console.log(“Created Firebase User successfully with id :”, userRecord.uid);
var wine = req.body;
wine.userId = userRecord.uid;
wine.timestamp = Date.now();
delete wine.password;
status = “201”;
var reply = JSON.stringify(wine);
db.collection(‘collname’, function(err, collection) {
collection.insert(wine, {safe:true}, function(err, result) {
if (err) {
wine.status = “200”;
wine.message = “An error occured”;
reply.set(‘status’,”201″);
res.status(201).send(wine);
} else {
console.log(‘Success: ‘ + JSON.stringify(result[0]));
status= “200”;
wine.status = “200”;
wine.message = “Account created Successfully”;
res.status(200).send(wine);
}
});
});
})
.catch(function(error) {
wine.message = “An error occured—“;
wine.status = “201”;
console.log(“User Creation onf Firebase failed:”, error);
res.status(201).send(wine);
});
}
For details you can see the following blog post
http://navraj.net/?p=53
Thanks

Related

react native facebook login using expo client: The App_id in the input_token did not match the Viewing App

I am using expo-facebook to integrate a Facebook login using expo and firebase. Everything looks to be working and I log into Facebook but get an OAuthException once I authenticate using Facebook as follows:
Unsuccessful debug_token response from Facebook: {"error":{"message":"(#100) The App_id in the input_token did not match the Viewing App","type":"OAuthException","code":100
I have gone through a lot of issues on Stack Overflow, GitHub and looked at expo documentation as well but to no avail.
I have configured the app id and secrets from Facebook into firebase as required as well as set up the OAuth redirect URI to my Facebook app configuration. The code I have put together to setup the login is as follows:
const signInWithFacebook = async () => {
try {
// const { type, token } = await Facebook.logInWithReadPermissionsAsync(
// facebookAppId,
// {
// permissions: ["public_profile"],
// }
// );
const appId = Constants.manifest.extra.facebook.appId;
const permissions = ["public_profile"]; // Permissions required, consult Facebook docs
await Facebook.initializeAsync({
appId: appId,
});
const { type, token } = await Facebook.logInWithReadPermissionsAsync({
permissions: permissions,
});
console.log(type);
console.log(token);
if (type === "success") {
await firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.LOCAL);
const credential = firebase.auth.FacebookAuthProvider.credential(token);
const facebookProfileData = await firebase
.auth()
.signInWithCredential(credential);
//this.onLoginSuccess.bind(this);
console.log(facebookProfileData);
}
} catch ({ message }) {
console.log(message);
alert(`Facebook Login Error: ${message}`);
}
};
I have also setup the relevant configurations in the app.json as follows:
"expo":{
"facebookScheme": "fb123243435566",
"facebookAppId": "123243435566",
"facebookDisplayName": "myapp"
}
The only aspect I am not sure about is where to grab the facebookScheme. Currenltly I have assumed it's fb+AppID. the documenatation mentioned here https://docs.expo.dev/versions/latest/sdk/facebook/
isn't clear. It states:
Configure app.json.
Add the field facebookScheme with your Facebook login redirect URL scheme found here under "4. Configure Your info.plist." It should look like "fb123456". If you do not do this, Facebook will not be able to redirect to your app after logging in.
But I am not sure how to grab that facebookScheme id. I suspect this is where the issue is as expo states that.
Expo Go from the Android Play Store will use the Facebook App ID that you provide, however, all Facebook API calls in the Expo Go from the iOS App Store will use Expo's own Facebook App ID. This is due to underlying configuration limitations.
so I am assuming the facebookScheme is some kind of workaround.
Although I am not sure if it's a working around for the ios standalone app or the expo managed.
Try this:
const { type, token } = await Expo.Facebook.logInWithReadPermissionsAsync(appId, {
permissions: [‘public_profile’, ‘email’],
behavior: Platform.OS === ‘android’ ? ‘web’ : ‘system’,
});
it should specify for the app to open a web browser on login
here's the ref:
https://forums.expo.dev/t/how-to-fix-standalone-android-expo-facebook-login/23922

How to integrate account-js package to already existed mongo db?

I have a meteor app and want to migrate non-meteor app. I found account-js is compatible with the meteor account system. When I create new user everything works well but If I want to login with already existed user account-js methods does not work and I get unauth message everytime. How to login with already existed users by using account-js ?
const accountsPassword = new AccountsPassword({
verifyPassword: (plainPassword, storedPassword) => {
const hashedPassword = crypto.Hash('sha256').update(plainPassword).digest('hex')
console.log('*****Verify Password*****')
return bcrypt.compareSync(plainPassword, storedPassword)
}
})
const accountsServer = new AccountsServer(
{
db: accountsMongo
},
{
password: accountsPassword
}
)
const accountsGraphQL = AccountsModule.forRoot({ accountsServer })
const schema = makeExecutableSchema({
typeDefs: mergeTypeDefs([typeDefs, accountsGraphQL.typeDefs]),
resolvers: mergeResolvers([resolvers, accountsGraphQL.resolvers]),
schemaDirectives: {
...accountsGraphQL.schemaDirectives
}
})
const schemaMiddleware = applyMiddleware(schema, permissions)
accounts-js utilizes an entirely different authentication mechanism than Meteor authentication system. accounts-js uses JWT tokens while Meteor uses unique hashes so it's not cross-compatible. I wrote a blog post about it which you can read here

Trying to authenticate a service account with firebase-admin from a Cloud Scheduler call? Error: Firebase ID token has incorrect "iss" (issuer) claim

I'm trying to authenticate an API call made to my server (on Cloud Run) from a Cloud Scheduler cron job.
I'm trying to use a service account to this.
Note: this is all happening inside the same Project.
References:
https://cloud.google.com/scheduler/docs/http-target-auth
This is what I'm doing:
STEP 1 - Create the service account
I went to https://console.cloud.google.com/apis/credentials and created a new service account. I've assigned the role as owner.
STEP 2 - Create the cron job.
I went to https://console.cloud.google.com/cloudscheduler to create the cron job like I always do.
In the service account field I've put my service account e-mail. In the Audience field, I've put my project id because at some point I got an error saying that it was expecting it to be the name of my project id.
This was the error:
Firebase ID token has incorrect "aud" (audience) claim. Expected "PROJECT_ID"
STEP 3 - Running the job and identify decoding the token:
This is the code on my server:
import * as admin from "firebase-admin";
admin.initializeApp({
credential: admin.credential.cert(
// THIS IS THE DEFAULT FIREBASE-ADMIN SERVICE ACCOUNT
// THAT IS AUTOMATICALLY CREATED BY FIREBASE
SERVICE_ACCOUNT as admin.ServiceAccount
)});
// THIS IS THE CODE THAT IS INSIDE MY SERVER TRYING TO VERIFY THE SERVICE ACCOUNT
try {
const authHeader = req.headers.authorization;
console.log(`authHeader: ${authHeader}`);
if (authHeader) {
const idToken = authHeader.split(" ")[1]; // GETS THE USER ID TOKEN
const decodedToken = await admin.auth().verifyIdToken(idToken);
console.log(`decodedToken: ${decodedToken}`);
}
}
And this is the error I'm currently getting:
Firebase ID token has incorrect "iss" (issuer) claim. Expected "https://securetoken.google.com/"my-project-id" but got "https://accounts.google.com". Make sure the ID token comes from the same Firebase project as the service account used to authenticate this SDK. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
Is there anything wrong with the way I'm doing it? Should I not be using firebase-admin to this?
Should I be using google-auth-library to verify the token?
https://github.com/googleapis/google-auth-library-nodejs#verifying-id-tokens
https://developers.google.com/identity/sign-in/web/backend-auth
After a morning in hell trying to debug this, here is what I've found.
It seems that firebase-admin's admin.auth().verifyIdToken() only works for tokens generated from the firebase SDK.
I got it to work by using the google-auth-library directly.
I did the following.
NOTE: The rest of the code is the same (using the same service account as described in the question):
import { OAuth2Client } from "google-auth-library";
export const apiExpressRouteHandler: RequestHandler = async (req, res) => {
try {
const PROJECT_ID = process.env.PROJECT_ID;
const authHeader = req.headers.authorization;
if (authHeader) {
const client = new OAuth2Client(PROJECT_ID);
const ticket = await client.verifyIdToken({
idToken: authHeader.split(" ")[1],
audience: PROJECT_ID
});
// LOGGING ticket PROPERTIES
console.log(`userId: ${JSON.stringify(ticket.getUserId())}`);
console.log(`payload: ${JSON.stringify(ticket.getPayload())}`);
console.log(`envelope: ${JSON.stringify(ticket.getEnvelope())}`);
console.log(`attributes: ${JSON.stringify(ticket.getAttributes())}`);
}
// REST OF THE CODE
}
}
catch(err) {
// ...
}
I'm not sure if the PROJECT_ID is necessary to initialize the client with new OAuth2Client(PROJECT_ID); but it is working like this.

Programmatically add Google Analytics to Firebase project

I wish to automate all of the steps involved in setting up a new Firebase project without any user interaction. I've accomplished most of the steps via either the gCloud CLI, Firebase CLI or the GoogleApis NodeJS library.
Authentication has been done via the CLI tools or via service accounts.
The only thing I haven't been able to do so far is adding Google Analytics to the newly created Firebase project. I have found this Google Api which should accomplish this, but I'm having problems authenticating the request.
How would I authenticate a request to this API without any user interaction? The API is not available via the CLI tools, so my best guess would be to use a service account with the owner IAM-role, but the request keeps failing.
My steps so far have been:
Ensuring that the management API is enabled
Add a service account to the GCloud project with owner privileges
Download the service account
Run the following code
import { google } from 'googleapis';
import * as fetch from 'node-fetch';
async function addGoogleAnalytics {
const token = await getJWTAcessToken();
await addAnalyticsFetch(token);
};
async function addAnalyticsFetch(accessToken) {
const url = `https://firebase.googleapis.com/v1beta1/projects/<my-project-id>:addGoogleAnalytics`;
const fetchResult = await fetch(url, {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}` },
json: true,
body: JSON.stringify({ analyticsAccountId: '<my-analytics-account-id>' }),
});
const fetchResultText = await fetchResult.text();
console.log('Fetch result: ', fetchResultText);
}
function getJWTAcessToken() {
const SCOPES = ['https://www.googleapis.com/auth/cloud-platform'];
const key = require('../../serviceAccount.json');
return new Promise((resolve, reject) => {
const jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, SCOPES, null);
jwtClient.authorize((err, tokens) => {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
}
The result of the API call is a simple 403 - "The caller does not have permission".
I've also attempted this using the GoogleApis NodeJS library with similar results.
If being a project owner doesn't give enough privileges, how do I permit this service account to perform this API call? I have a suspicion that I'm failing because the service account is in no way associated with the Google Analytics account, but the documentation doesn't list that as a requirement. It is also not listed as a step in Google's own guide.
It turns out that the above code is 100 % valid. The problem was indeed that the service account had enough privileges to edit the Firebase-project, but it had no authorization to create a new property for the Google Analytics account.
After giving the service account edit privileges for the Google Analytics account, the connection between Firebase and Google Analytics was successfully established. This process can be automated via this API.

Error on firebase admin nodejs Permission iam.serviceAccounts.signBlob is required

im using this tutorial:
https://firebase.google.com/docs/auth/admin/create-custom-tokens#using_a_service_account_id
to create a node.js function (deployed to google cloud functions) to authenticate my users. the function is super simple:
const admin = require('firebase-admin');
admin.initializeApp({
serviceAccountId: 'authenticator#igibo-b0b27.iam.gserviceaccount.com'
});
exports.authenticate = (req, res) => {
let pass;
let uid;
if (req.query) {
if (req.query.v == 3) {
pass = req.query.p;
uid = req.query.u;
}
admin.auth().createCustomToken(uid)
.then(function(customToken) {
res.status(200).send(customToken);
return customToken;
})
.catch(function(error) {
console.error("Error creating custom token:" + JSON.stringify(error));
res.status(400).send(error);
});
} else {
console.error("EMPTY to authentication");
res.end();
}
};
but im getting this annoying error:
{"code":"auth/insufficient-permission","message":"Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/-/serviceAccounts/authenticator#igibo-b0b27.iam.gserviceaccount.com.; Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens for more details on how to use and troubleshoot this feature."}
in the very same tutorial it says i must go to IAM and adjust some roles for the service account WHICH I DID but still getting this error.
this is a absolutelly simple task and shouldn't being such a hassle...
what i am forgetting? the id is correct! the role is correct! the code is correct!
what is wrong?
Firebase mentions about this error on its docs:
https://firebase.google.com/docs/auth/admin/create-custom-tokens#failed_to_determine_service_account
You must initialize your app correctly through a JSON config file.
A simple fix would be:
Go to
https://console.cloud.google.com/iam-admin/iam?project=PROJECT_NAME
Edit your default service account.
Add the role Service Account
Token Creator
In a few minutes your project will be able to create signed tokens.

Resources