Gossamer Forum
Home : General : Perl Programming :

Authentication Logic

Quote Reply
Authentication Logic
Argh. I can't get my head around the logic behnd authentication someone to use a script.

I currently have a sub called &check_credentials; at the top of my script which is called before any other thing happens. This basicaly checks to see if you've got a cookie. If not, returns you to an error page.

However, I can't ever login now because it alwasys takes me to the error_sub because I don't have my cookies.

Argh :-\

How do others make sure that a user is authenticated at every page he or she visits? But keeping overheads down? In my authentication sub it only checks to see if a cookie exists - I don't want to make a database connection to verify the cookie as this would have to be done for every single page loaded. Is this OK?

Cheers

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
Can you make some sort of session system? Otherwise you would just use the one connection on the login page that sets a cookie.

Do a query, select username from USERTABLE where username='$username' and password='password'

a result means they placed the correct login details in. Set a cookie with the username in it as the value. If the cookie exists they are logged in, and you can get information about them on each page if you want cause you have there username in the cookie.

A session system is usually a good option...
Cheers,
Michael Bray
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
Yeah, what I do now is when the user logs in it sets the username and password to the cookie.

But because it checks for a cookie before an subroutine executes in the script, it produces an error and never displays the login page - because there haven't been any cookies set the first time you visit?

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
The way I do it is I set a cookie when someone logs in containing a non-encrypted username and an encryted password. It expires in two hours.

Then I have a module to do the authentication. On the pages that only member should be able to access I do:

my $REC = Module->auth;

This check the cookie and compares it to the user record in the database. Doing this once per page is not going to slow things down. If the user is valid auth() return the user record as a hashref so I can send $REC to my template parser and put corresponding tags in my templates like: Welcome <%Username%> ....if they aren't authenticated they are taken to an error page with:

Code:
if (!$REC) {
print $IN->header();
print $TPL->parse('error', {} );
}

This works nicely. When the cookie expires they are logged out.


Quote Reply
Re: [RedRum] Authentication Logic In reply to
Thanks for the reply. Does that mean you make a call to my $REC = Module->auth; at the top of every sub?

I was trying to avoid this by putting this once at the very top of my script but then encountered errors for people that weren't logged in but were trying to.

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
Why set the password in the cookie?

Code:
function is_logged(){

$cookie_exists = $HTTP_COOKIE_VARS['username'];

if(!$cookie_exists){
redirect_to_login();
return false;
} else {
return $cookie_exists;
}

}

Thats just non sense writing there - but something along those lines written into a perl sub routine and then placed on the top of each page should work?
Cheers,
Michael Bray
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
Sorry - didn't see paul had replied. i started the reply during an ad on tv and finished it during the next ad break. paul's method is probably better... but why not set the cookie to expire in 2 hours and not do a check on each page in the DB?
Cheers,
Michael Bray
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
I'm not writing the password now, I realised that was a bad idea. I just write their username and a 0 or 1 to indictate if they are logged in or logged out.

I'm doing something very similar (but very simple now). At the top of each page there is a call to &check_credentials; and then in check_credentials there is simple code:

Code:
sub check_credentials {

my $true = $query->cookie('true');

unless ($true eq "1") {
&login_prompt;
exit;
}
}

The cookies do expire in 2 hours, anyway.

- wil

Last edited by:

Wil: Jan 4, 2002, 3:05 AM
Quote Reply
Re: [Wil] Authentication Logic In reply to
My method leads me to the question.. Can someone set a false cookie? In other words, my cookie looks like this:

Code:
$cookie_user = $query->cookie (
-name => 'user',
-value => $user,
-expires => '+1d',
-path => '/',
-domain => 'staff.fbagroup.co.uk'
);

$cookie_true = $query->cookie (
-name => 'true',
-value => '1',
-expires => '+1d',
-path => '/',
-domain => 'staff.fbagroup.co.uk'
);

Now would it be possible for someone to write that exact script on their own server and set a cookie for a different server? Ugh, I'm not very good with my English.

