Laravel 5.3 Passport自定义授权?

15

我知道不止我一个人遇到了这个问题。有没有人知道如何在Laravel(5.3) Passport中正确地实现自定义授权?

或者

有没有好的链接/教程可以参考如何正确实现?

我知道有这个包:

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

但我想要更多“自己动手”的方法。

提前谢谢。


使用内置的令牌作用域如何? - jeremykenedy
1
作用域更具用户或客户端特定性。当进行自定义授权时,您可以获得灵活性,以更改授权过程流程或验证流程,使其适合于认证服务器的特定需求(无论是什么)。 - Andre F.
以上的软件包已经采用“自己动手做”的方法制作完成。个人观点认为,这是实现此类需求的最佳方式之一。不要重复造轮子。 - Onur Demir
2个回答

8
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;
    }
}

编辑: 很抱歉只发布了这段代码,我不知道这段代码对你有多大用处。

好的,这里我将留下我的FacebookGrant实现,希望这能帮助到某些人。

<?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';
    }
}

App\Auth\Grants\FacebookGrant怎么样? - Onur Demir
1
嗨,@aod我会添加这个类。这是我的自己的实现。 - Francisco Daniel

0

我不确定您所说的自定义授权是什么意思,但您可以使用护照服务进行密码授权,这样您就可以根据需要进行自定义。

参考链接:https://laravel.com/docs/5.3/passport#password-grant-tokens

更具体地说,您会得到一个client_idclient_secret,所有使用您的API的用户都将使用它们来获取access_tokenrefresh_token,并使用他们的密码电子邮件,然后您可以通过添加中间件来自定义该过程。

例如,您可以检查某些自定义标头是否存在,或者根据请求更改数据库以执行进一步查询等等。

也许我对您的问题完全理解错误,如果是这种情况,请详细说明您的需求。


我们想要实现社交登录。假设我们只想使用Facebook访问令牌来登录或注册用户到我们的系统中,因此我们没有任何密码或电子邮件。PasswordGrant需要密码和电子邮件,所以我们必须进行自定义。 - Onur Demir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接