-9

I have read many articles advising me to use OpenID, including on Stack Overflow, for authentication. Unfortunately I can't use OpenID because my auth is not based on an email - it is based on a username and password.

Currently I am doing authentication like this:

  1. User enters username and password.
  2. If the user login is successful then insert useragent, IP and an unique key which I create into a database.
  3. Set the unique key in a cookie and transmit it to the user.
  4. Whenever the user clicks any link (opening a page) all of the three are matched. If any match fails they will be logged out.

I create the unique key by encrypting time stamp + ip + useragent + username many rounds with MCRYPT_RIJNDAEL_256.

All connections are made using TLS to avoid sniffing.

Is this type of auth secure from session hijacking, or should I alter this method?

Anders
  • 65,052
  • 24
  • 180
  • 218
CS GO
  • 83
  • 4
  • 1
    Why is your application required to ignore modern authentication theory? Why are you tied to username/password? What are the consequences of failure? – MCW Mar 04 '14 at 15:50
  • @MarkC.Wallace what do you mean by modern auth theory can you explain ? what are the consequences of failure(i didn't understand this one). – CS GO Mar 04 '14 at 15:52
  • @MarkC.Wallace I would love to use OpenID and i am ready to use it but the problem is **majority** of the OpenIds are **connected/linked** with an email address. emailid auth is what i don't want !!! – CS GO Mar 04 '14 at 15:58
  • @MarkC.Wallace **consequences of failures** are you referring to forgotten password / resetting password ? – CS GO Mar 04 '14 at 16:02

4 Answers4

13

You know what you shouldn't do? Reinvent the wheel.

There are many authentication libraries out there, especially for PHP. Almost every single framework includes one. Use it. If you aren't using a framework, stop what you are doing and use one!

And yes, you must use TLS for your site.

  • can you suggest some libraries ??? – CS GO Mar 04 '14 at 13:00
  • No, I don't know PHP well enough to have confidence in any one library. –  Mar 04 '14 at 13:02
  • session is hijack able OR not ? – CS GO Mar 04 '14 at 13:27
  • Everytime you reinvent the wheel, especially in cryptography, there's a high chance your code is going to present vulnerabilities. If I were you, I'd just consider your protocol to be too weak [or anyways not as strong as current technology allows it to be]. – Giulio Muscarello Mar 04 '14 at 17:32
2

You should never roll your own. There is a so called "Schneier Law" that states:

Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break.

That means that even after you fail to break your own scheme, an expert my break it in two seconds. Have a look to this Schneier article.

There are thousands of methods working and you should use them, many of them have been tested by crypto and security professionals.

Also, you should read this Q&A.

kiBytes
  • 3,470
  • 16
  • 26
2

I can't use openid because my auth is not based on email id

OpenID does not depend on e-mail—an OpenID identity could be something like someone.example.com.

Then insert ( useragent, ip, unique key which i create ). into a database.

It is unwise to tie your sessions to IP address. Some users' IP addresses will legitimately vary (for example because they are behind a proxy cluster, or are switching between mobile networks). Kicking them out on IP change would make your site very difficult to use for a subset of your audience.

Matching IP is in any case of very limited usefulness. The usual attack it is attempting to address is that of session token leakage and reuse from an attacker client. But possible causes of token leakage are generally those that give the attacker access to make requests from the client anyway (XSS, client-side malware, bad transport security) or those which are already catastrophic (database compromise, server code execution).

Similarly User-Agent matching is of little value as the UA string isn't any kind of secret and is easily spoofed. Matching IP and UA can be of some worth as just one input to a complex risk rating system with behavioural history, but primitive matching is ineffective as a security measure and likely to cause you more damage from false negatives than benefit.

Time stamp + ip + useragent + username and encrypt them many rounds = unique key !

Encrypt type = MCRYPT_RIJNDAEL_256

Then insert ( useragent, ip, unique key which i create ). into a database.

set the unique key in cookie and transmit it to user.

As the client-submitted ‘unique key’ is verified simply by comparing it against the known value in the database, its actual content is of no relevance and there is no point in generating it in such an elaborate way.

A string of random data would do just as well for this, and then what you'd have would be functionally equivalent to the normal way people do logins in PHP: by putting a logged-in-user-ID on the session. Re-using PHP's standard random-PHPSESSID-based sessions would have advantages in terms of performance and the well-understood nature of their configuration.

There is another somewhat-common model of authentication, which may be what you were thinking of with the ‘unique key’ idea. This is where you create a token based on items you want to authenticate (typically user ID, password/reset generation numbers and token expiry time) together with a cryptographic signature over those items (typically HMAC) using a server-side secret key. The server can recognise and authenticate the incoming token using that signature, giving it the advantage that it doesn't need any persistent database/session storage. But unless you need that particular property I would stick with plain old sessions.

i think using TLS is must here

Yes. And remember to give your cookies the secure flag so they don't leak through a non-TLS request.

bobince
  • 12,534
  • 1
  • 27
  • 42
  • 1. If a website is providing you a openid they do it after email auth . 2.so you are suggesting that i should use simple phpsession cookies as my only auth ? – CS GO Mar 04 '14 at 15:09
  • 1. There's nothing in OpenID that requires e-mail at all. Some identity providers have links to e-mail, some don't. 2. Yes. Store the user's ID on the server-side session and retrieve it on each request. (If you want a hard timeout then you can also store an expiry timestamp in the session too and refuse to accept the session if it is too old.) – bobince Mar 04 '14 at 15:21
  • store it like this ? `$_SESSION['username'] = 'superman';` – CS GO Mar 04 '14 at 15:28
  • That would work. The implication of storing username is that users are identified in your system purely by username. A consequence of this model is that users can never be renamed or deleted. That may or may not be true for your application. A more typical alternative is having unique-forever user IDs (surrogate primary key in database). – bobince Mar 04 '14 at 15:33
  • yeah i use both of them surrogate key(which is always unique) and username(provided by user) – CS GO Mar 04 '14 at 15:35
  • So at last 1.auth user 2.start session 3.php will take care of session. and I think i should regenerate the session id every 5 minutes . – CS GO Mar 04 '14 at 15:49
  • No particular need to invalidate/re-issue old session IDs as a matter of course, but you do need to do it on principal change (ie primarily at login) to stop any session fixation attack elevating to a logged-in session compromise. – bobince Mar 04 '14 at 16:16
0

The answers above that suggest not to reinvent the auth'ENTIC'ation wheel are completely missing the point that you are creating an auth'ORIZ'ation token. The best wheel for authorization tokens I think would be to use something like HMAC+SHA2.

Minor nit, don't use timestamp of creation but a time the token will expire. And if possible, don't use the login unless you really really need it. The principle of least privilege should apply, so in order to create an authorization token for a business logic REST servicew that has no need for a username, don't supply it and don't include it in the auth token generation.

So you will end up with something like:

authkey = base64(hmac(sha224, concat(expiretime, ip, useragent), secretkey))

eightShirt
  • 313
  • 1
  • 3
  • 12
user1703394
  • 311
  • 1
  • 4