1

我一直在修改 laravel 护照,我似乎无法实现自定义授权类型。我正在使用 laravel 5.6 和护照 6.0 。经过研究,我在这个CustomGrant 库中同样创建了一个CustomRequestGrantProvider和一个CustomRequestGrant , 但我没有运气,每次我都会使用grant_type、client_idclient_secret向localhost:8000/oauth/token发出 POST 请求

{"error": "unsupported_grant_type",
"message": "The authorization grant type is not supported by the authorization server.",
"hint": "Check that all required parameters have been provided"}

看起来,我的请求甚至没有通过。我确保将提供程序添加到app.php

这是我的CustomRequestGrantProvider

class CustomRequestGrantProvider extends PassportServiceProvider{


public function boot()
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'passport');
    $this->deleteCookieOnLogout();


}

public function register()
{
    $this->registerAuthorizationServer();
}

protected function registerAuthorizationServer()
{
    $this->app->singleton(AuthorizationServer::class, function () {
        return tap($this->makeAuthorizationServer(), function ($server) {
            $server->enableGrantType(
                $this->makeCustomRequestGrant(), Passport::tokensExpireIn()
            );
        });
    });
}

protected function makeCustomRequestGrant()
{
    $grant = new CustomRequestGrant(
        $this->app->make(UserRepository::class),
        $this->app->make(RefreshTokenRepository::class)
    );
    $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
    return $grant;
}}

这是我的CustomRequestGrant

class CustomRequestGrant extends AbstractGrant{

public function __construct(
    UserRepositoryInterface $userRepository,
    RefreshTokenRepositoryInterface $refreshTokenRepository
)
{
    $this->setUserRepository($userRepository);
    $this->setRefreshTokenRepository($refreshTokenRepository);
    $this->refreshTokenTTL = new \DateInterval('P1M');
}

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);
    // 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;
}

public function getIdentifier()
{
    return 'custom_request';
}

protected function validateUser(ServerRequestInterface $request)
{
    $laravelRequest = new Request($request->getParsedBody());
    $user = $this->getUserEntityByRequest($laravelRequest);
    if ($user instanceof UserEntityInterface === false) {
        $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
        throw OAuthServerException::invalidCredentials();
    }
    return $user;
}

protected function getUserEntityByRequest(Request $request)
{
    if (is_null($model = config('auth.providers.users.model'))) {
        throw OAuthServerException::serverError('Unable to determine user model from configuration.');
    }
    if (method_exists($model, 'byPassportCustomRequest')) {
        $user = (new $model)->byPassportCustomRequest($request);
    } else {
        throw OAuthServerException::serverError('Unable to find byPassportCustomRequest method on user model.');
    }
    return ($user) ? new User($user->id) : null;
}} 

Note: All imports and namespace is correct, i just removed them for the sake of this post.

I even thought about editing the passport library, but i am not sure how sustainable it would be in the future.

Any help is really appreciated.

A few references:

Custom Grants?

Outdated custom grant example

Github discussion

4

1 回答 1

2

So i ended up creating custom classes that implement the original classes (Take a look at the picture below).

The classes needed from the laravel/passport trait are the classes in the picture below with out the Custom in the beginning.

For the CustomUserRepositoryInterface, you only need to modify UserRepositoryInterface, if for example you need to send an extra parameter to the laravel post request.

This gave me the ability to customize laravel passport heavily, like for example passing multiple account types that have different ways of accessing the app(like sign in with phone number, email, facebook_token and id).

I am sorry that i did not go thoroughly into the answer, but i was thinking of creating a library and sharing my work on github and off course update the answer and share the link, but non the less, these are the only classes you need to alter to achieve such result.

enter image description here

Have a splendid day :)

于 2018-11-28T00:10:41.830 回答