Parse Server Two Factor Authentication or Additional Admin Security - security

I am running the open source parse-server and have well secured my database. However, my application requires administrator users which need to have the power to read and write nearly all the data. This is a security concern which I would like to address with two-factor authentication, though I am open to other ideas (IP whitelisting, cookies, or whatnot).
Setting this up on my client apps is straightforward enough and I have done that, but I would like to be even more secure so that if malicious agents have my Application ID (which is basically public) and somehow obtain an admin's credentials, they still cannot gain access.
I am puzzled as to how to accomplish this with the parse server as it is today. There are no Cloud Code triggers for User sign-in, so I can't enforce any MFA on the Parse server itself, as far as I can tell.
One possibility I see is to use check some MFA token in various Cloud Code routines, such as beforeSave, beforeDelete, and beforeFind, denying access to an admin user lacking proper MFA. Would that completely prevent a false admin from reading or writing all data?
The above option does not prevent the attacker from trying to brute force the MFA (assuming it's a 6-digit code). I also don't see any way of rate-limiting the login attempts of an attacker with the App ID and admin password. Any ideas here?
Thanks for any tips!

I really like the idea of adding 2FA and a small script to manage user accounts on the dashboard.
Can you open a feature request on https://github.com/parse-community/parse-dashboard ?
Also, for use authentication, you could probably use a custom auth adapter which would validate the username, email and 2FA token

Related

Node Server, is a database necessary for basic authentication if using oauth?

I'm learning Node, doing authentication stuff at the moment with passport.
Say my server has 2 pages, a public home page with various login options, then a super-secret page(and perhaps more) that is only accessible after authenticating.
If I'm only going to be using 3rd party strategies, is there any reason to have a database?
I know that you'd obviously need one for local user's id and pass, but if the server exclusively relies on 3rd party authentication, would session persistence be enough things to work? Or are there still various things that you would need to save for some reason (apart from logging) ?
Could you do without a database, sure... but in this case what is the point in authenticating at all? All you would be proving is that the user has a Google account which anyone can set up for free in a matter of minutes.
If your content is super secret then chances are you want to have a database of users (email addresses and the like) that have permission to see the content. By authenticating through OAuth you will be given an access token that will allow you to fetch the authenticated users email address. This can then be looked up against your user table to see if the user is registered and if your app enforces it, check whether the user has access to the page requested.
OAuth is proving that this person is the owner of the Google/Facebook/Twitter/Github Account. You can use this knowledge to sign someone in against a database of "local accounts" based on email used at sign up, assuming you validate the email on sign up locally.

Confirming user credentials in Facebook/Google OAuth2

Scenario: I have been developing a web application for management of small and medium-sized enterprises. Some time ago we used login and password authentication that were stored in our database. Nowadays when "everyone uses facebook" we moved to Facebook/Google OAuth2 authentication as well.
The problem is, there are some key operations that have to be especially secured (e.g. changing addresses, accessing clients' details). The best way to do this is I guess to ask users for retyping them credentials just before these risky operations are executed. But, since I use social authentication I can not confirm credentials anymore :(
Is there any way that I can force Facebook or other OAuth2 provider to re-ask users for credentials even they are already logged in?
I think this may be useful for someone.
I have found such a credentials confirmation implemented on https://www.airbnb.com but only for facebook.
AirBNB uses
https://www.facebook.com/login/reauth.php as an authentication url
Facebook re-authentication mechanism is described widely here:
https://developers.facebook.com/docs/facebook-login/reauthentication
For Google it is possible to force re-authentication by setting max_auth_age parameter to 0
No prompt for re-authentication with OAUth2. Why and how to force it?

securely authenticating users as a third-party

Let's say i'm writing a program or app that requires me to authenticate users on their behalf, i.e. ask a user for their credentials to log in to a website or something to retrieve and process data.
How can i do something like this in such a way that the user's security is guaranteed, preferably so that i can't even see the credentials they've provided at all. And if this is not possible, how can users be assured that their privacy and security is not compromised in any way.
Simplest answer, but probably not useful to you is:
You can't guarantee privacy and security are not compromised! And as the admin on the server, if you receive and store user credentials, you could access them.
Immutable Law #6 of Security: A computer is only as secure as the administrator is trustworthy
So think about what level of security you would accept as appropriate.
You could use something like OpenID, like StackExchange uses - it removes the authentication piece from their responsibility. Only the OpenID provider receives credentials - SE just gets a token from them.

How to keep the client credentials confidential, while using OAuth2's Resource Owner Password Credentials grant type

We are building a rest service and we want to use OAauth 2 for authorization. The current draft (v2-16 from May 19th) describes four grant types. They are mechanisms or flows for obtaining authorization (an access token).
Authorization Code
Implicit Grant
Resource Owner Credentials
Client Credentials
It seems we need to support all four of them, since they serve different purposes. The first two (and possibly the last one) can be used from third-party apps that need access to the API. The authorization code is the standard way to authorize a web application that is lucky enough to reside on a secure server, while the implicit grant flow would be the choice for a client application that can’t quite keep its credentials confidential (e.g. mobile/desktop application, JavaScript client, etc.).
We want to use the third mechanism ourselves to provide a better user experience on mobile devices – instead of taking the user to a login dialog in a web browser and so on, the user will simply enter his or her username and password directly in the application and login.
We also want to use the Client Credentials grant type to obtain an access token that can be used to view public data, not associated with any user. In this case this is not so much authorization, but rather something similar to an API key that we use to give access only to applications that have registered with us, giving us an option to revoke access if needed.
So my questions are:
Do you think I have understood the purpose of the different grant types correctly?
How can you keep your client credentials confidential? In both the third and fourth case, we need to have the client id and client secret somewhere on the client, which doesn't sound like a good idea.
Even if you use the implicit grant type and you don’t expose your client secret, what stops another application from impersonating your app using the same authorization mechanism and your client id?
To summarize, we want to be able to use the client credentials and resource owner credentials flow from a client application. Both of these flows require you to store the client secret somehow, but the client is a mobile or JavaScript application, so these could easily be stolen.
I'm facing similar issues, and am also relatively new to OAuth. I've implemented "Resource Owner Password Credentials" in our API for our official mobile app to use -- the web flows just seem like they'd be so horrible to use on a mobile platform, and once the user installs an app and trusts that it's our official app, they should feel comfortable typing username/password directly into the app.
The problem is, as you point out, there is no way for my API server to securely verify the client_id of the app. If I include a client_secret in the app code/package, then it's exposed to anyone who installs the app, so requiring a client_secret wouldn't make the process any more secure. So basically, any other app can impersonate my app by copying the client_id.
Just to direct answers at each of your points:
I keep re-reading different drafts of the spec to see if anything's changed, and am focused mostly on the Resource Owner Password Credentials section, but I think you're correct on these. Client Credentials(4) I think could also be used by an in-house or third-party service that might need access to more than just "public" information, like maybe you have analytics or something that need to get information across all users.
I don't think you can keep anything confidential on the client.
Nothing stops someone else from using your client id. This is my issue too. Once your code leaves the server and is either installed as an app or is running as Javascript in a browser, you can't assume anything is secret.
For our website, we had a similar issue to what you describe with the Client Credentials flow. What I ended up doing is moving the authentication to the server side. The user can authenticate using our web app, but the OAuth token to our API is stored on the server side, and associated with the user's web session. All API requests that the Javascript code makes are actually AJAX calls to the web server. So the browser isn't directly authenticated with the API, but instead has an authenticated web session.
It seems like your use-case for Client Credentials is different, in that you're talking about third-party apps, and are only serving public data through this method. I think your concerns are valid (anyone can steal and use anyone else's API key), but if you only require a free registration to get an API key, I don't see why anyone would really want to steal one.
You could monitor/analyze the usage of each API key to try to detect abuse, at which point you could invalidate one API key and give the legitimate user a new one. This might be the best option, but it's in no way secure.
You could also use a Refresh Token-like scheme for this if you wanted to lock it up a bit tighter, although I don't know how much you would really gain. If you expired the Javascript-exposed api tokens once a day and required the third-party to do some sort of server-side refresh using a (secret) refresh token, then stolen api tokens would never be good for more than a day. Might encourage potential token thieves to just register instead. But sort of a pain for everyone else, so not sure if this is worth it.

Secure Way of storing Passwords to APIs without OpenID?

I asked a similar question here a while back but all the answers were offering OpenID which is nice but it doesn't work with services that require authentication that don't use it (such as EventBrite).
Say I want to create an app that lists your events from event brite, and their analytics (which eventbrite includes). Any person can sign up for this service to list their events. But since EventBrite doesn't have OpenID to authenticate, I need to somehow get the user login and password to EventBrite.
Some possible solutions are:
Store credentials in YAML like this. Easily hackable.
Have user enter in credentials into a form on my site, I save the credentials to my database, and use them to login to EventBrite. Easily hackable.
Have user enter in credentials and I pass them directly to EventBrite without saving, and I save the response header Cookies to the database, and when they expire, have them login again. Is this easily hackable?
This hypothetical service also wants to automatically check events (say via cron), so it doesn't depend on the user going to my site via the browser. So cookies or credientials need to be stored somewhere.
The thing is, after asking this similar question about confidentiality and security it sounds like you should never build an application that does what I'm describing. There's got to be some way building something like this is okay.
What is that way? What am I missing? Is it okay to go with #3 and save the cookies (but still needing the user to submit their email/password via a form which I send to Eventbrite)? What is an acceptable solution to the problem?
There isn't a secure way to do this. You can employ workarounds, but that's about it.
Storing passwords in YAML or XML in cleartext is definitely out
In fact, even encrypting and storing passwords is wrong. Your application would need a way to decrypt the passwords, so the attacker can also decrypt the passwords.
The recommended way to store passwords is Salt + Hash, but because it becomes unrecoverable, it is useless in your case.
Because of 2 & 3, no matter where you store the users credentials, you are vulnerable.
Storing the cookies instead of the passwords is a better idea. But again, this involves the password going through your website, which isn't good.
Given your situation, storing the cookie is a better approach. Use HTTPS throughout, even on your website. Its less than ideal though, and you and your users should be aware of it.
Eventbrite has recently release new documentation describing how to implement OAuth2.0 for cross-site user authentication.
I would recommend using our javascipt-based OAuth2.0 widget, which stores the user's authentication tokens in their browser's localStorage by default.
Since the auth tokens are stored in the user's browser, and are prevented from being accessed by other domains, it's not likely that there would be any security leaks.
The need for email and password combos are completely avoided in this authentication scheme.
Most sites only support direct login with the original cleartext password, so you have to get, store and provide that too. And I would never ever trust you with that.
The problem with your concept is that you require the password to be given to a third party. The solution is not to involve a third party, for example my browser is pretty good at storing and filling in passwords for me automatically (my hard-drive is password protected too). And they are dozens of other password wallet apps too. I wouldn't gain anything by subscribing, using your service.
Before going into such a business, consider you are going to be the #1 target. Facebook, Google are incredibly paranoid about security, spending a lot of time, money and effort to keep the logins safe. Do you have the same resources? Then you are a better target. Also by hacking your service, they immediately get multiple accounts, passwords of your users, also seeing who is always reusing its password.
For working with the Eventbrite API, I'd recommend ensuring that all connections are over SSL, and that you authenticate using a user_key rather than a username and password.
More information about authentication for the Eventbrite API is here: http://developer.eventbrite.com/doc/auth/
After logging in, users can find their user_key here: http://www.eventbrite.com/userkeyapi
This should prevent username and password information from being intercepted over the wire, or read from a local data store.

Resources