Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update oauth2.0 part to comply with latest version #219

Closed
simplenotezy opened this issue Oct 14, 2014 · 16 comments
Closed

Update oauth2.0 part to comply with latest version #219

simplenotezy opened this issue Oct 14, 2014 · 16 comments

Comments

@simplenotezy
Copy link

Could you possible update the wiki to comply with the latest version of lucadegasperi's oauth2 server?

See: https://github.com/dingo/api/wiki/OAuth-2.0

I am having a lot of troubles getting started.

@jasonlewis
Copy link
Contributor

Am working on some updated docs now. Will move them to the Wiki ASAP.

@simplenotezy
Copy link
Author

Sounds great! Thanks for fast reply. Meanwhile; do you have any idea how the oauth authenication provider should work?

Currently:

'auth' => [
    'oauth2' => function($app) {
        $provider = new Dingo\Api\Auth\LeagueOAuth2Provider($app['oauth2.resource-server']);

        $provider->setUserCallback(function($id) {
            return User::find($id);
        });

        $provider->setClientCallback(function($id) {
            return Client::find($id);
        });

        return $provider;
    },
    'basic' => function ($app) {
        return new Dingo\Api\Auth\BasicProvider($app['auth']);
    }
],

Will cause error: Class oauth2.resource-server does not exist (using version 3.* of oauth2-server-laravel)

@jasonlewis
Copy link
Contributor

Have you registered the OAuth 2.0 provider correctly in your app/config/app.php file?

@simplenotezy
Copy link
Author

Yes- but things have changed quite from version 1.0. See https://github.com/lucadegasperi/oauth2-server-laravel/wiki/Installation

@pulkitjalan
Copy link
Contributor

I ran into the same problem. I have temporarily created a new provider until the one in dingo can support the dev version of lucadegasperi's oauth2 server. Its a copy of the existing LucaDegasperiOAuth2Provider with the relevant changes.

<?php namespace App\Providers\Auth;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Dingo\Api\Auth\AuthorizationProvider;
use LucaDegasperi\OAuth2Server\Authorizer;
use League\OAuth2\Server\Exception\InvalidScopeException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class LucaDegasperiOAuth2Provider extends AuthorizationProvider
{
    /**
     * OAuth 2.0 resource server instance.
     *
     * @var \Dingo\OAuth2\Server\Resource
     */
    protected $resource;

    /**
     * Indicates whether access token is limited to headers only.
     *
     * @var bool
     */
    protected $httpHeadersOnly = false;

    /**
     * Callback to fetch a user.
     *
     * @var callable
     */
    protected $userCallback;

    /**
     * Callback to fetch a client.
     *
     * @var callable
     */
    protected $clientCallback;

    /**
     * Create a new Dingo\Api\Auth\OAuth2Provider instance.
     *
     * @param  \Dingo\OAuth2\Server\Resource  $resource
     * @param  bool  $httpHeadersOnly
     * @return void
     */
    public function __construct(Authorizer $resource, $httpHeadersOnly = false)
    {
        $this->resource = $resource;
        $this->httpHeadersOnly = $httpHeadersOnly;
    }

    /**
     * Authenticate request with the OAuth 2.0 resource server.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Routing\Route  $route
     * @return mixed
     */
    public function authenticate(Request $request, Route $route)
    {
        try {
            $this->validateAuthorizationHeader($request);
        } catch (Exception $exception) {
            // If we catch an exception here it means the header was missing so we'll
            // now look for the access token in the query string. If we don't have
            // the query string either then we'll re-throw the exception.
            if (! $request->query('access_token', false)) {
                throw $exception;
            }
        }

        try {
            $access_token = $request->query('access_token', null);
            $this->resource->validateAccessToken($this->httpHeadersOnly, $access_token);

            foreach ($this->getRouteScopes($route) as $scope) {
                if (! $this->resource->hasScope($scope)) {
                    throw new InvalidScopeException('Requested scope "'.$scope.'" is not associated with this access token.');
                }
            }

            return $this->resolveResourceOwner();
        } catch (InvalidScopeException $exception) {
            throw new UnauthorizedHttpException('Bearer', $exception->getMessage(), $exception);
        }
    }

    /**
     * Resolve the resource owner.
     *
     * @return mixed
     */
    protected function resolveResourceOwner()
    {
        if ($this->resource->getResourceOwnerType() == 'client') {
            return call_user_func($this->clientCallback, $this->resource->getResourceOwnerId());
        }

        return call_user_func($this->userCallback, $this->resource->getResourceOwnerId());
    }

    /**
     * Get the routes scopes.
     *
     * @param  \Illuminate\Routing\Route  $route
     * @return array
     */
    protected function getRouteScopes(Route $route)
    {
        $action = $route->getAction();

        return isset($action['scopes']) ? (array) $action['scopes'] : [];
    }

    /**
     * Set the callback to fetch a user.
     *
     * @param  callable  $callback
     * @return \Dingo\Api\Auth\LeagueOAuth2Provider
     */
    public function setUserCallback(callable $callback)
    {
        $this->userCallback = $callback;

        return $this;
    }

    /**
     * Set the callback to fetch a client.
     *
     * @param  callable  $callback
     * @return \Dingo\Api\Auth\LeagueOAuth2Provider
     */
    public function setClientCallback(callable $callback)
    {
        $this->clientCallback = $callback;

        return $this;
    }

    /**
     * Get the providers authorization method.
     *
     * @return string
     */
    public function getAuthorizationMethod()
    {
        return 'bearer';
    }
}

