I have written the registration page in my CodeIgniter application. Everything works fine, and it's using the PHPass library for password hashing.
Now, I want to write the login part of the system, and was wondering how exactly I'd go about doing this with CodeIgniter. I'm mostly confused about the correct (and best practice) way of doing it. Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user? Do they need a cookie? Does that cookie need to be encrypted? Do I need to track the user in my database (CodeIgniter can do this for me) and watch for IP address changes or hostname changes?
There are many many auth libraries but since you are a beginner I strongly believe that it's better to make something on your own (unless you are on a very strict time frame). Because, as my colleague once told me, without making a mistake you won't understand why better solution is actually better.
Back to your actual question.
Do I just accept the users login credentials, determine if they're correct and if so, set up a session for that user?
Well, yes. There is no other reasonable way to do it, is there? :)
Do they need a cookie?
Session ID is stored automatically in a cookie. You can store other options in a cookie, but have in mind that cookies can be stolen (so it's NOT a good idea to save username/cookie). Plus people use more than one device (e.g. tablet and desktop) more and more so be sensible about using cookies.
Does that cookie need to be encrypted?
I believe I answered that already.
You should probably start here with this: http://codeigniter.com/wiki/Category:Libraries::Authentication and http://codeigniter.com/wiki/Category:Libraries::Authorization
From CI Wiki: Authentication is different from Authorization.
Authentication answers the question “is this user who they claim to
be?” Authorization answers the question “given this user, are they
authorized to perform this action?”
Why don't you use one of the many CI auth libraries?
How should I choose an authentication library for CodeIgniter?
You can just have a look at the CI wiki for all the particular details you are after:
http://codeigniter.com/wiki/auth
Related
A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.
This is a multi-part question, so feel free to give input on any one of the parts, but since I can only accept one answer, I will accept the most complete answer in relation to all that is being asked. I will upvote partial answers if they are relevant and useful.
First, a little background, without going TL;DR on the question: I am using Quake Framework (yes, it's mine) for this project - to quickly describe it, it uses CodeIgniter and jQuery 1.8.0 mainly (among others, but they are irrelevant for the question.) It also includes the Total Storage jQuery plugin (for local storage) and jQuery Cookies as a fallback for browsers that don't support local storage.
Part 1:
I have built a user authentication system. The login has a "remember me" feature (which is not yet functional) - what is the best way to store the user's data? Some thoughts:
Store the username and sha1'd password in local storage/cookie. This seems to me to be a possibly insecure option, but I'm unsure.
Store some kind of hash (maybe PHP's com_create_guid()?) in the localstorage/cookie as well as in the database (maybe along with a date for expiry?)
Part 2:
After implementation of the "remember me" feature, what is the best way to finish implementing it? Should I have every page check for the cookie (because the user could initially hit any page and would need re-logged?) While each page of course needs to check the session, and once they are re-logged by the cookie/local storage, they will get a regular session, it seems very redundant to check for both a session and a cookie on each page (we'd of course first check for a session so that we don't check cookies of logged-in users repeatedly, and then check for the cookie if there's no session, but still.) Is there a better way?
Part 1
It would be best to generate a random token(hash you mentioned) in the server, and save it both in the DB and cookie. Making it random will prevent others from "guessing" or generating your token. Using a GUID would be your best option.
Part 2
In each page, you can check if a session exists. If no session is available, check for your auth cookie. If auth cookie is available, trigger your auth-check code. That way, you only need to check the auth cookie when user is not logged in already.
I have a classifieds website, and I am about to create a members login section of the site.
I don't need anything advanced, just secure!
This is what I need in terms of functionality:
Website beeing able to recognize members so they don't have to login again (remember me)
Changing of their passwords and profiles
Logout page which removes the "remember me" so that website doesn't recognize next visit as "logged in"
Users beeing able to navigat while still logged in (kind of like the first functionality with "remember me" feature)
This is what I am thinking:
Create a MySql (I use MySql btw) table which contains Usernames, passwords etc.
Then create a "SESSION" in PHP and set a cookie to remember the user.
This cookie will have something like this value in it:
md5(IP.username.secret_word)
which I compare on top of each page so that the user is in fact the same user.
Next I need a logout page, which I am thinking of just deleting this cookie and destroying the session. Should be enough?
As for the still logged in feature, I will use the same method as the first remember me, which is to check for the cookie.
Is there anything I need to think about before doing this?
Sql injection, hacks, security flaws?
This isn't a bank or something which needs alot of security, but I would feel much better knowing it isn't easy to hack it.
One thing I am not sure about is the Session cookie. Is it any different from a regular cookie? Is it this cookie I should set when I use the "remember" feature?
Also, another last thing: If say 100 users are logged in at the same time, it means 100 sessions are running, will this slow down the performance of the website? (guessing yes).
Correct me, give me advice and information on how it is best done?
Thanks
My recommendation would be to avoid attempting to re-invent this particular wheel. Good security is hard to do, but there are some excellent libraries available to do the job for you, e.g. Zend Auth.
you should look at implementing openID - http://openid.net/
Is there anything I need to think about before doing this?
Sql injection, hacks, security flaws?
Yes. Do you really expect us to explain how to avoid all of these?
md5(IP.username.secret_word)
Don't use the clients IP address in any way as an identifier. While the approach you suggest would not be undermined by multiple users connecting via the same proxy, it won't work for users behind a cluster of load-balanced proxies.
I'd certainly recommend using separate cookies for the session and 'remember me' functionality (former should be a session cookie, latter with long expiry, both with HTTP only). Reasons should be obvious. Don't invent your own method for naming session cookies - they are random for a reason. For preference implement at least the login page over SSL and set the secure flag on the remember me cookie. (Which means that in the absence of an authenticated session you'll have to redirect to an HTTPS page to check the RemeberMe cookie).
it means 100 sessions are running, will this slow down the performance of the website? (guessing yes)
Yes, of course it will - but the difference will be so small that you'll not be able to measure it until you get to 10,000+ sessions.
You're almost there.
Just encrypt(hash) the password before putting into the Database. When users forget their passwords, you can't give them the original ones, so generate a random password for them and let them change it afterwards.
You could use SSL or another safe surfing method while they are on the login page.
You could limit the login to 3 try's in 5 mins, CAPTCHA, or something like that, to prevent automated bots.
Log ip, time and login try's and other things in DB for future investigation.
Use Mysqli or some other OOP method for DB connection and query's for possible injection hacks.
I would like to make a simple user login/registration system using PHP and mysql. I don't need to get any information beyond what is necessary for the user to log in and out. I want to make sure that the system is secure.
The way that I currently understand how it should work is:
Registration
User enters their email address and password and confirmation password.
The PHP script makes sure the passwords match and that the email is a valid address and is not already in the database.
It hashes the password along with a random salt and stores the salt and resulting hashed password in the database. (Is php's md5 function suitable for this? I am not quite sure how this part works.)
Store an email confirmation code in the database and send the given email address a link back to the website that contains that code for verification?
Login
User input their email address and password.
The server looks up the email in the database and retrieves the salt. Then hashes the salt with the password the user just provided to see if it matches the one in the database.
How do I make the session persist after login. With a PHP session? A cookie? What should get stored in the cookie for remembering the user between visits?
I basically would just like some verification that the process I am describing is an accurate and secure way of doing user registration/login. Also, what are some good tutorials with more information.
Is php's md5 function suitable for this?
MD5 is no longer considered secure; consider using PHP's newer built-in password hashing with the bcrypt algorithm which has variable computational complexity: PHP password_hash() and password_verify().
How do I make the session persist after login. With a php session? A cookie? What should get stored in the cookie for remembering the user between visits?
Ideally, you would use a PHP session to maintain state during a single visit, and if you would like to have a "remember my login" option, you would use a cookie that contains enough information to authenticate a returning user and restart a new session. There's a good article from 2004 on best practices regarding login cookies here: Persistent Login Cookie Best Practice. You might also be interested in a more modern (2015) solution to securely implementing "remember me" checkboxes.
Apart from these, I think whatever you have described is fine.
A few notes on some missing considerations:
PHP sessions typically already use cookies: the session ID is stored as one.
Sessions can be hijacked; you should also take steps to reduce the possibility (start by reading "PHP: Preventing Session Hijacking with token stored as a cookie?" and "What is the best way to prevent session hijacking?").
Related to hijacking is fixing, where an attacker picks the session ID. There are two ways of combatting this: set session.use_only_cookies (the default in PHP >= 5.3) and change the session ID when a user logs in with session_regenerate_id.
Also see the question "PHP Session Security" and article "PHP Security Guide: Sessions".
if you want a ready made solution
User Cake in php5
pretty much secure .. and stable.
Since Login systems are such an integral part of a website, you're screwed if it gets hacked. Unless you're doing this for educational purposes, I recommend finding a system that was created by someone that has experience in the field. You'll sleep soundly at night.
An example of a solid pre-built login system is tank auth, it's written for the Code Igniter framework. You might want to look at how this guy designed the system to get ideas on what's important if you decide to write your own.
Also just a note from experience, it takes more time to write a login system from scratch than it does to learn the code igniter framework and install tank auth.
Here's a recommendation: consider using a readily available framework that inherently provides such functionality. they are tried and tested. have a look at Kohana. It has an Auth module which takes care authentication.
I'm looking to implement user login onto my site for the first time. I'm happy to either build my own solution, or implement something open source, however no package has been an obvious choice in my search so far. Equally, I'm fully aware that as an intermediate php programmer at best, I am highly likely to miss something obvious if I roll my own solution, and leave the doors well and truly open.
Any suggestions? We're not talking super sensitive or payment data here, but equally, I'm keen not to have people mess up my site!
requirements are
- php based
- simple as possible, not need for fancy bells and whistles
- not Zend framework, since i've now rolled my own very basic frameworkthanks to this post
Thanks for your input.
A few good security gotcha's are
never store the an un-encrypted users password in the database
never store the users password or even a hash of the password in session or cookie data.
If you need to have ensure that the login is secure you have to use https.
I found these article very helpful in building login systems with cookies:
blog post on the fishbowl.
Improved Persistent Login Cookie Best Practice
"You'll put your eye out kid."
Security is hard. I hate to say this, but the odds of you making a simple authorization scheme that is secure are quite slim. There is no easy mode here. So you might want to start by reading through a bunch of authentication code in the various frameworks/cmses, and other places where you can see how others have done it, and begin researching.
Here are some links:
http://www.topmost.se/personal/articles/casual-cryptography-for-web-developers.htm
http://pear.php.net/packages.php?catpid=1
I find that for some uses, building my own using http authentication is sufficient. I'd recommend this as a starting point.
Since you have your own basic framework, it should not be too difficult to include the authentication code in some place that is common.
Some advantages are
Not a lot of code.
Does not require
cookies or URL rewriting.
Disadvantages
Doesn't scale well to more granular
access control.
No easy way to "log
out".
--
bmb
This is not that hard, and fun to code, as a beginner.
You need a place to store your data (let's say a mysql database).
You should at least have a login field, and a password field. (the password should be stored crypter using sha1() for instance).
Now, you have to display a login form. I assume this is ok for you.
What is to be done, whenever we get the login and the password?
Query the database to see wether there is a match with login_base == login_form and password_base == sha1(password_form).
If yes, you set something, like a session for instance.
So on a page where one should be logged, you only have to check if there is a session set.
This is for the basis; then you can add some levels and so on.