best practice for storing oauth AND local authentication methods? - mysql

If I were to run a service that allowed users to authenticate via "local" username/password combinations and ALSO any number of OAuth services - what might that user data model look like?
Usually, if I were handling all logins myself, in the "user" database (assuming MySQL), the username and password fields would be required as non-null. But, if my users just wanted to log in with Facebook, I'd just store the Facebook auto token, and not have any username/password locally.
Further, what if they want to log in with Twitter creds, and then tumblr, and then whatever service-of-the-day? I could keep a field for each type, but that might get a little unwieldy. Would I be better off keeping another table of "authentication methods" for lack of a better term, so I could have a one-to-many relationship between users and how authenticate them?
Basically, I'm asking if anyone knows of an industry standard best practice for this scenario, or can point me in the right direction (or if someone has implemented something like this that works well for them). One user, multiple methods of authenticating - what's the best way to hold that info?
If any of the assumptions I've made are invalid, I apologize, please correct me.

I have no idea if my solution comes close to any sort of industry standard but I've done this in several apps before.
Identity within your application should be abstract from the authentication source.
What I ended up setting up is something like this:
User table:
id int
username varchar
email varchar
password varchar
Authentication profile table:
user_id int
service enum('website','google','facebook')
token varchar
[ For further normalization, make service its own table with service meta fields. ]
Then your auth script does something like this:
Look for username / email
Identify known authentication profiles
See if the input validates for any known authentication profiles and auth, or return invalid credentials
In cases of some services, you will either need to autogenerate some of the user field values, or prompt the user to enter during the first authentication, depending on what sort of data is available to you from the service.

I think what you want is a local authentication system (possibly for legacy reasons?) as well as support for users logging in using delegated authentication. The standard for delegated auth is OpenID. You might want to look at OpenID consumer libraries and samples, which should give you an idea of storing OpenID credentials. Unfortunately Facebook and Twitter do not support OpenID, but the flow is pretty much same, i.e. your data model will not change. We have implemented an OpenID consumer to support OpenID based login and registration. In order to support the local authentication, we have used an OpenID provider. In other words, we are both a consumer and a provider. That way, even the local auth system is standards based. Now to answer your question about schema - We have the source (local, twitter, facebook, google, yahoo, AOL) and the email as a composite key, along with the token and/or password in the authentication table. We let users change their display names, and have a unique vanity URL which is also a part of this schema. Users have an option to set up a password when coming in through OpenID, as for Mobile they'd need a password (not a whole lot of OpenID support on mobile). OAuth solves a little different use case where you're dealing with authorization more than authentication. Does this help? If you have any questions feel free to comment and I'd be glad to provide more details - I just do not want to confuse you with too much information at this point.

Related

A website tells me my password is compromised, does this imply the website is also insecure?

I recently logged into a website (student run club website which stores event and participant information).
After successfully logging in the following message appears and follows me around for the rest of my time on the site:
You are using an insecure password. The password that you entered has
been exposed in at least one data breach.
How do you know my password is insecure? This password appears in a
database of known passwords. Hackers may use this password to try to
break into your accounts.
While I appreciate the notification that my password was compromised (and should know better and will change and stop reusing passwords etc etc) I now worry about the overall security of this site.
I don't know a terrible lot about web dev but my naive assumption, given this message and the fact that it appears after log in, is that my password must have been stored in plain text for them to be able to check it against a database. Is this correct? Or is there some clever secure way this could be done?
Just because you are receiving a notification from the site doesn't mean that your passwords are being stored in plaintext. Whatever website you are using can use your password in the "Have I Been Pwned" API before encrypting them. This of course doesn't necessarily mean that they are encrypting them as there isn't really a surefire way to know how they are storing your passwords without possibly contacting the owner or if you were to receive an email at a later date with your password in it.
You can read up on the API for password checking here haveibeenpwned.com/API or you can check for the website you are using in this list here haveibeenpwned.com/API/Consumers.

Secure way of storing 3rd party databases/APIs credentials through Laravel

I am working on a Laravel app that should allow the user to manually add integration to 3rd party APIs and databases. With APIs it's easy: you only need to store the token. But the user should also be able to add integration with their own databases like MySQL. For that I'll need to store a host, user, password, basically all of the credentials. The issue I'm having is finding a proper and secure way of storing those credentials.
I was thinking about storing all of the connections in a connections table, adding the credentials to a connection_parameters JSON type field (so there would be flexibility and different types of connections can be stored in the same table) and hiding the details using the $hidden property on the model. This would be a first step towards a secure way of storing them, but I'm not sure that's enough.
Do you have any suggestions or practices you've used that you can explain to me?
I can see your main concern is to hide sensitive data from 3rd parties. What you are doing is already "ok" unless someone gets access to your database somehow. You may want to treat those fields the same way you treat users' passwords, since they also contain credentials.
One way would be to encrypt them before storing. Laravel comes with encryption/decryption out of the box https://laravel.com/docs/5.8/encryption.
Another solution is to store each user's credentials in a file and store the file in any directory but the public directory (e.g: /storage/connections). This way, only you can access those files. Each file could be named something like user_1234 1234 being the user ID. So it's easy to retrieve.

Does web browsers provide a way to identify a unique instance of it installation?

