I have been trying to implement the example of leveraging user authentication information to "impersonate" a user and perform write operations on the user's behalf, using the code straight from the example here: https://firebase.google.com/docs/functions/database-events
I have been unable to get past permission denied errors. I've tried implementing adminRef as shown in some posts, but to no avail. Any help would be much appreciated
exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
.onCreate((snap, context) => {
const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
appOptions.databaseAuthVariableOverride = context.auth;
const app = admin.initializeApp(appOptions, 'app');
const uppercase = snap.val().toUpperCase();
const ref = snap.ref.parent.child('uppercase');
const deleteApp = () => app.delete().catch(() => null);
return app.database().ref(ref).set(uppercase).then(res => {
// Deleting the app is necessary for preventing concurrency leaks
return deleteApp().then(() => res);
}).catch(err => {
return deleteApp().then(() => Promise.reject(err));
});
});
EDIT: I am seeing the authType as unauthenticated, despite the fact that I am triggering this db change from a test client app that is signing in with email/pass using firebase.auth().signInWithEmailAndPassword, in the cloud functions logs, I am logging out auth and authtype : const authVar =context.auth; const authType = context.authType; Which are showing NULL and UNAUTHENTICATED, respectively.
EDIT: this is also the case if I trigger the db event from the client after authenticating with firebase.auth().signInWithCustomToken()
Firebase onCreate trigger: can't get authType other than UNAUTHENTICATED
Related
I'm currently attempting to use Supabase's JavaScript API to update a row in my 'profiles' database, which has RLS on, via my backend.
This is being done following Stripe sending me a webhook indicating a payment has been successful.
I won't put the full API call in, but here is my Supabase code:
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY
const supabase = createClient(supabaseUrl, supabaseAnonKey)
module.exports = async (req, res) => {
if (event.type === "checkout.session.completed") {
const userId = String(event.data.object.client_reference_id)
const { error } = await supabase.from('profiles').update({ premium: 'true' }).eq('id', userId)
if (error) {
console.log(error)
}
}
}
However, every time I try to run this, I get a 404 error. This seems to be because I have RLS on.
As a result, I have two questions:
Is it safe for me to turn RLS off?
How can I adjust my code / apply a new database policy to allow this to be accepted?
I am trying to interact with firebase firestore from my cloud function. The cloud functions looks like the following:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const db = admin.firestore();
exports.addVote = functions.https.onCall((data, context) => {
return db
.doc("sdd-enheter/enhet/votes/voteID")
.set({ user: "user", vote: 0 });
});
When calling the function from the client side I get a firebase internal error, indicating that the function has been called but throws an error. What should I do to fix this?
Your function needs to return a promise or otherwise terminate by throwing an https error. Throwing the https error will give the client back a relevant error that it can handle, so consider making that a habit. The function below covers both of those bases. If you still get an error then share that error with us as it appears in the console's function log.
exports.addVote = functions.https.onCall((_data, _context) => {
const db = admin.firestore();
try {
return db.doc("sdd-enheter/enhet/votes/voteID").set({user: "user", vote: 0});
} catch (error) {
throw new functions.https.HttpsError("unknown", "Failed to add vote.", error);
}
});
I followed several hundred links, most including stackoverflow links, to try to come up with a solution to this problem, but none yielded results.
I am simply trying to get the server to access client's detail via google. Ie, get the client's Google Sheets. I followed their documentation, but for the most part, its on client side only. I followed the instructions for server-side, but it has uncompleted work in it. I found out that the method to do is to have the client sign in via OAuth2.0 and then send the recieved code to the server to process to its very own access code. That is what I'm doing, however, when I try to query any data, I get that error in the title. Here is the code snippets, please let me know if there's anything I'm missing. RIP my rep.
server:
const Router=require("express").Router()
const auth=require("../utils/auth")
const fs= require("fs")
const {OAuth2Client}=require("google-auth-library")//I tried with this library instead, and it will give the exact same error.
const {google} = require('googleapis');
var auths=[]
function oAuth2ClientGetToken(oAuth2Client, code) {
return new Promise((resolve, reject) => {
oAuth2Client.getToken(code, (err, token) => { // errors out here
if (err) reject(err);
resolve(token);
});
});
}
async function formAuthClient(code) {
const {client_secret, client_id,redirect_uris} = JSON.parse(fs.readFileSync(__dirname+"/credentials.json"))
const oAuth2Client = new google.auth.OAuth2( // form authObject
client_id, client_secret,redirect_uris[1]
);
// var oauth2Client = new OAuth2Client(client_id,client_secret,redirect_uris[1]); other method
const token = await oAuth2ClientGetToken(oAuth2Client, code).catch(console.err);
// oauth2Client.credentials=token other method of oauth2.0
oAuth2Client.setCredentials(token);
return oAuth2Client;
}
Router.get("/",(req,res)=>{
res.render("home")
})
Router.post("/sheet",async (req,res)=>{
try {
const requestBody = {
properties: {
title:"hello"
}
};
var sheets= google.sheets({version:"v4", auth: auths[req.session.id]})
await sheets.spreadsheets.create(requestBody)
} catch (error) {
res.json(error)
}
})
Router.post("/login",(req,res)=>{
console.log("token: ",req.body.token);
req.session.token=req.body.token
console.log("req.session.id:",req.session.id);
auths[req.session.id]=formAuthClient(req.body.token)
res.status(200).json()
})
module.exports=Router
the client scripts is a simple button that will trigger an "getOfflineAccess" command and ask the user to log in and then send that data to the server with "/login". then, once another button is pushed, it will call "/sheet". I appreciate all help with this. I ran out of links to click on trying to solve this problem
I am losing my hope at solving a Network Error in my Firebase/React app. The error Uncaught Error: Network Error at auth.esm.js:255 shows up in the console sometimes, and at other times it simply won't show and the user gets logged in with Google successfully.
While searching for an answer, I couldn't find anything conclusive (be it in Stack Overflow or Github issues). The Firebase documentation only shows Thrown if a network error (such as timeout, interrupted connection or unreachable host) has occurred about this.
Below is my piece of code for the log in component.
useEffect(() => {
auth
.getRedirectResult()
.then(function (result) {
if (result.credential) {
const token = result.credential.accessToken
setIdToken(token)
history.push('/')
}
const user = result.user
setUsername(user.displayName)
})
.catch(function (error) {
var errorCode = error.code
var errorMessage = error.message
console.log('errorCode and errorMessage: ', errorCode, errorMessage)
})
}, [])
function handleSignInWithGoogle() {
signInWithGoogle()
setLoading(true)
}
//then, inside of my return statement
<button onClick={() => handleSignInWithGoogle()}> Sign in with Google </button>
And this is what inside of my Firebase file
firebase.initializeApp(firebaseConfig)
export const firestore = firebase.firestore()
export const auth = firebase.auth()
export const provider = new firebase.auth.GoogleAuthProvider()
export const signInWithGoogle = () => auth.signInWithRedirect(provider)
Its possible you have some debugger on the code or any blocking process.
Aparently firebase has a timeout and after that time pass (few seconds on my case) it doesnt allow you, as soon as took out the debugger that was blocking the first start it got solved.
I am trying to send a sample notification to all devices according to their token, however the token is being logged as "undefined" and the notification subsequently fails to deliver
The following lines from my code successfully show me the data from the database:
const notificationSnapshot = change.after.val(); //get new value
console.info(notificationSnapshot);
However, the following gives "undefined", despite the above retrieving the data successfully.
const userToken = notificationSnapshot.token;
console.info(userToken);
Is this not the correct way to retrieve the token to send the notification to all the registered devices in my firebase database?
my whole function (index.js)
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendSampleNotification = functions.database.ref('/User')
.onWrite((change, context) => {
const notificationSnapshot = change.after.val(); //get new value
const userToken = notificationSnapshot.token;
const name = notificationSnapshot.name;
const surname = notificationSnapshot.surname;
console.info(notificationSnapshot);
console.info(userToken);
var message = {
notification: {
title: 'test title',
body: 'test message'
},
token: userToken
};
admin.messaging().send(message).then((response) => {
console.log("Message sent successfully:", response);
return response;
})
.catch((error) => {
console.log("Error sending message: ", error);
});
});
I would say that your issue is very similar to this one since you are having a missing token (showed as undefined) due to the executions times, more or less what Doug was pointing out.
Note that the solution relies on considering the execution times and I’ve seen also that the implementation differs in some method executions but I would say the generals point in the same direction.