Is it possible to enable auth in MongoDB AND configure permissions for anonymous (non-auth) account? - mongodb

I'm running MongoDB with authorisation enabled, and multiple users created.
Now I want the clients to be able to connect anonymously as well, and be able to perform selected actions on the database without authenticating.
Is it possible to configure Mongo to have the unauthenticated access enabled at the same time as authenticated, and to control what the unauthenticated user can do?

To allow limited permission for an anonymous client can prove to be detrimental to your application. You can never predict the behaviour of client, there is always going to be some degree of uncertainity regarding it.This makes your application vulnerable to malicious exploitation.
The ideal way would be to let your application code talk to the database with a limited set of permissions(eg.read only, targetting specific database). You can expose a few api's that does what is required for anonymous clients.

Related

Making API requests to a 3rd party that requires authentication

Here is my scenario. Imagine there is a Yoga studio that uses a professional booking and reservation system that exposes an API. Through this API an application can make a reservation for a client. The API takes the client's userid and password to make the reservation. The booking API doesn't use OAuth or any social media sign-ins.
My desire is to create an Assistant Action that would retrieve the list of classes and allow the client to make a booking.
My puzzle is what design/architecture to look towards to supply the userid/password pair required by the booking API.
How have others solved this puzzle?
Should I store the userid/password as "user state" associated with the action?
First, you should have a conversation with the API provider about why they don't provide an OAuth-based solution. This is a security vulnerability waiting to happen, if it hasn't already.
Second, you need to think very carefully about your own risk profile in this case:
Google does not allow you to collect credential information (ie - passwords) through your Action.
Because of this, you must use Account Linking to authenticate them.
This means that you will need something (ie - a database or data store) to manage their account on your side.
This database would be a good place to keep the username/password you need to use for them for the API...
...but it now means that you need to take extreme care about protecting this database.
You don't really say how this API allows for accounts to be created and managed. If these accounts are just used for you (ie - the user doesn't necessarily see them), then you can mitigate some of that risk by treating the username/password as an opaque token that you manage and generate and that the user never sees.
If this is something that the user is aware of, then you'll need to approach the account linking in one of two ways:
Have them log into your service via an app or webapp using this credential info that you will need to save (ack!) and then link to the Assistant using OAuth.
Have them log into your service via an app or webapp using Google Sign-In, which will carry over to your Action. Then have them provide the credential info for the API, which you will need to save (ack!).

Best practice for secure data fetching with Mongodb Atlas

I have a client-side react app that I need to fetch information from a MongoDB Atlas collection that is being populated directly to the source by another individual. When I went to check out the connection string I noticed that the user password for db access would need to be present in the code:
(Not enough rep to post images sorry)
https://i.imgur.com/5Vs23WJ.png
Now obviously if I include this right in my front-end code anybody will be able to see my password and that's no good. But I need this app to be self-contained and I don't want to have to host a server just to reroute the single Get request that is called upon loading the site.
If I create a new user with read-only privileges, is it safe to keep that user's (super generic obviously) password in the front-end code for access to the db? Is there any harm in this? Am I correct in assuming that non-whitelisted IP addresses aren't able to make requests to the Atlas db? The only address that is going to be whitelisted is the IP where the web-app will be hosted, so I'd imagine I don't need to worry about someone spamming requests to rack up charges on my Atlas account or doing anything else malicious?
I'm a recent grad so I don't have much experience with secure deployment but I'm hoping I can change that this summer.
Thanks :)
I'm not sure about "best" practices, but I'll try to answer according to what I would do:
is it safe to keep that user's (super generic obviously) password in the front-end code for access to the db?
Yes you can create a read-only user. It's generally not a good idea to use a super-user to do your reads. I would only give as much access as the job requires.
Am I correct in assuming that non-whitelisted IP addresses aren't able to make requests to the Atlas db?
Correct. Only whitelisted IPs will be able to connect to the Atlas instance.
Having answered that, I personally would either:
create an API layer on top of the database to prevent direct access to the database by a client application, or
(If applicable) create a Stitch Webhook that provides a Stitch-based REST API layer on top of the Atlas deployment.
The idea is to provide security by limiting access to the database from the outside world. Using a whitelist is one layer of security. Using a REST API is further security layer that essentially forces anything that needs database access to go through a guarded gate that is under your control.
Some additional benefits of a REST API gateway:
Should your Atlas URI changes in the future, you don't need to redeploy the client applications everywhere again. You just reconfigure the REST API gateway to point to the new Atlas URI, while your client application can still use the existing REST API address with no change.
Limiting client connections to the database itself. Since only your API gateway can connect directly to the database, there is little chance that the database can get accidentally DDOSed when you have a lot of clients active at the same time.
Note that I would not consider the above to be "best" practice by any means. It's just how I would do it.