I am trying to solve the classical approach to how user login pass token is stored in web browsers. By default, anyone who can access the developer's consoles of the browser can obtain the content in password fields by looking at the HTML content of the input element or using javascript.
Because of this, if by mistake someone comes across your login password, he/she can use it on any browser to access your data from the server.
To solve this problem, I am researching a way which on an attempt to login the server will generate a unique pair ID from the client's Unique ID and let the client store this server generated ID as the user's login pass for this client only, such that if the server generated ID is used in attempt to log in from another browser, the server will compare the associated browser ID to the accessing unique ID before permitting access.
Consequently, A server generated login can only be valid on the client who generated the ID, the real password is never stored on the client, but only used on the first attempt to login on a client who does not have valid server ID. The user will have the opportunity to invalidate all the server-generated pass.
For this to work, I need a unique token from the browser such that if 10 instances of the same browser are installed on the computer within a time-space less than 1 second, the ID of this browsers will never be the same.
My question is, can such Unique ID be obtained from the browser? any suggestion on how to go about this is also appreciated.
In general, you can't uniquely identify a browser installation in the way you describe. This is, in part, to protect users' privacy from tracking across the web.
Your ultimate goal (preventing an attacker from authenticating if they discover the user's password), however, can be satisfied with a one-time-password system, like TOTP.
In a system like this, when an account is set up for one-time passwords, the user and service share a secret. Later, when the user logs in, they are prompted for a one-time password, which they generate using special software, which is isolated from the client, and ideally on another device. For example, the user might use the Google Authenticator app on a smartphone to generate a code that they enter on their desktop browser.
Even if the attacker captures the user's conventional password with a key logger, they can't authenticate themselves because they don't have access to the shared secret necessary to compute the one-time-password.
Universal 2nd Factor authentication is another approach to thwart key loggers based on some parallel concepts. (That is, it also uses a one-time code, generated with a secret that is securely stored rather than being exposed on the client.)

Best way to save external systems credentials

I'm working with an app that provides basic username and password authentication to access their API. Specific access to this api would be on an user-by-user basis and their rights in the external application. What is the best way to store these external credentials, and what is the best say to pass them back to the app?
I'm currently working with Node.js using Express, and MySQL.
I'm looking for specific technologies to possibly use? I'm a bit new, and was trying to hash them and save them to the database, but then I don't know how to send it back to the application...
Definitely don't try to roll your own security, invest in an a proper, industry tried & tested, user authentication service like:
Okta
AWS Cognito
Azure AD B2C
Auth0
And the likes, you won't regret it.
Hashing the password to store it in the database is usually the least you should do to keep this information safe. It is necessary however that the way you hash it is also an approved and secure way, so not every hashing algorithm is useful here. There are a lot of ways to do this, you should always rely on something approved, maybe even something open source so that a community can check wether its really secure or not. Usually there are security packages for every operating system that you can use that implement those things properly, you should never try to code your own stuff here in my opinion. You could check for sha-256 or sha-512 implementations for example, just to give you well known and approved algorithms that I assume often do the job.
The question I'm asking myself is why you would want to send the information back to the frontend because in most cases this should not be necessary. Once hashed in the database you should never be able to retrieve the original password anyway. If you want to verify if a user entered a correct password, you can easily check that fully on the backend side. This can be done by sending the credentials entered in the frontend to the backend (this is a security problem already which is why you should use something like ssl), then hash the password with the exact same algorithm you use to hash passwords initially and compare this hash with the hash that was saved in the database for the given user. This is a simple equals check that tells you if the credentials were correct or not and therefore telling you if the login should be successful or not. Then there is no way to send the information bsck to the frontend.
Also I'd advise to use a random string value for every new password and combine it with the password before the hashing function to create a unique string. I think this is referred to as a salt value. This way two passwords won't have the same value in the database even if they are actually the same password, which makes it more secure. When you use a salt value you have to save it as plain text in the database with the rest of the indormation though so you can use it for the equal check again later. In this case you can load the salt value of the user and combine it with an entered password again, hash it with your algorithm and check if the entered and saved hashes are equal. Both hashes should only be equal if they were generated with the same salt, password and hashing algorithm.
There is a lot more that you can do to secure this stuff, this is just a basic example of how you could achieve a relative secure login mechanism with relatively low amount of effort. It always depends on what you are trying to do, if it's a simple home stuff or maybe something for a big company and so on. If it affects a high amount of users with information that needs to be extremely secure I would recommend to use professional toolsets or services ehich specialize in exactly those kind of things.
Edit
nodejs crypto implementation
For the hashing functionality you can checkout nodejs' internal crypto service that brings a ton of functionality with it. Here's some code to give you an example of how creating a hash with a salt can look like.
var sha512 = function (password, salt) {
// create hmac instance with algorithm and salt
var hash = crypto.createHmac('sha512', salt);
// here comes the password that you want to hash
hash.update(password);
// get the hashed value
var value = hash.digest('hex');
// keep the salt for future references
return {
salt: salt,
passwordHash: value
};
};
passport authentication library
If you want to implement a real authentication you can have a look into Jared Hansons passport library. It helps you to implement all the stuff that is usually quite tricky like keeping the user logged in, making sure certain http requests are only possible if the user is logged in, keeping track of the user state or sending an authentication token to the frontend. It's still tricky to begin with, but it is still way easier than doing this on your own. Also he brings an insane amount of so called strategies with it that you can install and use, for example for oauth authentication with facebook, google, etc.

Session for user in JSP

I'm a beginner in Web Designing. I have an application which requires login. After i login on every next page i want to use the user's username for storing and retrieving data from mysql database. How to do this? Please help me out!
First: You have to learn about JAAS:
really complete and technical http://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/AcnOnly.html
In fact it depends of your application server and the login module you want to use for login (tomcat; glassfish; kerberos; database ...)
Second: Think also to reuse cloud authentication like OpenID Connect and provider like Google, Yahoo!
Third: At the end you will found information in the Principal see What is the meaning of Subject vs. User vs. Principal in a Security Context?