Guide me implementing Oauth2 PHP server using thephpleague library

Tejas picture Tejas · Oct 11, 2014 · Viewed 9.2k times · Source

I am using Slim Framework With Eloquent ORM. Trying to implement https://github.com/thephpleague/oauth2-server but I am totally confused how to do this. After adding this with composer, I created database with sql file provided in this package.

Now it is suggested to implement Storage interfaces. I don't wanna do this, So I just copied storage classes found in Example Folder. I guess they should work as I am using same database right?

Also it is unclear how to initially seed the db. Here's my router where I am trying password method.

$server = new \League\OAuth2\Server\AuthorizationServer;

$server->setSessionStorage(new SessionStorage);
$server->setAccessTokenStorage(new AccessTokenStorage);
$server->setClientStorage(new ClientStorage);
$server->setScopeStorage(new ScopeStorage);

$passwordGrant = new \League\OAuth2\Server\Grant\PasswordGrant();
$passwordGrant->setVerifyCredentialsCallback(function ($username, $password) {
    // implement logic here to validate a username and password, return an ID if valid, otherwise return false
    return 1;
});

$server->addGrantType($passwordGrant);

$app->post('/token',function() use ($server,$app){
    try{
        $response = $server->issueAccessToken();

        $res = $app->response();
        $res['Content-Type'] = 'application/json';

        $res->body(json_encode($response));

    } catch (\Exception $e) {

       var_dump($e);
    }

});

I am totally frustrated whats happening. This throws following exception. [I have added scope ok in db]

object(League\OAuth2\Server\Exception\InvalidScopeException)[82]
  public 'httpStatusCode' => int 400
  public 'errorType' => string 'invalid_scope' (length=13)
  public 'serverShouldRedirect' => boolean true
  protected 'message' => string 'The requested scope is invalid, unknown, or malformed. Check the "ok" scope.' (length=76)
  private 'string' (Exception) => string '' (length=0)
  protected 'code' => int 0
  protected 'file' => string 'C:\wamp\www\linkshare\vendor\league\oauth2-server\src\Grant\AbstractGrant.php' (length=77)
  protected 'line' => int 163
  private 'trace' (Exception) => 
    array (size=11)
      0 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\league\oauth2-server\src\Grant\PasswordGrant.php' (length=77)
          'line' => int 130
          'function' => string 'validateScopes' (length=14)
          'class' => string 'League\OAuth2\Server\Grant\AbstractGrant' (length=40)
          'type' => string '->' (length=2)
          'args' => 
            array (size=2)
              ...
      1 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\league\oauth2-server\src\AuthorizationServer.php' (length=77)
          'line' => int 330
          'function' => string 'completeFlow' (length=12)
          'class' => string 'League\OAuth2\Server\Grant\PasswordGrant' (length=40)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      2 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\index.php' (length=31)
          'line' => int 67
          'function' => string 'issueAccessToken' (length=16)
          'class' => string 'League\OAuth2\Server\AuthorizationServer' (length=40)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      3 => 
        array (size=2)
          'function' => string '{closure}' (length=9)
          'args' => 
            array (size=0)
              ...
      4 => 
        array (size=4)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Route.php' (length=53)
          'line' => int 462
          'function' => string 'call_user_func_array' (length=20)
          'args' => 
            array (size=2)
              ...
      5 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Slim.php' (length=52)
          'line' => int 1326
          'function' => string 'dispatch' (length=8)
          'class' => string 'Slim\Route' (length=10)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      6 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Middleware\Flash.php' (length=64)
          'line' => int 85
          'function' => string 'call' (length=4)
          'class' => string 'Slim\Slim' (length=9)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      7 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Middleware\MethodOverride.php' (length=73)
          'line' => int 92
          'function' => string 'call' (length=4)
          'class' => string 'Slim\Middleware\Flash' (length=21)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      8 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Middleware\PrettyExceptions.php' (length=75)
          'line' => int 67
          'function' => string 'call' (length=4)
          'class' => string 'Slim\Middleware\MethodOverride' (length=30)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      9 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\vendor\slim\slim\Slim\Slim.php' (length=52)
          'line' => int 1271
          'function' => string 'call' (length=4)
          'class' => string 'Slim\Middleware\PrettyExceptions' (length=32)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)
              ...
      10 => 
        array (size=6)
          'file' => string 'C:\wamp\www\linkshare\index.php' (length=31)
          'line' => int 131
          'function' => string 'run' (length=3)
          'class' => string 'Slim\Slim' (length=9)
          'type' => string '->' (length=2)
          'args' => 
            array (size=0)

Answer

smcjones picture smcjones · Oct 27, 2014

OAuth 2.0 is very challenging to understand and use correctly. In fact, the lead of OAuth 2.0 famously walked away from the protocol after years of developing for it. According to Eran Hammer (the aforementioned lead developer):

When compared with OAuth 1.0, the 2.0 specification is more complex, less interoperable, less useful, more incomplete, and most importantly, less secure.

To be clear, OAuth 2.0 at the hand of a developer with deep understanding of web security will likely result is a secure implementation. However, at the hands of most developers – as has been the experience from the past two years – 2.0 is likely to produce insecure implementations.

So needless to say, there is some contention about OAuth 2.0. Alex Bilbie, the lead developer of the PHP League's OAuth 2.0-Server framework, appears to be one of the more knowledgeable developers for OAuth 2.0, although there are undoubtedly more. Still, keeping in mind one of Hammer's larger complaints - the lack of interoperability and completeness - you probably want to look for the following in an OAuth 2.0 implementation:

  • Active development
  • Full compliance with OAuth 2.0

I personally use and recommend Alex Bilbie's OAuth 2.0-Server, which now includes MAC bearer tokens and aims to be fully compliant. It is also under active development.

So, what does this mean for your project? Read up on the specifications. The package we are using claims to be fully compliant, which means that your best resource is OAuth 2.0's specification itself. There is also decent documentation under the PHP League website that can help you with this particular implementation.

That being said, you may be missing the Scope for your client/user combination. The way OAuth2.0 is structured, your user needs to accept scopes that the client requests. That means that your "scopes" need to be linked in your other tables. If "OK" is not approved by a user (in the DB) then it will not be approved.

Edit

Sounds like scopes are not the issue for you. This venue is not well suited for troubleshooting so I advise that you ensure you have the most current version of whatever framework you choose to use and report any bugs to the developer (with PHPLeague, it is via Github).