I'm well aware that passwords should be hashed and then saved to the database. But in my situation, I need to get the User's Username and Password in order to activate their accounts on my Linux VPS.
Depending on which server they subscribe on, they'll be reactivated on a monthly basis, so I'll need access to user passwords at all times (not just when they register).
Is there a way to store the passwords in the database unhashed or would that be too risky?
Related
I have an MVC 4 web application that requires user to login. Most of the users don't have email accounts. If someone forgot his password, how do I reset it? All the reset password systems I find require some sort of email account. I just want something simple, such as reset it to a default password, and the user can change his password once he logon using that default password. The problem is the password is encrypted in SQL Server. I can't find a tool that encrypt password.
First off the most widely used authentication implementations go to considerable lengths to prevent user credentials being stored in a reversible (i.e. plane text, or something that could be encrypted) format. Instead you should hash & salt plane text credentials and compare with a stored value.
Next to securely reset a users credentials you need to authenticate them through some other means, this is as you mention most commonly achieved through email, but if this isn't possible you should look at other out-of-band methods of authentication, perhaps send the user a SMS with a one time code, or make them answer a series of security questions. Once you have validated the users identity, force them to set a new password and override your stored hash for the user.
so we are currently using a Rails application as our primary backend but we are also using a node.js server with socket.io to allow for some realtime updating data on each page. Setting up the connections and socket.io rooms is fine right now, the issue is I need to validate that a user has permission to access the information in the room they are trying to join. What I need to do is validate that the user making the javascript socket.io request is logged in on that same session to the rails server (I.E. If someone tries to access data restricted to user X on the node server, they must be logged in as user X on the rails server). I'm using sorcery on the rails server for my account authorization.
My initial idea for this was to store two cookies in the user session when they log into rails: a session_token and their email. Say user X logged in once again, his email is X#mail.com. X's account credentials (user and password) are validated on rails and the two cookies are stored in his session. Then the rails server would store X#mail.com's session_token in the SQL database. Then X navigates to a page with a socket.io connection. Then the node server would read these cookies, find the user with that email, and validate that their session token cookie is the same as the entry in the database. If it is, they effectively are now logged in on the node server and I can give them access to the same information they would have on the rails server. Is this an effective solution, or are there potential security holes here?
I'm very familiar with Rails, but new to node.js/socket.io, so I'd ask that you are fairly descriptive when describing node stuff.
I have an ASP.NET MVC web app which requires the user to login with their domain username and password by validating against ActiveDirectoryMembershipProvider.
On login I use ValidateUser(username, password) to validate the user's credentials, and I then set the forms auth cookie so that in future requests the user is not asked to enter their username and password again
FormsAuthentication.SetAuthCookie(m.Username, true);
This is fine, but I need to periodically re-validate the user to make sure their domain password has not changed, and I don't want them to have to enter their credentials again.
One way of doing this would just be to store the user's password in plain text in the session object, or perhaps encrypting it then later decrypting it. Then I could call ValidateUser once more, and log the user out if necessary.
In other web apps where I've rolled my own auth I would simply store a hash of the user's password and compare that to the hash stored in the database.
There doesn't appear to be a single method on ActiveDirectoryMembershipProvider which would let me do that.
What is the logical thing to do here?
The answer is to periodically (every 30 minutes or so) check User.IsApproved and User.LastPasswordChangedDate to make sure the users credentials are still valid.
To do this you need to manually create the FormsAuthenticationTicket and cookie, rather than using FormsAuthentication.SetAuthCookie.
Put the date you validated the user inside UserData and compare this against LastPasswordChangedDate.
I've implemented this and it works perfectly.
More information here
Check if Active Directory password is different from cookie
Note: Although I raise this issue in the context of an iOS app, I don't think it's confined to an app running on that specific OS.
I'm developing an iOS application that will back up user data to a server and I'm trying to figure out the best way to verify server-side that the user being updated is actually the real user. Each user will have an id (uid). If that's all I depended on server-side, then I imagine the process would go like this:
User runs app for the first time
Creates account in the app, which communicates with the server to both create the account on the server and to get a unique "user id" (uid)
App stores this uid so that it can identify the user in subsequent communications with the server
However, if someone were to hack the app on their iphone, they could change the user id value and then that would instantly give them access to/allow them to modify a different user's data.
The current solution I'm considering is that the user receives 2 unique ids, the uid (just an auto-incremented number) and a longer, more complex key string. All communication with the server will therefore have to send along both the uid and the key. The server will verify that they match in order to make sure that the user truly is who the app says it is.
So, my question is two-fold:
Is this the correct way to achieve this? Or is there some other standard method that I should pursue?
If this is the correct approach, what's the recommended way to generate the unique key?
First of all, you can use the more complex value as the user ID to begin with, if you like (e.g. a UUID). Monotonically increasing IDs get hard to manage as your service scales.
You have the same problem a secure web site does when it leaves secure cookies on the browser to remember a session. Those cookies do include the user ID, but must prevent tampering. This is generally done by signing the cookie on the server before sending it back.
So what you'd do is:
Generate the user ID on the server, and use it to create some sort of "auth token" for the client to have to sign in.
Sign the auth token on the server with a secret key that only your server knows.
Send the auth token to the client, where it is stored for all subsequent logins. Transfer the auth token over HTTPS to prevent someone else from snooping it on the network.
When the app goes to login, send up the auth token to the server. If it's been hacked, the signature validation will fail, and you'll know to reject the client.
Consider including a timestamp in the signed token as well, so it expires after some time, forcing the server to regenerate an auth token periodically, which protects you in case your key is compromised. It's hard to do this all fully unless the user himself has a shared secret/password he can use to authenticate periodically as well. Depends on how far you need to go.
Other considerations: If all you know about a user is their generated UID, you don't have any way for that user to come back later from a different iOS device and restore their account there, right? Generally, if the user will be creating anything "valuable" in their account that they'll want access to later, you'll probably want to create a more traditional user account backed by an email address and password or the like, so they can access the account again after reinstalling your app. (This may or may not be relevant to your case.)
I would recommend going the "standard web browser way" and just letting the user set an email (login) and password.
When the iOS device connects to the server (using HTTPS), it uses regular "basic authentication" to log in, and receives a cookie which is valid for a set period of time. As long as the device keeps requesting data from the server within the cookie's lifetime, the cookie is renewed, and when the cookie is expired the server will automatically challenge the client to log in using its stored information again.
This has some advantages;
The user can log back into his account with a new device with a regular password reset. Easy, straight forward solved problem.
There is no special solution on the server side, any server side script can require authentication just like it would for a browser - built in functionality.
You would not have to invent your own security scheme. This scheme is used by millions of browsers every day to authenticate to web sites.
Not tied to a special phone, if the user has several iOS devices, he can use the same account from all of them by just logging in. No special set up procedures.
In other words; no special solutions for you to develop, generally solved problems how to handle login information, proven security and ease of use.
According to me, you can't really beat that :)
I am reading a great Rails tutorial and came across a passage that I had a question about:
Box 9.2.Sessions and cookies Because
HTTP is a stateless protocol, web
applications requiring user signin
must implement a way to track each
user’s progress from page to page. One
technique for maintaining the user
signin status is to use a traditional
Rails session (via the special session
function) to store a remember token
equal to the user’s id:
session[:remember_token] = user.id
This session object makes the user id
available from page to page by storing
it in a cookie that expires upon
browser close. On each page, the
application can simply call
User.find_by_id(session[:remember_token])
to retrieve the user. Because of the
way Rails handles sessions, this
process is secure; if a malicious user
tries to spoof the user id, Rails will
detect a mismatch based on a special
session id generated for each session.
For our application’s design choice,
which involves persistent
sessions—that is, signin status that
lasts even after browser close—storing
the user id is a security hole. As
soon as we break the tie between the
special session id and the stored user
id, a malicious user could sign in as
that user with a remember_token equal
to the user’s id. To fix this flaw, we
generate a unique, secure remember
token for each user based on the
user’s salt and id. Moreover, a
permanent remember token would also
represent a security hole—by
inspecting the browser cookies, a
malicious user could find the token
and then use it to sign in from any
other computer, any time. We solve
this by adding a timestamp to the
token, and reset the token every time
the user signs into the application.
This results in a persistent session
essentially impervious to attack.
I don't understand what this is saying. I take from it that a unique session ID is created and stored on the client in a cookie. Then when that cookie is sent to the server on a request, the server knows that is the user in question so that the login can be persisted. However, if a malicious user stole the cookie, I don't understand why they can't log in from another computer. The author says this is solved by adding a timestamp, but I don't see how that helps. Further, the author says that the token is reset every time the user signs in, but the whole point is a persistent sign in, so I don't understand. Please help!
You are correct—a "Remember Me" cookie can be used to steal a login. The issue that they're trying to resolve are if someone steals your cookie, containing your unique identifier, and hangs on to it—they'd then be able to log into your account at any point in the future.
The usual solution is to invalidate all previous cookies every time that you log into your account using either the username/password or the "Remember Me" cookie, so that a given cookie will allow you to login a single time. The timestamp is how they're ensuring the uniqueness of each cookie.
If you're worried about cookies being stolen, a typical solution is to also store the IP address that the request came from, and if the IP address that the cookie is coming from doesn't match the IP address that the cookie was created from, deny the login and force the user to sign in. This can be inconvenient to users who are behind dynamic proxies, or who carry their laptop to and from work/home/coffee-shop, since their IP address will change all the time.
"Remember Me" is a security hole by design. The goal is to limit how much of a hole it is, and if you're designing a system that requires absolute security, it's not a good choice. If convenience is more relevant than security, using timestamps and cookie invalidation limits the potential security issues.
If you're interested in more information on this topic, the Security Guide section of Rails Guides has an entire section on sessions.