This question already has answers here:
How to protect firebase Cloud Function HTTP endpoint to allow only Firebase authenticated users?
(9 answers)
Closed 5 years ago.
I am trying to figure out if it is possible to check auth object from client that called firebase https cloud function to achive following tasks:
1) Only allow authed users with verified email call https endpoint, otherwise return 403.
2) Somehow gain access to uid of client that called a function in order to set node like characters/:uid in database.
Reason for this is to disallow duplicate characters. I can manually pass uid in req.body, but this means that anyone could fiddle with this and create 100 different characters by sending any sort of uid as req.body payload.
Only work around I can think of for this is changing this logic to database triggers i.e. client writes to database void/characters/uid node (database rules do this whole validation) then function listens to this change in database, processes data and pushes it to characters/uid
But this means additional logic like removing node after it is done is needed, plus I am not sure how to send back error or success response back to client, as with https functions we can just res.send(200) or send back error.
If I understand this, I think this can be done by firebase rules.
https://firebase.google.com/docs/reference/security/database/#location
In the example provided, a rule like :
".write": "auth.uid === $user"
Would only allow authenticated users with the same uid as appears on the path to write data there.
I am uncertain if a 403 is returned. This implies that you are using firebase authentication, which is covered in some depth here, depending on the mechanism you are using for authentication.
Related
Not sure if the title summarises my question well.
Basically, I am trying to authenticate routes such as checking if user exists etc. I only want to allow
requests coming from my frontend application to be approved, but, since no user is signed in there is no token to send.
Api request -
mywebiste/checkUser/email
This route is unprotected on my backend because no user is logged in.
BUT I want to protect this route, in such a way that it's accessible only from the frontend.
Some ideas I came up with were adding specific headers tag from the frontend and check them on the backend, but that could be easily replicated, is there something more secure like using tokens etc.
I am using React and Node.js
Same origin policy is going to give you some basic protection, but basically if an API endpoint is exposed publicly, it's exposed publicly. If you don't want that route to be publicly accessible you need to add access control.
If you use that route to check if a user is already registered, you could, for example, merge it with the user registration route and send a different error code if the user already exists (which is not a great idea because it leaks which emails are registered on your system).
You can verify that a request was originated by a user (by authenticating him) but you cannot verify that a request comes from a particular client because of these two reasons :
If you include some API key in your client (web page or other), it's easily retrievable by everyone (the best thing you could do is offuscate it which makes things slightly harder but still possible)
If you send an API key over the network it's easily retrievable as well
The only thing you could do is prevent other web pages from calling your backend on behalf of the user, by using CORS (which is actually active by default if you dont specify an Access-Control-Allow-Origin header)
I ended up creating a kind of working solution, so basically, I create a new base64 string on my frontend and attach that to the header while making a request to the backend. The base64 string is different every minute, so even if the header is copied, it differs every minute and is combined with your secret key.
I have made a package so that people can use it if they want - https://github.com/dhiraj1site/ncrypter
You can use it like so
var ncrypter = require('ncrypter');
//use encode on your frontend with number of seconds and secret key
var encodedString = ncrypter.encrypt(2, 'mysecret1')
//use decode on your backend with same seconds and secret
var decodedString = ncrypter.decrypt(encodedString, 2, 'mysecret1');
console.log('permission granted -->', decodedString);
This question already has answers here:
Python Requests and persistent sessions
(8 answers)
Closed 2 years ago.
https://repl.it/#rafrafraf/project-server
https://repl.it/#rafrafraf/Project
I'm basically confused about how to log in a user to my website and know if he is still logged in on page switch while having access to his data from the server.
The two links above are to my code for the server and website. I already have the html for the login and registration complete, I also recieve the auth from the server however I'm not sure what to do after that.
You'd use sessions or JWT - a session is a server side storage of data associated with a secret key that the user has (usually stored as a cookie or in local storage), while a JWT (JSON Web Token) contains signed (by you) data that identifies the user. You decode the content and validate that the signature is correct, then trust the data given.
In Flask you can quickly implement the first option by using Flask-Session, a library for handling sessions transparently for you inside a Flask application.
from flask import Flask, session
from flask.ext.session import Session
app = Flask(__name__)
# Check Configuration section for more details
SESSION_TYPE = 'redis'
app.config.from_object(__name__)
Session(app)
#app.route('/set/')
def set():
session['key'] = 'value'
return 'ok'
#app.route('/get/')
def get():
return session.get('key', 'not set')
You'd associate a value identifying the user to the session when logging the user in, then read that value back in the views that require a user to be logged in. You can further move this into authentication and authorization (i.e. which user have access to which resource), but that goes outside of the scope of an answer here.
Flask-Session supports multiple backends for session data:
null: NullSessionInterface (default)
redis: RedisSessionInterface
memcached: MemcachedSessionInterface
filesystem: FileSystemSessionInterface
mongodb: MongoDBSessionInterface
sqlalchemy: SqlAlchemySessionInterface
Pick one that suits your existing software stack.
To provide dynamic content delivery, I am using rewrites in fire base hosting. Whenever open website with index.html then the browser request the firebase cloud function main.
"rewrites": [ {
"source": "/index.html",
"function":"main"
}]
Now I am facing a problem to provide dynamic content based on user login status. I also checked about client side authendication using JS.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
I don't know about web development. Here I have few questions,
How can I find authentication status of user by more flexible way? Does cookies used for this? I am asking because I don't know to pass firebase-token to the cloud function main.
Please address me an idea. Thank you all.
Short answer: End users don't have a sign-in status that's visible on a backend. That's just not how Firebase Authentication works.
Auth clients provide credentials to get a token that's used to identify themself when they invoke backend services. This tokens has a lifetime of 1 hour, and the client must refresh it in order to keep using it. Your backend doesn't know or care if the client has an auth token, if they use it, or if they refresh it. The client just needs to provide that token from whatever device they have signed in so the backend can validate it. There is no way your backend can know if the client obtained a token - you just have to accept the one it is given. This means you're going to have to actually figure out how to pass that token and validate it with the Firebase Admin SDK, or use a callable type function using the Firebase Client SDK to send that token automatically.
This question already has an answer here:
In Firebase security rules how can you stop hackers running a script for signup to your website? bare in mind I need them to be able to signup
(1 answer)
Closed 3 years ago.
Anybody who knows how to write scripts in Tampermonkey extension or how to create create extension can easily inject javascript code in webpage and access config keys. So how do you secure it?
var config = {
apiKey: "apiKey",
authDomain: "projectId.firebaseapp.com",
databaseURL: "https://databaseName.firebaseio.com",
storageBucket: "bucket.appspot.com"
};
firebase.initializeApp(config);
Right now only thing I can think of is wrap in anonymous function to avoid variable accessibility globally. which can prevent accessing variable.
It is still not secure, developer can ajax javascript file and parse data using regex, so how do you prevent it?
Another thing I thought of that is using nodejs as backend and use restapi to get data but it also exclude it being real time database. In addition I'd have to use socket.io to transfer data to client side in realtime if firebase update database in realtime in backend.
Because If anyone can inject script to access config keys can also read & write anywhere in database at his own will where read and write permission is granted.
which is a security concern. Any keys available on client is risky. so how do you prevent such attack?
This is a fairly common question. The answer is: no, a client cant write and read from everywhere in the database but only where your rules allow it.
This is exactly like REST, if you have a REST API then all your endpoints are public. What prevents mischief use are the server rules.
In this case, the database rules are in charge of securing and validating the data.
The simplest rule is user is logged in:
Items: {
.read: if auth != null,
.write: if auth != null
}
You can also have more common rules, like owner permissions
user_items: {
$uid: {
.read: if auth.uid == $uid,
.write: if auth.uid == $uid
}
}
The previous example considers a data structure where each user has its own node, but if for any reason you meant to keep it all in the same node it can be done using query rules. My recommendation would be to use the above structure, that way in the future, an admin feature can be added by denormalizing data.
The difference here is you are exposing your credentials if you take a look at them, there is nothing really private but only needed data for Firebase to match the request with your project, beyond that your project has to define the security. Please, take care of securing RTD, Firestore and Storage.
I want to define custom functions on Firebase using firebase-tools. Is there a way to get userId from firebase-functions?
Say on this code sample, is it possible to get the user who sent the request?
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
I have tried getting it with the following code unsuccessfully functions.auth.user().uid.
I am quite new to both js and firebase, so go easy on me please, I am trying to learn.
You're over-simplifying the way HTTP triggers work. They have no knowledge of anything about the entity on the end making the request. It could be a user, or just some automated program. The user doesn't have to be authenticated in order to access your function.
If you want to limit access to your HTTP trigger to only authenticated users, you could try something as described in this other question. There is official sample code that shows what you need to do.
Bottom line is this. Unless you do something to safely transmit to the function who the user is (identified by an id token), then you really have no idea who they are.
Think I find a better answer from this post :
https://medium.com/super-declarative/dev-snack-testing-firebase-cloud-functions-with-user-id-tokens-83841d3f06c.
Basically 2 ways for http functions
functions.https.onRequest : You may get, if available, the token from the request and then use firebase admin api to get user UID;
functions.https.onCall for authenticated request : You get it from exposed context object