Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5.3 Passport Custom Grants?

I know I am not the only person who has come up to this point. Does anyone know how to properly implement a custom grant in Laravel(5.3) Passport?

Or

Have a good link/tutorial to reference how to properly do it?

I know there's this package:

https://github.com/mikemclin/passport-custom-request-grant

But I'm asking for a more "Do it yourself" approach.

Thank you in advance.

like image 592
Andre F. Avatar asked Oct 19 '16 00:10

Andre F.


People also ask

Which is better JWT or Passport in laravel?

JSON Web Token and Passport can be primarily classified as "User Management and Authentication" tools. JSON Web Token and Passport are both open source tools. It seems that Passport with 15.9K GitHub stars and 936 forks on GitHub has more adoption than JSON Web Token with 2.59K GitHub stars and 259 GitHub forks.

Which is better sanctum or Passport in laravel?

If your application absolutely needs to support OAuth2, then you should use Laravel Passport. However, if you are attempting to authenticate a single-page application, mobile application, or issue API tokens, you should use Laravel Sanctum.

What is the difference between sanctum and Passport?

@vincent15000 Passport is an OAuth server implementation, and used to offer OAuth authorisation for your application. Sanctum is an authentication library for “simpler” token-based authentication for clients that need it (i.e. mobile apps) but also offers cookie-based authentication for SPAs.

Does laravel Passport use JWT?

Passport uses JWT authentication as standard but also implements full OAuth 2.0 authorization. OAuth allows authorization from third-party applications like Google, GitHub, and Facebook, but not every app requires this feature.


1 Answers

namespace App\Providers;

use App\Auth\Grants\FacebookGrant;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Bridge\RefreshTokenRepository;
use Laravel\Passport\Passport;
use League\OAuth2\Server\AuthorizationServer;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        app(AuthorizationServer::class)->enableGrantType(
            $this->makeFacebookGrant(), Passport::tokensExpireIn()
        );

        Passport::routes();

        //
    }

    /**
     * Create and configure a Facebook grant instance.
     *
     * @return FacebookGrant
     */
    protected function makeFacebookGrant()
    {
        $grant = new FacebookGrant(
            $this->app->make(RefreshTokenRepository::class)
        );

        $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());

        return $grant;
    }
}

EDIT: sorry for only posting this code, i do not know how much this code is going to be useful to you.

Well, here i'll leave my implementation of FacebookGrant, hope this helps someone.

<?php

namespace App\Auth\Grants;

use Illuminate\Http\Request;
use Laravel\Passport\Bridge\User;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;

class FacebookGrant extends AbstractGrant
{
    /**
     * @param RefreshTokenRepositoryInterface $refreshTokenRepository
     */
    public function __construct(
        RefreshTokenRepositoryInterface $refreshTokenRepository
    ) {
        $this->setRefreshTokenRepository($refreshTokenRepository);

        $this->refreshTokenTTL = new \DateInterval('P1M');
    }

    /**
     * {@inheritdoc}
     */
    public function respondToAccessTokenRequest(
        ServerRequestInterface $request,
        ResponseTypeInterface $responseType,
        \DateInterval $accessTokenTTL
    ) {
        // Validate request
        $client = $this->validateClient($request);
        $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
        $user = $this->validateUser($request, $client);

        // Finalize the requested scopes
        $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier());

        // Issue and persist new tokens
        $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes);
        $refreshToken = $this->issueRefreshToken($accessToken);

        // Inject tokens into response
        $responseType->setAccessToken($accessToken);
        $responseType->setRefreshToken($refreshToken);

        return $responseType;
    }

    /**
     * @param ServerRequestInterface $request
     *
     * @return UserEntityInterface
     * @throws OAuthServerException
     */
    protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
    {
        $facebookId = $this->getRequestParameter('facebook_id', $request);
        if (is_null($facebookId)) {
            throw OAuthServerException::invalidRequest('facebook_id');
        }

        $email = $this->getRequestParameter('email', $request);
        if (is_null($email)) {
            throw OAuthServerException::invalidRequest('email');
        }

        $user = $this->getUserEntityByUserFacebookId(
            $facebookId,
            $email,
            $this->getIdentifier(),
            $client
        );

        if ($user instanceof UserEntityInterface === false) {
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));

            throw OAuthServerException::invalidCredentials();
        }

        return $user;
    }

    /**
     *  Retrieve a user by the given Facebook Id.
     *
     * @param string  $facebookId
     * @param string  $email
     * @param string  $grantType
     * @param \League\OAuth2\Server\Entities\ClientEntityInterface  $clientEntity
     *
     * @return \Laravel\Passport\Bridge\User|null
     * @throws \League\OAuth2\Server\Exception\OAuthServerException
     */
    private function getUserEntityByUserFacebookId($facebookId, $email, $grantType, ClientEntityInterface $clientEntity)
    {
        $provider = config('auth.guards.api.provider');

        if (is_null($model = config('auth.providers.'.$provider.'.model'))) {
            throw new RuntimeException('Unable to determine authentication model from configuration.');
        }

        $user = (new $model)->where('facebook_id', $facebookId)->first();

        if (is_null($user)) {
            $user = (new $model)->where('email', $email)->first();

            if (is_null($user)) {
                return;
            }

            // Now that we retrieved the user with the email, we need to update it with
            // the given facebook id. So the user account will be linked correctly.
            $user->facebook_id = $facebookId;
            $user->save();
        }

        return new User($user->getAuthIdentifier());
    }

    /**
     * {@inheritdoc}
     */
    public function getIdentifier()
    {
        return 'facebook';
    }
}
like image 66
Francisco Daniel Avatar answered Oct 02 '22 03:10

Francisco Daniel