MeteorJS Removing insecure Security Flaw?

i know this is a question that has been asked many time. but im still concerned about best practice when trying to develop secure code in meteor.
i know you can prevent the client from being able to access the database with the command:
meteor remove insecure
my code currently adds, retrieves records by using Meteor.methods() so although the client is not able to insert data into a collection, it can use the Meteor.method() function. im concerned about holding the login details in the database because would this not mean that the client can use the Meteor.method() function to add/get/remove data from the database.
the client being able to call the Meteor.methods() function seems to still keep the same risk doesn't it? or have i coded me work wrong?
if it help, here is a run down of what my work is doing:
application loads
client calls to get username and password from database
client sends login details to external server (over https) to initiate socket.io connection.
step 2 is the risk because it seems to allow the client to get the login details. once it has this, it uses the socket.io.js library and the api to my webservice to login. so meteor remove insecure doesnt seem to have secured it because get methods are still available in the Meteor.methods()?
being able to use these functions are quite crucial to retrieving data from the database, is there a way around this? what would be best practice for communicating to the database without exposing private data to the client?
Meteor's insecure package is just a tool provided by MDG to quickly prototype apps. It is not meant to be runned in a production app and some people think is a best practise to remove it all together from the start.
After you remove this package, if you want to interact with the database on the client using mini-mongo you must create the appropiate allow and deny rules on the collection. Here is the link for the Meteor documentation on this topic. The other way to interact with the database, is as you said, using Meteor.methods().
Meteor methods calls don't trigger allow or deny rules, since they are runned on the server. You must hardwire all the security measures you need on the Meteor Call by yourself. So it can be a security problem if you don't take the time to secure the call.
Regarding authenticating your clients I would suggest you take a look at Meteor's Accounts package. For example you can add this two packages for basic username/password authentication:
meteor add accounts-base accounts-passwords
Then you can just use the methods detailed on the Meteor Documentation.
I hope this helps.
Login
If you are using accounts-password, you can check the source here to see details of how it works. But here's a rough overview of it. When you call Meteor.loginWithPassword, the password is hashed client-side. Then a method is called with the parameters. The password is then salted and checked against the database server-side. If it matches, the client gets logged in. The client then subscribes to their own user data (Meteor.user()). The server only publishes their data. So everyone else's data is save.
Methods
A method executes code server-side. So they are generally secure. But you can of course write insecure methods. Just know, that you can't trust the parameters passed by the user.

Host my own user authentication service on my own server?

