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.
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
csrf
Turn off csrf protect.
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:
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.
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
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. ;)
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.