I have designed a website which uses AJAX. I have a PHP page named store.php which accepts data sent by POST method and stores in the database.
How do I implement authentication into store.php? I only want a user logged into my site to use store.php.
Currently I am using htaccess to redirect the requests for store.php but I don't think that is a good solution.
Any AJAX Call to a Server Script will still include the session id in the request. If you are implementing sessions in your site, then start the session and you will be able to see session variables for the currently logged in user.
Store a token associated with the user in your database. Make sure that the token will be unique and not guessable. Also store the same token in a hidden form field so that it gets posted back to the page. Ensure on the server that the token is present in the posted form values and check that it is valid.
The security of Ajax requests is not a simple matter. They can be susceptible to man-in-the-middle attacks and replay attacks, to name a few. I'd recommend reading this book: http://www.amazon.com/Ajax-Security-Billy-Hoffman/dp/0321491939. It will give you lots of good information on the subject.
As for your question, specifically: once your PHP session has been set up, those session cookies will apply to Ajax requests as well.
What you are looking for is a persistent state for the user. The best way to implement this in PHP is to utilize sessions.
There is great documentation on it: http://www.php.net/manual/en/book.session.php
I normally just include the exact same code I use to authenticate on the rest of my site in the ajax-called page. I use SESSION to hold a sessionID, and the rest is handled in my DB. I usually end up just adding a line like this..
require_once('loginProcedures.php');
//Login Authentication takes place here using SESSION ID
if (!$me['validLogin']) die("Invalid Authentication");
//perform actions and echo your result for a valid login.
Related
I am trying to prevent CSRF in php in the following way:
A $_SESSION['token'] is generated at the start of each page. I already know that using $_COOKIES is completely wrong since they are send automatically for each request.
In each <form>, the following input: <input type="hidden" name="t" value="<?php echo '$_SESSION['token']; ?>"> is appended.
The $_SESSION['token']; is validated with the $_POST['t']
Now I have several small questions:
Is this a good way to prevent CSRF? If not please explain.
When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?
For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?
Thank you very much in advance.
Is this a good way to prevent CSRF?
Yes. What this does is to force the client to do a GET on the form before it can do a POST to your form handler. This prevents CSRF in modern browsers since browsers will prevent client-side Javascript to do an XHR GET request to a foreign domain, so a 3rd party cannot imitate your form on their site and successfully get a valid token for the submission.
When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?
Allow several tokens to be valid at a time, keeping an array of valid tokens in the session. Alternatively, store no tokens at all and use a token signing scheme instead. I've dabbled in and explained that here. Alternative 2: just use a single token for the whole session, without invalidating tokens. (tip o' the hat to #SilverlightFox in the comments)
For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?
No. You only need to protect POST requests since presumably only POST requests can alter sensitive data (wink wink nudge nudge, you're sticking to REST conventions, right?!) and XHR GET requests are already blocked browser-side.
CSRF attack occurs when a hacker tries to send a fake request from an authenticated user. normally this attack occurs
in online shops or banks.
Prevent csrf attack in php we can:
1 = Create a check login function:
If the login session is set that is true Ok, if not false and return to login page.
2 = create a random makeToken hash function with: base64_encode(md5(microtime())) and save it into session and create a input hidden type with token name and the value with name Token's function.
3 = Create a checkTocken function and check it, if it is equall to makeToken function, and after that use unset function to unset the session, and create a new one.
Are cookies necessary to create a login page with php (that keeps you logged in across several pages), or could a session variable do the trick without use of cookies?
Answer simply is yes.
Sessions rely on a session id.
Sessions in php use a cookie to store this id, but you can change it to append the id to each url instead of saving it in cookies.
ini_set('session.use_cookies', false);
in the config variable url_rewriter.tags, you see which URLs automatically get rewritten to append this id:
"a=href,area=href,frame=src,form=,fieldset="
As Pekka mentions, jQuery requests and special JS/Ajax/jQuery calls are not getting rewritten by default and you have to append the id manually like:
<script>
$.get('/yourpage/?PHPSESSID=<?php echo session_id(); ?>');
</script>
the session name can be obtained via session_name();, default is in the config variable: session.name.
Use ini_get(); or phpinfo(); to see your configuration.
Actually if you are using sessions you can use a cookie or a special GET/POST fields to identify yourself towards the server. The server then using the user id, passed either by GET/POST or a cookie - knows which data set is connected to the current user/client at server side. This way using sessions you can store data at server side with only sending a special user id to the client.
This way you can save login data for each user, thus login functionality can be implemented using sessions in PHP.
And yes, you can solve login with no other cookie just the Session user ID, or use the POST/GET session id.
Typically sessions are more reliable when working with keeping a user logged in. Sessions are stored on the server, whereas cookies are stored client sided. So that falls down to: do you want your login dependent on something the client can control and manipulate?
I've had first hand issues with logins being hacked with cookies, so I suggest sessions.
No, you do not need cookies in order to set up a login system, sessions suffice. However, if you seek a "Remember me" option, you need cookies in order to keep the user logged in beyond the point when the user closes the browser or the session expires.
http://www.php.net/manual/en/features.sessions.php
For maintaining a session with server, you need to identify yourself (your page) to server. So that server can keep track of your page's subsequent request and maintain a session.
So, if you only have username and password option on your login page, then cookies may not be required. Refer to the following link:
Passing the Session ID from page to Server
You can have a special URL which will have identifier as part of URL, which will inform server about your subsequent request.
However, please note that using this type of special URL is not always the recommended approach. Because this is insecure than cookie based session. For example, someone may paste their own link on a chat or in an email, and other person will be entered to your site without username/password.
You can do authentication without cookies (or sessions which are a special case of cookies) but it won't be on a page. This method is called HTTP Authentication.
I am using PHP and Codeigniter to do this. Currently I am just saving a cookie to the user with their username and a $logged_in variable set to true. Then when they try to access a page, I check for the status of their $logged_in, and if they are, they're free to access.
It occurs to me that this may not be the safest way to go about this. Is there a better tactic I should be using?
It's not safe at all. Cookie is considered user input and it can't be trusted in any case.
Use sessions instead.
Also you could use some sort of custom login encrypted code (I'd personally suggest SHA1) that is matched against the login code in the database and is refreshed every, let's say, 5 minutes.
CodeIgniter offers a nice solution to this problem - You can use Database Sessions.
With Database Sessions, all the data you put in a session is stored within your SQL database. The user gets a cookie with a unique session ID that changes on a regular basis. The session ID along with IP and User Agent is used to match up the user with their session data, thus making it impossible for users to tamper with their own session data, and very hard for them to hijack someone else's session.
You can read more about CodeIgniter Database Sessions in the CodeIgniter User Guide.
Good Day,
I am creating a webpage that users login called "index.html" which POSTs data to the "home.php" site when the user submits the form from "index.html." Now that I am inside the "home.php" I can retrieve the posted variables, check them against the database and authenticate the user. Once I am in the "home.php" file, I would like the user to issue a GET request to the "home.php" site to display different data. Is there a way to do that and maintain the authentication?
Right now I am getting a notice saying that the POST variables are undefined. (Obviously, since I am not posting anything)
Notice: Undefined index: pass in C:\xampp\htdocs\home.php on line 7
Thanks,
Matt
It sounds like you want to use sessions.
See: http://www.w3schools.com/php/php_sessions.asp
See: http://www.tizag.com/phpT/phpsessions.php
Once you perform your initial authentication check, which would be the form submission and account verification, you should assign the user some form of session token. This is a token that you can verify is authentic that you use for a short-hand verification for subsequent requests. You can create this token a few ways:
Create a simple table to keep track of authorized session tokens and their expiration date. This ensures that only sessions you create are allowed, tied to a single account, and have a guaranteed expiration date.
Create an encrypted token format so the session token is actually an encrypted data container which you can only read on the server side with a private, rotating key. The token would contain information about the user and expiration and eliminate the need for a server side table.
In addition to the basic information for each token it would also be good to include references to the UserAgent and IPAddress of the initial authentication request so you can ensure there is no session hijacking taking place.
Once you create your token you will want to store it in a cross-request location; which can be either a session or cookie variable. This is primarily a preference, but either way, you should ensure it is only accessible from an HTTP request and not a JS request to prevent XSS (cross site scripting). Check out these artickes on sessions and cookies:
http://www.w3schools.com/php/php_sessions.asp
http://www.w3schools.com/php/php_cookies.asp
Now that you have a token you can use from anywhere in your site you will want to make an authentication handler for each of your pages to check this token and verify it is valid. Once you confirm it is authentic you can use it to figure out which user is viewing the page and what permissions they should have.
Do this
$pass = isset($_POST['pass']) ? $_POST['pass'] : null;
You can for example do that :
echo "<form method='post' action='home.php?parameter1=".$variable1."'>";
Then you have both POST and GET variables.
Edit: But I think I misunderstood you, use SESSION variables to persist the authentication through pages.
I'm currently building my own login script and have noticed that most append the session ID or similar to the logout page as a get variable.
Why do they do this?
Is it not just safe/easier to just the destroy the session on logout.php and not pass in any ID?
I cannot think of any reason why they would need to add a get param only when logging out.
Adding some token to an URL can be used to prevent abuse or when the session id is added to the url to also make session work when cookies are disbled on the client side.
Update
From the linked article:
However, a quick view of the file shows a fairly interesting issue. It requires the signature computed by logging in to be presented to the user to submit to the login page. Presumably this was done as a form of CSRF protection. However, it also leaks the data necessary to take over a session to the user. So we come to our 11th vulnerability so far:
UPDATE2
I've asked ircmaxell in chat. And yup it is because of CSRF protection.