Is it possible to set a cookie for a server other than the server the script executed on. If so, it would be very easy to pass my system, right?

- wil
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
>>but why not set the cookie to expire in 2 hours and not do a check on each page in the DB?
<<

Because anyone could then create a fake cookie and gain access. By setting the username/password in the cookie I can make sure they are really allowed to access the members area.

Module->auth is like 10 lines of code so calling it isn't going to make any real impact on execution speeds. It isn't needed in routines producing welcome pages and pages that non-members can access, it is only needed at the top of routines producing member pages.

To check a cookie and select a record from mysql takes milliseconds so it isn't going to be noticed and gives greater security.


Last edited by:

RedRum: Jan 4, 2002, 3:10 AM
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Yeah, but if you're running a busy site, with each page calling a MySQL call to checj authentication then you're looking at big overheads?

- wil
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Yeah - I didn't think about people faking the cookies. I use PHP's built in sessions. They are stored on the server so I don't need to worry about people faking them.

Store username and password in the cookie and do a check on each page - or better yet, use sessions :)
Cheers,
Michael Bray
Quote Reply
Re: [Wil] Authentication Logic In reply to
>>Yeah, but if you're running a busy site, with each page calling a MySQL call to checj authentication then you're looking at big overheads? <<

Not at all. One query is almost negligable....take GossamerForum as an example.....127 queries alone for the main page and thousands and thousands of hits per day.

Last edited by:

RedRum: Jan 4, 2002, 3:27 AM
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Jeepers, why so many queries for the GT forum?! :-)

OK. So can a cookie be faked? Can I set a cookie for a server that is not mine or not from where the cookie orignated?

- wil
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
Is there a similar session thingy in Perl? Or I guess I would have to make a seshion table in a database? But I'd still need cookies for that..

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
>>So can a cookie be faked?<<

Easily. Alex posted some code a while back to do it. So with my method faking a cookie would be useless as you'd still need to know the username/password and encryption seed to be authenticated.


Quote Reply
Re: [Wil] Authentication Logic In reply to
Ok it was 108, take a look:

http://www.gossamer-threads.com/...h_string=127;#174277
Quote Reply
Re: [RedRum] Authentication Logic In reply to
So mine can easily be faked. All you need is to know someone's username. :-(

I hate this.

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
Paul,

Just because GForum had 127 queries does *NOT* make it good practice. 127 queries puts a huge load on a program like MySQL - a busy forum could potentially have a few simultaneous people load the main page. Imagine MySQL getting 400 queries all of a sudden, even if they are simple queries the sheer number is going to cause problems.

You should aim to minimise the total ammount of SQL queries per page to reduce load and produce fast pages. I was talking in another thread somewhere about each query adding up - and optimising code etc and how one 10th of a second etc does make a difference. Think about having that ammount of queries, plus loading up all the code, plus processing all the code etc - it is going to be quite slow.

Cheers,
Michael Bray

Last edited by:

Michael_Bray: Jan 4, 2002, 3:54 AM
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
Hmm. I wonder why there are so many queries on the main page. I can only cound around 70 queries needed (to extract information from the database, such as description and titles, last post, usernames).

BTW: Is the detach thread moderator option done yet? :-)

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
>>Is the detach thread moderator option done yet?<<

Yup.
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
>>Just because GForum had 127 queries does *NOT* make it good practice. 127 queries puts a huge load on a program like MySQL<<

Take a look at the link I pasted for Wil where Alex comments about the speed of mysql.

Im obviously not suggesting someone use 127 queries unless they need to :)

However...one query, selecting one row from mysql to authenticate someone, has benefits that outway adding 0.001s to the execution time Cool

Last edited by:

RedRum: Jan 4, 2002, 5:40 AM
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Yeah I know that :) I like to make optimised code - but I am realistic with things like that. Saying 127 queries is not good practice was a general statement rather then for this specific case.
Cheers,
Michael Bray
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
And to add to this post, GT is on a dedicated server. If you're on a virtual server, it is best to reduce the amount of queries in your scripts, so that you do not abuse hosting company's TOAs.
========================================
Buh Bye!