I have tried Google with queries similar to the title of this question, but haven't found anything useful.
Background: I am building a web app and would like to add a user authentication level to it. I cannot imagine anything worse than building a user authentication system from the ground up, so I want a quick solution.
I'm looking for open source software I can host on my server that provides an auth layer I can connect to, with multiple user accounts
Criteria:
I want to host the software on my own server
Provide a log in screen that works with multiple sign in strategies - twitter, facebook, vanilla email, etc.
Persists users to a database (preferably postgres) and persists session data
Preferably lets me store a minimal amount of data per user, like key value store
Has a client-side (Javascript) API, like Facebook's JS, so I can use this auth service on multiple sites. Namely, I want to use it on localhost or my own file system (when allowing file cookies). Client side JS API exposes methods like log in / log out
Has a server side API (such as exposes local RESTful endpoints) so that when I do build out my server side app for other data storage outside of the user, my app can query the auth service for log in status.
I want to run this stack completely independently of my own app - in fact I want to run this auth service and purely communicate to it from my local dev environment without building any server side app of my own.
I have used Firebase and they do many of the things that I want, including log in strategies and the client / server side APIs, but I want to be able to host my own version of this.
I can't imagine anyone takes pleasure out of building user authentication of any kind, so I'm surprised I haven't found anything in research.
I also know this is an open-ended question, but as far as I can tell I haven't found anything satisfying my requirements.
I like Devise (https://github.com/plataformatec/devise), which is for Rails. It has an active community with a boatloads of plugins available that can fulfill many of your requirements.
I didn't see a language specified; most languages and frameworks have their own implementations. Can you provide more information?
Example: I use the Flask framework on python. In addition, I use the Authomatic library which provides Oauth access for twitter, google, facebook, etc.
What I was looking for is something called a Single Sign On solution. According to this list there is nothing currently that meets my criteria.
Instead I have chosen to just run a local webserver and implement a regular auth flow.

Kerberos, delegation and how to do this correctly?

I've got two separate homemade applications that need to communicate among themselves. One is a frontend application (asp.net actually), the other is a backend interface to an accounting application. The backend interface was not created specifically for this frontend - it is a generic interface that many other applications use to integrate with our product.
For the convenience of users we wish to provide a Windows Authentication in our frontend application. That means however that we need to pass the credentials on to the backend application which has to check them.
We do not wish to set up our frontend as a "trusted" application to the backend which can authenticate itself as any user. If the frontend was to be hacked, it would then also compromise the backend system.
As I understand it, one way to do it with Windows Authentication is Kerberos Delegation. However this requires to be explicitly enabled for the user that is to be delegated, and the machine which does the delegation (the server with our frontend). By default these options are disabled in Active Directory, and I suspect that many sysadmins will have their reservations about turning them on for all their users.
Also, I'm not really sure that this is what Kerberos Delegation was meant for. I don't need our frontend to impersonate the user that is connecting. I just need to prove that this user has authenticated itself to me.
How would you do this?
I'm not clear what you can and can't do with your use case but I can answer the question what Kerberos Delegation was meant for.
First let's talk about what Kerberos does prior to delegation. It is important to understand this part well because it is subtle.
Kerberos authenticates the identity of BOTH ends of a communication between two end-points across a network, those end-points can be interactive users or services running on a computer.
This is strong authentication so it will not allow a man-in-middle attack in any form. If set up correctly an end point can guarantee they won't be compromised. To the level of the service name (if you are connecting to IIs on a machine it is different than connecting to SQL Server on the same machine). It makes heavy use of modern encryption techniques and requires the use of secure certificates. The details of the authentication protocol are complicated and not worth going into now, but it involves about 20 different distinct steps of confirmation between the two authenticating end points and authentication server (in windows the Domain Controller is the authentication server).
So what the heck is delegation?
Delegation is a Microsoft extension to the Kerberos standard which
allows a trusted source to continue the authentication to another
end-point.
This allows you to act as a "man in the middle" -- however many settings have to be explicitly setup, certificates installed, etc to allow this to work. It is far from simple. (EDIT: Here is another SO answer on the details - https://stackoverflow.com/a/954154/215752)
So, for example, you could have someone authenticate to a website and then have the .NET code connect to an SQL Server AS THE SAME USER to read data with that user's rights.
Now to answer your question, since I'm not sure what you want to do I present three choices:
1) You want to connect to the back end system as the SAME user as the one authenticating at the website.
In this case Kerberos delegation is perfect -- it does exactly what you want.
2) You want to connect to the back end system as a DIFFERENT user than the one authenticating at the website (eg a service account).
In this case you don't want delegation. Kerberos to the website and Kerberos (as a different user) to the back-end will work great.
3) You want to connect to the back end system as the SAME user some of the time and as a DIFFERENT user other times. (For example, you need to validate this is a legal user for the back end system, but want to perform trusted actions as a system account other times. This is (in my experience) the most common use case.)
In this case you use both. Delegation for the connections which need to validate the user identity and then revert to the service account identity for the times when you need system access to the back end. (A previous question of mine went into the details of how to revert to the system identity on the .NET platform see How to "un-impersonate" (un-delegate?) in Kerberos.)
Here is a post describing how Kerberos works and how to set it up.
ASP.NET passing along Windows Authentication credentials
Actually Kerberos delegation is designed exactly for this use case. But the challenge here is craft this on a legacy system and with AD's settings that you do not want to change.
One possible hack is to have the Front End just send the user and the time of authentication but the backend can query the Active Directory Event Logs to determine whether that user has authenticated to the Front end. This requires you to use WIndows Event Log API.and also play around with Event Log settings in AD to log the issue of service tickets. (MY recollection is that this is the default)
-