Yii 1.1: yii-apiauth

HTTP Authentication for (REST) clients (Basic or Digest Authentication)
15 followers

Yii ApiAuth Extension

Authenticate a (REST) client through Http Authentication Methods like Http Digest or Http Basic (or implement your own authentication scheme)

Most webservers, like Apache or IIS support different types of HTTP authentication, but they can be difficult (if not impossible) to integrate with a custom user account source, especially one that is implemented in Yii. This extension uses only Yii, PHP and MySQL and should be easy to integrate in an existing Yii based Authorization scenario.

Even though this extension can be used for virtually any authentication scenario, it is mostly suitable for automation, for example in REST requests. Hence it's name apiAuth.

Yii comes with an extensive built in authorization scheme and many great extensions like Rights, Auth or yii-user that you can use alongside this extension. @see http://www.yiiframework.com/doc/guide/1.1/en/topics.auth

Key Features:

  • For server-to-server communication (REST API's)
  • Secure: supports Digest authentication (used by default) or Basic authentication, which is less secure, but can be very usefull (and mainly faster) when you're already protected by SSL.
  • Easy to implement: intuitive yii-like filters & rules for controllers
  • Focus only on authentication. Leave authorization to other (or already implemented) components/extensions

Requirements

  • Yii 1.1.12 or newer (at least 1.1.13 when supporting qop: auth-int, older versions might work, not tested)
  • PHP 5.3 or newer
  • A database system like MySQL (other database systems might work, not tested).

Usage

See the README on GitHub.

Resources

Important Notes

To quote section 4.14 from RFC 2617:

By modern cryptographic standards Digest Authentication is weak. But
for a large range of purposes it is valuable as a replacement for
Basic Authentication. It remedies some, but not all, weaknesses of
Basic Authentication. Its strength may vary depending on the
implementation.  In particular the structure of the nonce (which is
dependent on the server implementation) may affect the ease of
mounting a replay attack.  A range of server options is appropriate
since, for example, some implementations may be willing to accept the
server overhead of one-time nonces or digests to eliminate the
possibility of replay. Others may satisfied with a nonce like the one
recommended above restricted to a single IP address and a single ETag
or with a limited lifetime.
The bottom line is that *any* compliant implementation will be
relatively weak by cryptographic standards, but *any* compliant
implementation will be far superior to Basic Authentication.

Total 5 comments

#12626 report it
Denit S. at 2013/04/02 05:58am
re: md5 hash

In digest authentication the password is not sent over the wire. Both sides know a shared secret and use it in combination with the header params that are sent over the wire to calculate a hash, which in turn gets sent to the server. If the server can calculate a hash that's the same as the client's hash, you can be sure that both sides are using the same shared secret.

In terms of transfer it's reasonably secure. On the other hand, you're now basically storing your password plaintext in the database, which isn't very secure. Even though it's an md5 encoded version of a string, that hash has now become the (reasonably complex) password, instead of the original unencrypted string.

Note that storing the A1 instead of the plaintext password isn't completely secure either, because md5 should not be considered secure. That's a limitation of digest imho, but it's still a lot better than storing it plaintext. ;)

#12625 report it
02xK at 2013/04/02 05:33am
md5 hash

Thanks! How about sending the md5 hash to the api? This is my current workaround. Is it still 'secure'?

// client
curl_setopt($curlHandle, CURLOPT_USERPWD, $this->username . ':' . md5($this->password)); // $this->password => form input field
// api
$A1 = md5($user->username . ':' . REALM . ':' . $user->password); // $user->password => md5 hash from db
#12623 report it
Denit S. at 2013/04/02 03:06am
digest encrypt passwords

It could also be related to the way you've stored your passwords.

What is important to know, but perhaps not very apparent in the config examples, is that Http Digest requires (encrypted) passwords to be stored in the following format:

md5($username . ":" . $realm . ":" . $unencrytedPassword);

If you already have user passwords, but they're stored in md5($unencryptedPass) format, digest authentication will always fail.

You could use:

ApiAuth::encryptPassword($username, $unencrytedPassword);

But it requires you to have access to the unencrypted password. If you want to implement this in an existing application with already existing clients for which you don't have the unencrypted password, this is going to be somewhat difficult. I've added the extra apiAuthPasswordAttribute config param so that you can be able to add a new password column to you user which can be used only by ApiAuth.

Note that you can always call this method. It will encrypt the password depending on your configuration and automatically include your realm setting. Meaning if you set ApiAuth::$hash to an empty value from you config, this method will simply return the unencryted password.

#12621 report it
Stageline at 2013/04/02 02:18am
csrf

Turn off csrf protect.

#12613 report it
02xK at 2013/04/01 06:14pm
Better how-to

Better how-to needed. Always getting 401. After 3 hours debugging still no result. testChallengeResponse in AHttpAuthenticatorDigest always returns false. Passwords are stored in md5.

"curl --digest -u user:test123 http://url.com/api" -> 401 -> redirect to the login page -> 302

Leave a comment

Please to leave your comment.

Create extension