Cheers,
Me
Quote Reply
Re: [Heckler] Authentication Logic In reply to
TOA? You mean TOS?

- wil
Quote Reply
Re: [Wil] Authentication Logic In reply to
Wil,

Back to your original point. I would recommend not storing any login information in client cookies. What I do is the following:

1) Create a client cookie upon successfully logging in. The cookie contains the following info:

a) Domain
b) UserID (not username or password)
c) Expiration info (3 hours)

2) When the user logins successfully (which is a simple check of the User table by username and password), the Session table is propegated with the following info:

a) SessionID (randomized)
b) UserID (from the Users table)
c) Date and Time Created

3) Then in each script, there is a sub call to the "authentication" subroutine in one of the Module files, which checks the UserID in the cookie file against the UserID in the session table.

The above logic is a combination of what GT Links SQL (v.1.X) offers and also from jerrysu who wrote a code hack for modify.cgi awhile back for Links SQL v.1.13. I modified his code hack to only store the UserID rather than Username that he used in his code hack.


========================================
Buh Bye!

Cheers,
Me

Last edited by:

Heckler: Jan 4, 2002, 7:12 AM
Quote Reply
Re: [Wil] Authentication Logic In reply to
Nope...Terms of Agreement (TOA)
========================================
Buh Bye!

Cheers,
Me
Quote Reply
Re: [Heckler] Authentication Logic In reply to
Just a quick note,

If you want to not use cookies at all you can pass the Session_ID around on each link / form which eliminates the need to set a cookie. A small percentage of people are weird and do not accept cookies - if you want to eliminate as many client-side problems are possible this may be an option you want to look into.
Cheers,
Michael Bray
Quote Reply
Re: [Heckler] Authentication Logic In reply to
>>I would recommend not storing any login information in client cookies.<<

If it is encrypted it is not a problem whatsoever. In order to hack the site you'd still need to know the username and password and encryption seed as I mentioned to Wil .

So I'd say thats more secure than checking a UserID against mysql.


Last edited by:

RedRum: Jan 4, 2002, 7:34 AM
Quote Reply
Re: [Michael_Bray] Authentication Logic In reply to
Thanks...forgot to mention that in my revised authentication sub, I do have a check to see if the cookie doesn't exist and I do use the SessionID as another check across the scripts...to eliminate client cookie problems.

Forgot to mention that....
========================================
Buh Bye!

Cheers,
Me
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Good point...however, encrypted or not, I prefer NOT to store login information in cookies...yes, encryption helps, but not 100% fool-proof.

Thanks for your input, but I respectively disagree with your approach...the beauty of Perl and other programming languages is its level of flexibility to allow different approaches...some better than others, but to be honest, I think that both of our approaches are secure in their own realm, but it is a philosophical difference in our approaches...so, there is no need to argue or belabor this point further.

And I was simply providing Wil with additional food for thought.

========================================
Buh Bye!

Cheers,
Me

Last edited by:

Heckler: Jan 4, 2002, 7:37 AM
Quote Reply
Re: [Heckler] Authentication Logic In reply to
Thanks for the food. I'll much on both and see where I come up with.

Cheers

- wil
Quote Reply
Re: [Heckler] Authentication Logic In reply to
>>so, there is no need to argue or belabor this point further. <<

Theres no harm in a healthy discussion and everyone providing different ideas. No-one is arguing which is good.

>>the beauty of Perl and other programming languages is its level of flexibility to allow different approaches<<

Exactly. It's personal preference and if we have different ways of approaching something theres no harm in that - it makes the world a better place.


Last edited by:

RedRum: Jan 4, 2002, 8:05 AM
Quote Reply
Re: [RedRum] Authentication Logic In reply to
Correct...And I noticed that you edited your post. I think it is more secure to check a field/column that is not used in the login form at all, thus using the UserID. Your comment about checking for the UserID not being secure in MySQL is not correct, IMHO.

Again, both of our approaches _are secure and thus Wil can choose which method best suits his needs. Stating that my approach is "not secure in MySQL" is not correct, IMHO.