Also update the config with the relevant provider

'auth' => [
    'oauth2' => function($app) {
        $provider = new App\Providers\Auth\LucaDegasperiOAuth2Provider($app['oauth2-server.authorizer']);

        $provider->setUserCallback(function($id) {
            return User::find($id);
        });

        $provider->setClientCallback(function($id) {
            return Client::find($id);
        });

        return $provider;
    }
],

@simplenotezy
Copy link
Author

Nice - where did you put this file, and how did you then deal with the dingo-config (in Authentication Providers)?

@pulkitjalan
Copy link
Contributor

for now I have put it into my application namespace.

<?php namespace App\Providers\Auth;
...

I updated the original comment with info about the dingo config. Hope it helps :)

@jasonlewis
Copy link
Contributor

Ah I see what you mean. I'll get a fix out for this soon. For the mean time just go ahead with the above.

@simplenotezy
Copy link
Author

I have tried to implement your solution pulkitjalan, but it results in errors. I don't know if it is because I am using a custom grant type?

image

Authentication providers look like so:

image

@pulkitjalan
Copy link
Contributor

Its probably due to the custom grant type. I'm guessing the custom grant requires an instance of League\OAuth2\Server\Authorization but since in lucadegasperi's service provider, the grant_type class is initialised without any arguments (https://github.com/lucadegasperi/oauth2-server-laravel/blob/master/src/OAuth2ServerServiceProvider.php#L75) you see this error.

If you are able to modify the custom grant class then maybe make sure it extends League\OAuth2\Server\Grant\AbstractGrant (which implements League\OAuth2\Server\Grant\GrantTypeInterface) and also does not does not require League\OAuth2\Server\Authorization in the constructor.

@pulkitjalan
Copy link
Contributor

I had a quick look at your other post https://github.com/lucadegasperi/oauth2-server-laravel/issues/184 and your custom facebook grant class. Instead of using $this->authServer you should be able to use $this->server. Its similar to how the other grants are done already in league's. Then you should not need League\OAuth2\Server\Authorization in your constructor.

@simplenotezy
Copy link
Author

Thanks for your help!! I have tried replacing $this->authServer with $this->server in confusion (except for the constructor) in my custom grant, but it didn't solve my problem. Instead extending AbstratGrant worked!

UPDATE! I've seen stuff changed alot since 1.0. I've created the custom grant type back then, as a "copy" from the password grant. But that has changed a lot since. I've now recoded my custom grant to fit 1.5 version. But after client_id and client_secret have been authorized, it fails with some strange error:

image

My custom grant: http://laravel.io/bin/yLyno

@pulkitjalan
Copy link
Contributor

If you are extending the AbstractGrant, you will not need a constructor. Nor will you need:

/**
 * AuthServer instance
 * @var AuthServer
 */
protected $authServer = null;

Anywhere you are using $this->authServer you should be able to replace it with $this->server. $this->server is populated in the AbstractGrant (https://github.com/thephpleague/oauth2-server/blob/develop/src/Grant/AbstractGrant.php#L114) automatically with that method call.

Also getParam() is no longer used.

try:

$client_id = $this->server->getRequest()->request->get('client_id', null);
if (is_null($client_id)) {
    throw new Exception\InvalidRequestException('client_id');
}

You will need to repeat this for each variable $var = $this->server->getRequest()->request->get('var', null) but I think it would be a better structure than arrays any.

@simplenotezy
Copy link
Author

Great answer! Seems to solve the oauth issue. The "Failed to request resource" has something to do with another package: artdarek/oauth-4-laravel#114

Thanks for your intense help!

@pulkitjalan
Copy link
Contributor

Great! Glad I could help. :)

@jonaholsson
Copy link

@jasonlewis, curious to know why this issue was closed. Shouldn't it be kept open until there's a way to implement lucadegasperi 3.0 support?

UPDATE: Sorry, just realized this was already covered in the latest version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants