bshaffer / oauth2-server-php

A library for implementing an OAuth2 Server in php
http://bshaffer.github.io/oauth2-server-php-docs
MIT License
3.26k stars 953 forks source link

Unused method in interface OAuth2\RequestInterface::getAllQueryParameters() #239

Open svycka opened 11 years ago

svycka commented 11 years ago

I had to replace build in request object with my own with uses zf2 request object because you are using file_get_contents('php://input') in your request class so zend can't get request content and sow OAuth2\RequestInterface::getAllQueryParameters() method I was not sure what it is for, so I did quick search and found that it never used, do I really need implement this? maybe I missed something? Maybe it should be removed? If we have getAllQueryParameters() maybe we want all headers, post params and so on?

bshaffer commented 11 years ago

You're right... The call to getAllQueryParameters was removed in b53bec7e750b8d526762b17c24c98562d347d7fa. It was initially put there for ExtensionGrant grant types, but until those are added I see no reason to keep it in the interface.

But please tell me the problem with using file_get_contents('php//input')? And if there is a problem, do you know of a work around? I definitely want this library to be zf2 compatible

svycka commented 11 years ago

the problem with php//input is the same #213 not only zf2 but also other modules who use this when your library calls file_get_contents('php//input') then zend can't get for example PUT request body i don't know easy workaround for this. This is my Request implementation of RequestInterface. More on php//input

<?php
namespace OAuth2Server\Provider;

use OAuth2\RequestInterface;
use Zend\Http\PhpEnvironment\Request as HttpRequest;

class Request implements RequestInterface
{
    protected $request;

    public function __construct(HttpRequest $request = null)
    {
        if ($request instanceof HttpRequest)
            $this->setRequest($request);
    }

    public function setRequest(HttpRequest $request)
    {
        $this->request = $request;
    }

    public function getRequest()
    {
        if (!$this->request instanceof HttpRequest) {
            throw new \OAuth2Server\Exception('Zend\Http\PhpEnvironment\Request was not set.');
        }

        return $this->request;
    }

    public function query($name, $default = null)
    {
        return $this->getRequest()->getQuery($name, $default);
    }

    public function request($name, $default = null)
    {
        if ($param = $this->getRequest()->getPost($name)) {
            return $param;
        }

        $contentType = $this->server('CONTENT_TYPE', '');
        $requestMethod = $this->server('REQUEST_METHOD', 'GET');

        if (0 === strpos($contentType, 'application/json')
            && in_array(strtoupper($requestMethod), array('POST', 'PUT', 'DELETE'))
        ) {
            $data = json_decode($this->getRequest()->getContent(), true);
            if (array_key_exists($name, $data))
                return $data[$name];
        }
        return $default;
    }

    public function server($name, $default = null)
    {
        return $this->getRequest()->getServer($name, $default);
    }

    public function headers($name, $default = null)
    {
        $header = $this->getRequest()->getHeader($name);

        if ($header) {
            return $header->getFieldValue();
        }

        return $default;
    }

    public function getAllQueryParameters()
    {
        return $this->getRequest()->getQuery()->toArray();
    }

    /**
     * @see https://github.com/bshaffer/oauth2-server-php/issues/240
     */
    public function addAuthHeaders()
    {
        if ($this->server('PHP_AUTH_USER')) {
            $headers = $this->getRequest()->getHeaders();
            $headers->addHeaderLine('PHP_AUTH_USER', $this->server('PHP_AUTH_USER'));
            $headers->addHeaderLine('PHP_AUTH_PW', $this->server('PHP_AUTH_PW'));
        } else {
            /*
             * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
             * For this workaround to work, add this line to your .htaccess file:
             * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
             *
             * A sample .htaccess file:
             * RewriteEngine On
             * RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
             * RewriteCond %{REQUEST_FILENAME} !-f
             * RewriteRule ^(.*)$ app.php [QSA,L]
             */

            $authorizationHeader = null;
            if ($this->server('HTTP_AUTHORIZATION')) {
                $authorizationHeader = $this->server('HTTP_AUTHORIZATION');
            } elseif ($this->server('REDIRECT_HTTP_AUTHORIZATION')) {
                $authorizationHeader = $this->server('REDIRECT_HTTP_AUTHORIZATION');
            } else if ($this->headers('Authorization')) {
                $authorizationHeader = trim($this->headers('Authorization'));
            }

            if (null !== $authorizationHeader) {
                // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic
                if (0 === stripos($authorizationHeader, 'basic')) {
                    $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
                    if (count($exploded) == 2) {
                        $headers = $this->getRequest()->getHeaders();
                        $headers->addHeaderLine('PHP_AUTH_USER', $exploded[0]);
                        $headers->addHeaderLine('PHP_AUTH_PW', $exploded[1]);
                    }
                }
            }
        }
          // TODO: not sure why do we need this??
//        // PHP_AUTH_USER/PHP_AUTH_PW
//        if (isset($headers['PHP_AUTH_USER'])) {
//            $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
//        }

    }
}

I have not written any tests for this so don't know if it works correctly, but so far working without any problems. Also factory for example how to initialize this

namespace OAuth2Server\Service;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use OAuth2Server\Provider\Request as RequestProvider;

class RequestProviderFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $request = $serviceLocator->get('request');
        $request_provider = new RequestProvider;
        $request_provider->setRequest($request);

        $request_provider->addAuthHeaders();

        return $request_provider;
    }
}
svycka commented 11 years ago

ops sorry for closing :D