As always, Paul, I think that we view things quite differently in the world and I am learning to become accustomed to you always questioning and disagreeing with my statements. Neither of our viewpoints are necessarily right or wrong, but you see black, while I see white. I think it chalks up to more than personality differences.

I look forward to our continued "friendly" disagreements about everything since we can never see eye to eye on anything.

Have a great day.
========================================
Buh Bye!

Cheers,
Me
Quote Reply
Re: [Heckler] Authentication Logic In reply to
The only thing I edited was to change ID to UserID in my post above. Anyway its not important.

>>I am learning to become accustomed to you always questioning and disagreeing with my statements<<

Ouch, thats a little harsh. I think you summed it up with:

I think that we view things quite differently in the world

....and it wouldn't be surprising as we are on opposite sites of the world with different religions etc....but that shouldn't be an excuse to disagree about everything.

>>I look forward to our continued "friendly" disagreements about everything since we can never see eye to eye on anything.
<<

I'd like to think there wouldn't be any more arguments and we could just accept our differences.
I've seen a nicer side of you in this thread....I'd like to see more.

Damn I sound like some kind of peace maker Angelic



Last edited by:

RedRum: Jan 4, 2002, 8:33 AM
Quote Reply
Re: [RedRum] Authentication Logic In reply to
And I would love to see you more respectively disagree with me rather than belitting me like you have had a tendency of doing. Yes, accepting our differences without belitting or berating each other would be nice, Paul, now wouldn't it? I am willing to give it a shot if you are...Wink

I wasn't being harsh, just being honest, which BTW is my worst trait, because I don't mince words and don't sugar coat..not my style. Yea, you can attract more bees with honey than vinegar, yada yada yada...and on the Net, my "sarcasim" is often mistaken for being condescending, which is not my intent.

Anyway, I will continue to make an effort to be more patient with your posts, which I can always count on including disagreeing remarks about anything that I post.

Good bye. Smile

========================================
Buh Bye!

Cheers,
Me

Last edited by:

Heckler: Jan 4, 2002, 8:40 AM
Quote Reply
Re: [Heckler] Authentication Logic In reply to
This thread brings a tear to my eye ;-))

- wil
Quote Reply
. In reply to
Removed after a rethink.

Last edited by:

RedRum: Jan 4, 2002, 9:40 AM
Quote Reply
Re: [Wil] Authentication Logic In reply to
Hi,

I would recommend one of the following:

1. Easy way:

Set a cookie with username=username, password=crypt(password). At the top of your script before anything else, make sure you have the cookie, and that there exists a user and password that match.

2. Better way:

You'll need a sessions table that looks like:

username char(50),
session char(50) not null primary key,
session_time int,

When a user logs in, generate a random session string, and insert it along with the value time(), and the username into the sessions table. Then return a cookie with session=$session that you just generated.

Each request, do a SELECT username FROM sessions WHERE session = ?, and check that the session they pass in is valid.

You also need to remove old sessions using:

DELETE FROM sessions WHERE session_time < $time

where $time is time() - 3600 for 1 hour sessions. This has the advantadge that you control how long sessions last, not the browser, and does not store any infromation about the user on the clients machine.

As for SQL queries, don't be afraid about using them. If you have a properly optimized query, the time it takes to execute is negligble. You want your SQL server to do the hard work, that's what it is there for.

Cheers,

Alex
--
Gossamer Threads Inc.
Quote Reply
Re: [Alex] Authentication Logic In reply to
Thanks for the reply, Alex. Your second option is the route I'm currently going down, thank you all for your input.

The only thing that really got me was that I needed to check for Authentication at the beginning of every sub. I really wanted to do this check once at the very top of my script so that it occurred whenever the script was called. The problem with this was that people who had never logged in would never be able to, and that's where it really hit me.

Thanks for the side note about SQL. I've heard a few people tell me that lately. ie, it's best to let the SQL server do the work rather than figure out a way to do it in Perl. If you can do it in SQL, do it, like increment numbers etc. This is supposedly faster?

Rgds

- wil