OAuth

Do Cryptographic Signatures Beat SSL/TLS In OAuth 2.0?

This post is more about perception vs reality than anything else. When it comes to application security, we like to consider that the steps we take to protect ourselves are unassailable bastions interlocked to poke sharp things at incoming attackers. What we don’t like is knowing that our bastions are always at risk of being
Author: Pádraic Brady

by News Robot on October 19, 2010 in News, No Comments »
tags: , , , ,

Do Cryptographic Signatures Beat SSL/TLS In OAuth 2.0?

This post is more about perception vs reality than anything else. When it comes to application security, we like to consider that the steps we take to protect ourselves are unassailable bastions interlocked to poke sharp things at incoming attackers. What we don’t like is knowing that our bastions are always at risk of being undermined in numerous unexpected ways. The consistent reaction among programmers is the same – we often pretend those bastions are completely unassailable no matter what and using any excuse necessary. Reality isn’t always a factor in my experience.

OAuth 2.0 is the next version of OAuth. It’s always great to see a good thing get better but the new version started off with an oddity inherited from OAuth WRAP. It removed the requirement for cryptographic signatures. Anyone who has skirmished with OAuth 1.0 has probably found the signature requirement a PITA. It’s poorly specified, subject to language specific errors, and difficult to debug. OAuth 2.0 would do away with this for these same reasons, replacing the need for digital signatures with a requirement that OAuth 2.0 operate over SSL/TLS between web servers. In this way, requests could not be intercepted by a Man-In-The-Middle (MITM), altered or replayed, thus rendering the need for digital signing obsolete. Simple as pie.

Very recently, a similar proposal was raised in relation to Pubsubhubbub which needs optional cryptographic signatures to prevent potential vulnerabilities in scenarios where topic updates must be verified as coming from a trusted source. The new Pubsubhubbub measure would have dropped any need for an all-encompassing cryptographic signature of both the topic body and its headers (currently headers are not signed which is problematic for future use) in favour of requiring SSL/TLS support on both sides (i.e. both Hubs and Subscribers). This was inspired by the bearer token approach of OAuth 2.0 over TLS currently required when using OAuth 2.0 from web servers. Technically it’s a simple effective solution.

However, both of these have the same problem. SSL/TLS offers a perception of unassailable security at odds with reality. The reality is harsh. SSL/TLS from a browser is, for most purposes, rock solid. Your connections are secure and if Firefox stumbles over a SSL Certificate it can’t validate or doesn’t immediately trust, it warns you, giving you the option of allowing an exception. This all works because we don’t each build our own browser from the ground up. The narrow field and expertise dedicated to each ensures SSL/TLS works as it should. Let’s turn that view on web applications sitting on a web server. Here we find more than a couple of discouraging trends.

The first is that setting up SSL/TLS is, for at least some percentage of people, difficult. Servers are misconfigured, SSL certificates are reused on different domains, and SSL certificates vary between self-signed and those signed by a trusted party which needs to be paid. It’s a bit on the messy side and mistakes are common. This was one reason why I objected to the Pubsubhubbub proposal – Subscribers refer to anyone wishing to receive topic updates, which is, well, everyone. The chances of everyone being able, or even capable, of setting up SSL/TLS for their websites is small.

The second is that client libraries for HTTP may be subject to insecure behaviour. The simplest example here is PHP itself, where the default options for the SSL context sets the verify_peer option to FALSE. If one were to build any SSL/TLS based protocol implementation in PHP without realising this (which people do), they will of course fail to verify SSL certificates encountered by their client. On the other hand, curl has SSL peer verification enabled by default. Insecurity by default is a nightmare.

The third, related to how hard/error prone it is for people to get SSL setup right, is the all too common practice of dealing with SSL certificate problems by deliberately disabling SSL Certificate verification in client libraries. Great for testing, bad for production purposes. This practice is widespread to ensure HTTPS requests will still work regardless of the state of the SSL certificate employed by the server. Sure, you’ll get a valid error-free response – but from who?

These three issues combine to offer a picture where SSL/TLS can be significantly broken on the web. This is hardly news. So hearing about SSL/TLS requirements in commonly used protocols begs the simple question: how does it improve security when it obviously conflicts with commonplace practice?

This is why protocols such as OAuth 2.0 and Pubsubhubbub need to tread carefully. Mandating the use of SSL/TLS introduces a single point of failure that will fail. It’s guaranteed to fail. It’s already failing. For those left vulnerable by such failures from, for example, an open source library that reaches common use, an attacker can just walk right in with a Man-In-The-Middle (MITM) attack. Sure, you’re using HTTPS, but if you’re not verifying certificates you do not have any guarantee that you are communicating with the intended trusted server.

Compare this to digital signatures. You have a shared secret that is not known to any potential MITM. You have a signature to verify the origin of any request/response. You have a random non-repeating nonce which varies the signature to prevent both replay attacks and remote timing attacks. You can additionally run it over SSL/TLS all you want, secure in the knowledge that John Doe’s PHP Streams based HTTP client will always work securely even if SSL certificate verification is still disabled by default. And best of all? You can’t optionally disable it! Either you implement it, or nothing will work.

Like practically everything in security, it’s a choice. Secure the protocol in depth, or make it easier to implement. You can’t have both which is why protocols will always be a PITA to implement when designed with security uppermost in their list of important features. It can’t be helped.

Back to OAuth 2.0, it has been mentioned that the next draft will contain an option to use cryptographic signatures instead of relying solely on SSL/TLS. This is a significant improvement in my opinion, and gives implementers back the ability to freely choose the most appropriate form of security for their APIs. You can all thank Erin Hammer-Lahav for triggering this or, you know, curse him forever when it becomes the standard means of using OAuth 2.0 from a web server and you are faced with implementing it ;-).

Author: Pádraic Brady

by News Robot on October 8, 2010 in News, No Comments »
tags: , , , ,

TweetGT: an example of Zend_Service_Twitter via OAuth

TweetGT is a simple application that talks to Twitter. I wrote it as I couldn’t find another way to send a geotagged tweet sent from an arbitrary location.

Screenshot of tweetgt.funkymongoose.com

Also, my friend Cal Evans says that writing a Twitter app is the new Hello World, so I thought I’d better find out how to do it! Obviously, I used Zend Framework :)

The source is up on github so you can have a look at the entire project. The section I want to concentrate on in this post is the Twitter OAuth integration, which was added to Zend_Service_Twitter in version 1.10.6.

To implement my Twitter integration, I used a model, Application_Model_Twitter, which has a protected member variable to an instance of Zend_Service_Twitter. This means that the rest of the application has to go through the model to get to the service and so in principle at least, I get to control access.

OAuth integration requires that we get an access token from twitter. The basic process is that we hand off from our website to Twitter, who then call back to a URL on our site once the user has logged in.

Login: Redirect to Twitter

The loginAction looks like this:


    public function loginAction()
    {
        $twitter $this->_helper->twitter(); /* @var $twitter Application_Model_Twitter */

        // We need the request token for use in the callback when the user is
        // redirected back here from Twitter after authenticating
        $session = new Zend_Session_Namespace();
        $session->requestToken $twitter->getRequestToken();

        // redirect to the Twitter website
        $twitter->loginViaTwitterSite();
    }

Three things going on here. Firstly, I have set up an action helper to retrieve an instance of my model for me. This is mainly for ease of use as there’s a bit of configuration required, so having it centralised saves having to duplicate code. There’s other ways of doing this of course, but a action helper suited me this time :)

When we hand over to Twitter, we send a request token over too. We will need the request token in the call back so we store to the session ready for use after the user has authenticated on Twitter’s site.

Finally we do the redirect to Twitter’s site via a model method, loginViaTwitterSite, which simply proxies to the redirect method within Zend_Service_Twitter‘s OAuth consumer.

Instantiating the model

The model is instantiated within a controller action helper. To log in to twitter using OAuth we need a consumer key and a consumer secret that are available from Twitter on a per-application basis. I’ve chosen to store these in the application.ini file. We also need to configure Zend_Service_Twitter with the callback URL to use and, if we are logged in, the username and access token from Twitter. This action helper does all that for us and looks like this:


class Application_Controller_Helper_Twitter extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * @var Application_Model_Twitter
     */
    protected $_twitter;

    public function direct()
    {
        if (!$this->_twitter) {
            $controller $this->getActionController();

            $config = array();

            $session = new Zend_Session_Namespace();
            if ($session->accessToken) {
                $token $session->accessToken;
                $config['username'] = $token->screen_name;
                $config['accessToken'] = $token;
            }
            
            $options $controller->getInvokeArg('bootstrap')->getOptions();
            $config['consumerKey'] = $options['twitter']['consumerKey'];
            $config['consumerSecret'] = $options['twitter']['consumerSecret'];

            $request $controller->getRequest();
            $url $request->getScheme() . '://' .  $request->getHttpHost() . $request->getBaseUrl();
            $config['callbackUrl'] = $url '/callback';

            $this->_twitter = new Application_Model_Twitter($config);
        }

        return $this->_twitter;
    }

}

I didn’t want my model interacting with sessions or the bootstrap options, so I used an action controller. I could equally have used a service layer object, or instantiated the model in the bootstrap or in a Front Controller plugin. The most important thing is that I only deal with the config of sorting out the config array that Zend_Service_Twitter needs once.

Callback

I have chosen /callback as the URL for Twitter to use. The easiest way to set this up is to have in indexAction() within a CallbackController class. This code will use the model’s twitter service to retrieve the access token and store it to the session.

It looks like this:

class CallbackController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $session = new Zend_Session_Namespace();
        if (!empty($this->getRequest()->getQuery()) && isset($session->requestToken)) {

            // Get the model instance from the action helper
            $twitter $this->_helper->twitter(); /* @var $twitter Application_Model_Twitter */

            // turn the request token into an access token
            $accessToken $twitter->getAccessToken($this->getRequest()->getQuery(),
                    $session->requestToken);

            // store the access token
            $session->accessToken $accessToken;

            // we don't need the request token any more
            unset($session->requestToken);

            // redirect back to home page
            $this->_helper->redirector('index''index');
        } else {
            throw new Zend_Exception('Invalid callback request. Oops. Sorry.');
        }
    }

}

The code should be fairly self-explanatory with the inline comments to help :)

That’s it. We are now logged into Twitter and back on our own website able to do whatever we want to do :) Have a look at the source to see the rest of the details of how it all fits together.

Author: Rob…

by News Robot on September 14, 2010 in News, No Comments »
tags: , , ,

Developer Tutorials: Writing A Simple Twitter Client Using the PHP Zend Framework’s OAuth Library (Zend_Oauth)

Pádraic Brady announced on Developer Tutorials site completing Zend_Oauth’s Consumer implementation for the OAuth Core 1.0 Revision A specification. He also present example implementation of Tweeter client using new component.

The OAuth protocol enables websites or applications (Consumers) to access Protected Resources from a web service (Service Provider) via an API, without requiring Users to disclose their Service Provider credentials to the Consumers. More generally, OAuth creates a freely-implementable and generic methodology for API authentication.

Zend_Oauth might be released in Zend Framework 1.10 (due December?) and is already in incubator. See how it works before the official release.