ubah ke docker mode
This commit is contained in:
No files matched your search
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Firebase\JWT\JWT;
|
||||
use Illuminate\Contracts\Config\Repository as Config;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
class ApiTokenCookieFactory
|
||||
{
|
||||
/**
|
||||
* The configuration repository implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Config\Repository
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The encrypter implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
protected $encrypter;
|
||||
|
||||
/**
|
||||
* Create an API token cookie factory instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Config $config, Encrypter $encrypter)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->encrypter = $encrypter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new API token cookie.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @param string $csrfToken
|
||||
* @return \Symfony\Component\HttpFoundation\Cookie
|
||||
*/
|
||||
public function make($userId, $csrfToken)
|
||||
{
|
||||
$config = $this->config->get('session');
|
||||
|
||||
$expiration = Carbon::now()->addMinutes($config['lifetime']);
|
||||
|
||||
return new Cookie(
|
||||
Passport::cookie(),
|
||||
$this->createToken($userId, $csrfToken, $expiration),
|
||||
$expiration,
|
||||
$config['path'],
|
||||
$config['domain'],
|
||||
$config['secure'],
|
||||
true,
|
||||
false,
|
||||
$config['same_site'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JWT token for the given user ID and CSRF token.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @param string $csrfToken
|
||||
* @param \Carbon\Carbon $expiration
|
||||
* @return string
|
||||
*/
|
||||
protected function createToken($userId, $csrfToken, Carbon $expiration)
|
||||
{
|
||||
return JWT::encode([
|
||||
'sub' => $userId,
|
||||
'csrf' => $csrfToken,
|
||||
'expiry' => $expiration->getTimestamp(),
|
||||
], Passport::tokenEncryptionKey($this->encrypter), 'HS256');
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AuthCode extends Model
|
||||
{
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'oauth_auth_codes';
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The guarded attributes on the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'revoked' => 'bool',
|
||||
'expires_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The "type" of the primary key ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyType = 'string';
|
||||
|
||||
/**
|
||||
* Get the client that owns the authentication code.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(Passport::clientModel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\AccessTokenTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
|
||||
|
||||
class AccessToken implements AccessTokenEntityInterface
|
||||
{
|
||||
use AccessTokenTrait, EntityTrait, TokenEntityTrait;
|
||||
|
||||
/**
|
||||
* Create a new token instance.
|
||||
*
|
||||
* @param string $userIdentifier
|
||||
* @param array $scopes
|
||||
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($userIdentifier, array $scopes, ClientEntityInterface $client)
|
||||
{
|
||||
$this->setUserIdentifier($userIdentifier);
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$this->addScope($scope);
|
||||
}
|
||||
|
||||
$this->setClient($client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Laravel\Passport\Events\AccessTokenCreated;
|
||||
use Laravel\Passport\Passport;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
|
||||
|
||||
class AccessTokenRepository implements AccessTokenRepositoryInterface
|
||||
{
|
||||
use FormatsScopesForStorage;
|
||||
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokenRepository;
|
||||
|
||||
/**
|
||||
* The event dispatcher instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param \Laravel\Passport\TokenRepository $tokenRepository
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $events
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokenRepository, Dispatcher $events)
|
||||
{
|
||||
$this->events = $events;
|
||||
$this->tokenRepository = $tokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
|
||||
{
|
||||
return new Passport::$accessTokenEntity($userIdentifier, $scopes, $clientEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
|
||||
{
|
||||
$this->tokenRepository->create([
|
||||
'id' => $accessTokenEntity->getIdentifier(),
|
||||
'user_id' => $accessTokenEntity->getUserIdentifier(),
|
||||
'client_id' => $accessTokenEntity->getClient()->getIdentifier(),
|
||||
'scopes' => $this->scopesToArray($accessTokenEntity->getScopes()),
|
||||
'revoked' => false,
|
||||
'created_at' => new DateTime,
|
||||
'updated_at' => new DateTime,
|
||||
'expires_at' => $accessTokenEntity->getExpiryDateTime(),
|
||||
]);
|
||||
|
||||
$this->events->dispatch(new AccessTokenCreated(
|
||||
$accessTokenEntity->getIdentifier(),
|
||||
$accessTokenEntity->getUserIdentifier(),
|
||||
$accessTokenEntity->getClient()->getIdentifier()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAccessToken($tokenId)
|
||||
{
|
||||
$this->tokenRepository->revokeAccessToken($tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAccessTokenRevoked($tokenId)
|
||||
{
|
||||
return $this->tokenRepository->isAccessTokenRevoked($tokenId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\AuthCodeTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
|
||||
|
||||
class AuthCode implements AuthCodeEntityInterface
|
||||
{
|
||||
use AuthCodeTrait, EntityTrait, TokenEntityTrait;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use Laravel\Passport\Passport;
|
||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||
|
||||
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
||||
{
|
||||
use FormatsScopesForStorage;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewAuthCode()
|
||||
{
|
||||
return new AuthCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => $authCodeEntity->getIdentifier(),
|
||||
'user_id' => $authCodeEntity->getUserIdentifier(),
|
||||
'client_id' => $authCodeEntity->getClient()->getIdentifier(),
|
||||
'scopes' => $this->formatScopesForStorage($authCodeEntity->getScopes()),
|
||||
'revoked' => false,
|
||||
'expires_at' => $authCodeEntity->getExpiryDateTime(),
|
||||
];
|
||||
|
||||
Passport::authCode()->forceFill($attributes)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeAuthCode($codeId)
|
||||
{
|
||||
Passport::authCode()->where('id', $codeId)->update(['revoked' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isAuthCodeRevoked($codeId)
|
||||
{
|
||||
return Passport::authCode()->where('id', $codeId)->where('revoked', 1)->exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\ClientTrait;
|
||||
|
||||
class Client implements ClientEntityInterface
|
||||
{
|
||||
use ClientTrait;
|
||||
|
||||
/**
|
||||
* The client identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* The client's provider.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $provider;
|
||||
|
||||
/**
|
||||
* Create a new client instance.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string $name
|
||||
* @param string $redirectUri
|
||||
* @param bool $isConfidential
|
||||
* @param string|null $provider
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($identifier, $name, $redirectUri, $isConfidential = false, $provider = null)
|
||||
{
|
||||
$this->setIdentifier((string) $identifier);
|
||||
|
||||
$this->name = $name;
|
||||
$this->isConfidential = $isConfidential;
|
||||
$this->redirectUri = explode(',', $redirectUri);
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client's identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return (string) $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client's identifier.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @return void
|
||||
*/
|
||||
public function setIdentifier($identifier)
|
||||
{
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use Laravel\Passport\ClientRepository as ClientModelRepository;
|
||||
use Laravel\Passport\Passport;
|
||||
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
|
||||
|
||||
class ClientRepository implements ClientRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The client model repository.
|
||||
*
|
||||
* @var \Laravel\Passport\ClientRepository
|
||||
*/
|
||||
protected $clients;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ClientModelRepository $clients)
|
||||
{
|
||||
$this->clients = $clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientEntity($clientIdentifier)
|
||||
{
|
||||
$record = $this->clients->findActive($clientIdentifier);
|
||||
|
||||
if (! $record) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new Client(
|
||||
$clientIdentifier,
|
||||
$record->name,
|
||||
$record->redirect,
|
||||
$record->confidential(),
|
||||
$record->provider
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateClient($clientIdentifier, $clientSecret, $grantType)
|
||||
{
|
||||
// First, we will verify that the client exists and is authorized to create personal
|
||||
// access tokens. Generally personal access tokens are only generated by the user
|
||||
// from the main interface. We'll only let certain clients generate the tokens.
|
||||
$record = $this->clients->findActive($clientIdentifier);
|
||||
|
||||
if (! $record || ! $this->handlesGrant($record, $grantType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! $record->confidential() || $this->verifySecret((string) $clientSecret, $record->secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given client can handle the given grant type.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $record
|
||||
* @param string $grantType
|
||||
* @return bool
|
||||
*/
|
||||
protected function handlesGrant($record, $grantType)
|
||||
{
|
||||
if (! $record->hasGrantType($grantType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($grantType) {
|
||||
case 'authorization_code':
|
||||
return ! $record->firstParty();
|
||||
case 'personal_access':
|
||||
return $record->personal_access_client && $record->confidential();
|
||||
case 'password':
|
||||
return $record->password_client;
|
||||
case 'client_credentials':
|
||||
return $record->confidential();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the client secret is valid.
|
||||
*
|
||||
* @param string $clientSecret
|
||||
* @param string $storedHash
|
||||
* @return bool
|
||||
*/
|
||||
protected function verifySecret($clientSecret, $storedHash)
|
||||
{
|
||||
return Passport::$hashesClientSecrets
|
||||
? password_verify($clientSecret, $storedHash)
|
||||
: hash_equals($storedHash, $clientSecret);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
trait FormatsScopesForStorage
|
||||
{
|
||||
/**
|
||||
* Format the given scopes for storage.
|
||||
*
|
||||
* @param array $scopes
|
||||
* @return string
|
||||
*/
|
||||
public function formatScopesForStorage(array $scopes)
|
||||
{
|
||||
return json_encode($this->scopesToArray($scopes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of scope identifiers for storage.
|
||||
*
|
||||
* @param array $scopes
|
||||
* @return array
|
||||
*/
|
||||
public function scopesToArray(array $scopes)
|
||||
{
|
||||
return array_map(function ($scope) {
|
||||
return $scope->getIdentifier();
|
||||
}, $scopes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use DateInterval;
|
||||
use League\OAuth2\Server\Grant\AbstractGrant;
|
||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class PersonalAccessGrant extends AbstractGrant
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function respondToAccessTokenRequest(
|
||||
ServerRequestInterface $request,
|
||||
ResponseTypeInterface $responseType,
|
||||
DateInterval $accessTokenTTL
|
||||
) {
|
||||
// Validate request
|
||||
$client = $this->validateClient($request);
|
||||
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
|
||||
$userIdentifier = $this->getRequestParameter('user_id', $request);
|
||||
|
||||
// Finalize the requested scopes
|
||||
$scopes = $this->scopeRepository->finalizeScopes(
|
||||
$scopes,
|
||||
$this->getIdentifier(),
|
||||
$client,
|
||||
$userIdentifier
|
||||
);
|
||||
|
||||
// Issue and persist access token
|
||||
$accessToken = $this->issueAccessToken(
|
||||
$accessTokenTTL,
|
||||
$client,
|
||||
$userIdentifier,
|
||||
$scopes
|
||||
);
|
||||
|
||||
// Inject access token into response type
|
||||
$responseType->setAccessToken($accessToken);
|
||||
|
||||
return $responseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return 'personal_access';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\Traits\RefreshTokenTrait;
|
||||
|
||||
class RefreshToken implements RefreshTokenEntityInterface
|
||||
{
|
||||
use EntityTrait, RefreshTokenTrait;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Laravel\Passport\Events\RefreshTokenCreated;
|
||||
use Laravel\Passport\RefreshTokenRepository as PassportRefreshTokenRepository;
|
||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||
|
||||
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The refresh token repository instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
protected $refreshTokenRepository;
|
||||
|
||||
/**
|
||||
* The event dispatcher instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param \Laravel\Passport\RefreshTokenRepository $refreshTokenRepository
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $events
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(PassportRefreshTokenRepository $refreshTokenRepository, Dispatcher $events)
|
||||
{
|
||||
$this->events = $events;
|
||||
$this->refreshTokenRepository = $refreshTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNewRefreshToken()
|
||||
{
|
||||
return new RefreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity)
|
||||
{
|
||||
$this->refreshTokenRepository->create([
|
||||
'id' => $id = $refreshTokenEntity->getIdentifier(),
|
||||
'access_token_id' => $accessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier(),
|
||||
'revoked' => false,
|
||||
'expires_at' => $refreshTokenEntity->getExpiryDateTime(),
|
||||
]);
|
||||
|
||||
$this->events->dispatch(new RefreshTokenCreated($id, $accessTokenId));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revokeRefreshToken($tokenId)
|
||||
{
|
||||
$this->refreshTokenRepository->revokeRefreshToken($tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRefreshTokenRevoked($tokenId)
|
||||
{
|
||||
return $this->refreshTokenRepository->isRefreshTokenRevoked($tokenId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\ScopeEntityInterface;
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
|
||||
class Scope implements ScopeEntityInterface
|
||||
{
|
||||
use EntityTrait;
|
||||
|
||||
/**
|
||||
* Create a new scope instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->setIdentifier($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data that should be serialized to JSON.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->getIdentifier();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Laravel\Passport\Passport;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
|
||||
|
||||
class ScopeRepository implements ScopeRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The client repository.
|
||||
*
|
||||
* @var \Laravel\Passport\ClientRepository|null
|
||||
*/
|
||||
protected ?ClientRepository $clients;
|
||||
|
||||
/**
|
||||
* Create a new scope repository.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository|null $clients
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(?ClientRepository $clients = null)
|
||||
{
|
||||
$this->clients = $clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getScopeEntityByIdentifier($identifier)
|
||||
{
|
||||
if (Passport::hasScope($identifier)) {
|
||||
return new Scope($identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function finalizeScopes(
|
||||
array $scopes, $grantType,
|
||||
ClientEntityInterface $clientEntity, $userIdentifier = null)
|
||||
{
|
||||
if (! in_array($grantType, ['password', 'personal_access', 'client_credentials'])) {
|
||||
$scopes = collect($scopes)->reject(function ($scope) {
|
||||
return trim($scope->getIdentifier()) === '*';
|
||||
})->values()->all();
|
||||
}
|
||||
|
||||
$client = $this->clients?->findActive($clientEntity->getIdentifier());
|
||||
|
||||
return collect($scopes)->filter(function ($scope) {
|
||||
return Passport::hasScope($scope->getIdentifier());
|
||||
})->when($client, function ($scopes, $client) {
|
||||
return $scopes->filter(fn ($scope) => $client->hasScope($scope->getIdentifier()));
|
||||
})->values()->all();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||
|
||||
class User implements UserEntityInterface
|
||||
{
|
||||
use EntityTrait;
|
||||
|
||||
/**
|
||||
* Create a new user instance.
|
||||
*
|
||||
* @param string|int $identifier
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($identifier)
|
||||
{
|
||||
$this->setIdentifier($identifier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Bridge;
|
||||
|
||||
use Illuminate\Contracts\Hashing\Hasher;
|
||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||
use RuntimeException;
|
||||
|
||||
class UserRepository implements UserRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The hasher implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Hashing\Hasher
|
||||
*/
|
||||
protected $hasher;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Hashing\Hasher $hasher
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Hasher $hasher)
|
||||
{
|
||||
$this->hasher = $hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
|
||||
{
|
||||
$provider = $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.');
|
||||
}
|
||||
|
||||
if (method_exists($model, 'findAndValidateForPassport')) {
|
||||
$user = (new $model)->findAndValidateForPassport($username, $password);
|
||||
|
||||
if (! $user) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new User($user->getAuthIdentifier());
|
||||
}
|
||||
|
||||
if (method_exists($model, 'findForPassport')) {
|
||||
$user = (new $model)->findForPassport($username);
|
||||
} else {
|
||||
$user = (new $model)->where('email', $username)->first();
|
||||
}
|
||||
|
||||
if (! $user) {
|
||||
return;
|
||||
} elseif (method_exists($user, 'validateForPassportPasswordGrant')) {
|
||||
if (! $user->validateForPassportPasswordGrant($password)) {
|
||||
return;
|
||||
}
|
||||
} elseif (! $this->hasher->check($password, $user->getAuthPassword())) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new User($user->getAuthIdentifier());
|
||||
}
|
||||
}
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Passport\Database\Factories\ClientFactory;
|
||||
|
||||
class Client extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use ResolvesInheritedScopes;
|
||||
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'oauth_clients';
|
||||
|
||||
/**
|
||||
* The guarded attributes on the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes excluded from the model's JSON form.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [
|
||||
'secret',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'grant_types' => 'array',
|
||||
'scopes' => 'array',
|
||||
'personal_access_client' => 'bool',
|
||||
'password_client' => 'bool',
|
||||
'revoked' => 'bool',
|
||||
];
|
||||
|
||||
/**
|
||||
* The temporary plain-text client secret.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $plainSecret;
|
||||
|
||||
/**
|
||||
* Bootstrap the model and its traits.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function ($model) {
|
||||
if (Passport::clientUuids()) {
|
||||
$model->{$model->getKeyName()} = $model->{$model->getKeyName()} ?: (string) Str::orderedUuid();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that the client belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
$provider = $this->provider ?: config('auth.guards.api.provider');
|
||||
|
||||
return $this->belongsTo(
|
||||
config("auth.providers.{$provider}.model")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the authentication codes for the client.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function authCodes()
|
||||
{
|
||||
return $this->hasMany(Passport::authCodeModel(), 'client_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the tokens that belong to the client.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function tokens()
|
||||
{
|
||||
return $this->hasMany(Passport::tokenModel(), 'client_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* The temporary non-hashed client secret.
|
||||
*
|
||||
* This is only available once during the request that created the client.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPlainSecretAttribute()
|
||||
{
|
||||
return $this->plainSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the secret attribute.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return void
|
||||
*/
|
||||
public function setSecretAttribute($value)
|
||||
{
|
||||
$this->plainSecret = $value;
|
||||
|
||||
if (is_null($value) || ! Passport::$hashesClientSecrets) {
|
||||
$this->attributes['secret'] = $value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->attributes['secret'] = password_hash($value, PASSWORD_BCRYPT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the client is a "first party" client.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function firstParty()
|
||||
{
|
||||
return $this->personal_access_client || $this->password_client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the client should skip the authorization prompt.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function skipsAuthorization()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the client has the given grant type.
|
||||
*
|
||||
* @param string $grantType
|
||||
* @return bool
|
||||
*/
|
||||
public function hasGrantType($grantType)
|
||||
{
|
||||
if (! isset($this->attributes['grant_types']) || ! is_array($this->grant_types)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_array($grantType, $this->grant_types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the client has the given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function hasScope($scope)
|
||||
{
|
||||
if (! isset($this->attributes['scopes']) || ! is_array($this->scopes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$scopes = Passport::$withInheritedScopes
|
||||
? $this->resolveInheritedScopes($scope)
|
||||
: [$scope];
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if (in_array($scope, $this->scopes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the client is a confidential client.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function confidential()
|
||||
{
|
||||
return ! empty($this->secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auto-incrementing key type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyType()
|
||||
{
|
||||
return Passport::clientUuids() ? 'string' : $this->keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value indicating whether the IDs are incrementing.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIncrementing()
|
||||
{
|
||||
return Passport::clientUuids() ? false : $this->incrementing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new factory instance for the model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Factories\Factory
|
||||
*/
|
||||
public static function newFactory()
|
||||
{
|
||||
return ClientFactory::new();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class ClientRepository
|
||||
{
|
||||
/**
|
||||
* The personal access client ID.
|
||||
*
|
||||
* @var int|string|null
|
||||
*/
|
||||
protected $personalAccessClientId;
|
||||
|
||||
/**
|
||||
* The personal access client secret.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $personalAccessClientSecret;
|
||||
|
||||
/**
|
||||
* Create a new client repository.
|
||||
*
|
||||
* @param int|string|null $personalAccessClientId
|
||||
* @param string|null $personalAccessClientSecret
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($personalAccessClientId = null, $personalAccessClientSecret = null)
|
||||
{
|
||||
$this->personalAccessClientId = $personalAccessClientId;
|
||||
$this->personalAccessClientSecret = $personalAccessClientSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a client by the given ID.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return \Laravel\Passport\Client|null
|
||||
*/
|
||||
public function find($id)
|
||||
{
|
||||
$client = Passport::client();
|
||||
|
||||
return $client->where($client->getKeyName(), $id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an active client by the given ID.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return \Laravel\Passport\Client|null
|
||||
*/
|
||||
public function findActive($id)
|
||||
{
|
||||
$client = $this->find($id);
|
||||
|
||||
return $client && ! $client->revoked ? $client : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a client instance for the given ID and user ID.
|
||||
*
|
||||
* @param int|string $clientId
|
||||
* @param mixed $userId
|
||||
* @return \Laravel\Passport\Client|null
|
||||
*/
|
||||
public function findForUser($clientId, $userId)
|
||||
{
|
||||
$client = Passport::client();
|
||||
|
||||
return $client
|
||||
->where($client->getKeyName(), $clientId)
|
||||
->where('user_id', $userId)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client instances for the given user ID.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function forUser($userId)
|
||||
{
|
||||
return Passport::client()
|
||||
->where('user_id', $userId)
|
||||
->orderBy('name', 'asc')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active client instances for the given user ID.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function activeForUser($userId)
|
||||
{
|
||||
return $this->forUser($userId)->reject(function ($client) {
|
||||
return $client->revoked;
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the personal access token client for the application.
|
||||
*
|
||||
* @return \Laravel\Passport\Client
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function personalAccessClient()
|
||||
{
|
||||
if ($this->personalAccessClientId) {
|
||||
return $this->find($this->personalAccessClientId);
|
||||
}
|
||||
|
||||
$client = Passport::personalAccessClient();
|
||||
|
||||
if (! $client->exists()) {
|
||||
throw new RuntimeException('Personal access client not found. Please create one.');
|
||||
}
|
||||
|
||||
return $client->orderBy($client->getKeyName(), 'desc')->first()->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new client.
|
||||
*
|
||||
* @param int|null $userId
|
||||
* @param string $name
|
||||
* @param string $redirect
|
||||
* @param string|null $provider
|
||||
* @param bool $personalAccess
|
||||
* @param bool $password
|
||||
* @param bool $confidential
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public function create($userId, $name, $redirect, $provider = null, $personalAccess = false, $password = false, $confidential = true)
|
||||
{
|
||||
$client = Passport::client()->forceFill([
|
||||
'user_id' => $userId,
|
||||
'name' => $name,
|
||||
'secret' => ($confidential || $personalAccess) ? Str::random(40) : null,
|
||||
'provider' => $provider,
|
||||
'redirect' => $redirect,
|
||||
'personal_access_client' => $personalAccess,
|
||||
'password_client' => $password,
|
||||
'revoked' => false,
|
||||
]);
|
||||
|
||||
$client->save();
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new personal access token client.
|
||||
*
|
||||
* @param int|null $userId
|
||||
* @param string $name
|
||||
* @param string $redirect
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public function createPersonalAccessClient($userId, $name, $redirect)
|
||||
{
|
||||
return tap($this->create($userId, $name, $redirect, null, true), function ($client) {
|
||||
$accessClient = Passport::personalAccessClient();
|
||||
$accessClient->client_id = $client->getKey();
|
||||
$accessClient->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new password grant client.
|
||||
*
|
||||
* @param int|null $userId
|
||||
* @param string $name
|
||||
* @param string $redirect
|
||||
* @param string|null $provider
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public function createPasswordGrantClient($userId, $name, $redirect, $provider = null)
|
||||
{
|
||||
return $this->create($userId, $name, $redirect, $provider, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given client.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @param string $name
|
||||
* @param string $redirect
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public function update(Client $client, $name, $redirect)
|
||||
{
|
||||
$client->forceFill([
|
||||
'name' => $name, 'redirect' => $redirect,
|
||||
])->save();
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the client secret.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public function regenerateSecret(Client $client)
|
||||
{
|
||||
$client->forceFill([
|
||||
'secret' => Str::random(40),
|
||||
])->save();
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given client is revoked.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function revoked($id)
|
||||
{
|
||||
$client = $this->find($id);
|
||||
|
||||
return is_null($client) || $client->revoked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given client.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return void
|
||||
*/
|
||||
public function delete(Client $client)
|
||||
{
|
||||
$client->tokens()->update(['revoked' => true]);
|
||||
|
||||
$client->forceFill(['revoked' => true])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the personal access client id.
|
||||
*
|
||||
* @return int|string|null
|
||||
*/
|
||||
public function getPersonalAccessClientId()
|
||||
{
|
||||
return $this->personalAccessClientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the personal access client secret.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPersonalAccessClientSecret()
|
||||
{
|
||||
return $this->personalAccessClientSecret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Passport\Client;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class ClientCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'passport:client
|
||||
{--personal : Create a personal access token client}
|
||||
{--password : Create a password grant client}
|
||||
{--client : Create a client credentials grant client}
|
||||
{--name= : The name of the client}
|
||||
{--provider= : The name of the user provider}
|
||||
{--redirect_uri= : The URI to redirect to after authorization }
|
||||
{--user_id= : The user ID the client should be assigned to }
|
||||
{--public : Create a public client (Auth code grant type only) }';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a client for issuing access tokens';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
public function handle(ClientRepository $clients)
|
||||
{
|
||||
if ($this->option('personal')) {
|
||||
$this->createPersonalClient($clients);
|
||||
} elseif ($this->option('password')) {
|
||||
$this->createPasswordClient($clients);
|
||||
} elseif ($this->option('client')) {
|
||||
$this->createClientCredentialsClient($clients);
|
||||
} else {
|
||||
$this->createAuthCodeClient($clients);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new personal access client.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
protected function createPersonalClient(ClientRepository $clients)
|
||||
{
|
||||
$name = $this->option('name') ?: $this->ask(
|
||||
'What should we name the personal access client?',
|
||||
config('app.name').' Personal Access Client'
|
||||
);
|
||||
|
||||
$client = $clients->createPersonalAccessClient(
|
||||
null, $name, 'http://localhost'
|
||||
);
|
||||
|
||||
$this->info('Personal access client created successfully.');
|
||||
|
||||
$this->outputClientDetails($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new password grant client.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
protected function createPasswordClient(ClientRepository $clients)
|
||||
{
|
||||
$name = $this->option('name') ?: $this->ask(
|
||||
'What should we name the password grant client?',
|
||||
config('app.name').' Password Grant Client'
|
||||
);
|
||||
|
||||
$providers = array_keys(config('auth.providers'));
|
||||
|
||||
$provider = $this->option('provider') ?: $this->choice(
|
||||
'Which user provider should this client use to retrieve users?',
|
||||
$providers,
|
||||
in_array('users', $providers) ? 'users' : null
|
||||
);
|
||||
|
||||
$client = $clients->createPasswordGrantClient(
|
||||
null, $name, 'http://localhost', $provider
|
||||
);
|
||||
|
||||
$this->info('Password grant client created successfully.');
|
||||
|
||||
$this->outputClientDetails($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a client credentials grant client.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
protected function createClientCredentialsClient(ClientRepository $clients)
|
||||
{
|
||||
$name = $this->option('name') ?: $this->ask(
|
||||
'What should we name the client?',
|
||||
config('app.name').' ClientCredentials Grant Client'
|
||||
);
|
||||
|
||||
$client = $clients->create(
|
||||
null, $name, ''
|
||||
);
|
||||
|
||||
$this->info('New client created successfully.');
|
||||
|
||||
$this->outputClientDetails($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a authorization code client.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @return void
|
||||
*/
|
||||
protected function createAuthCodeClient(ClientRepository $clients)
|
||||
{
|
||||
$userId = $this->option('user_id') ?: $this->ask(
|
||||
'Which user ID should the client be assigned to? (Optional)'
|
||||
);
|
||||
|
||||
$name = $this->option('name') ?: $this->ask(
|
||||
'What should we name the client?'
|
||||
);
|
||||
|
||||
$redirect = $this->option('redirect_uri') ?: $this->ask(
|
||||
'Where should we redirect the request after authorization?',
|
||||
url('/auth/callback')
|
||||
);
|
||||
|
||||
$client = $clients->create(
|
||||
$userId, $name, $redirect, null, false, false, ! $this->option('public')
|
||||
);
|
||||
|
||||
$this->info('New client created successfully.');
|
||||
|
||||
$this->outputClientDetails($client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the client's ID and secret key.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return void
|
||||
*/
|
||||
protected function outputClientDetails(Client $client)
|
||||
{
|
||||
if (Passport::$hashesClientSecrets) {
|
||||
$this->line('<comment>Here is your new client secret. This is the only time it will be shown so don\'t lose it!</comment>');
|
||||
$this->line('');
|
||||
}
|
||||
|
||||
$this->line('<comment>Client ID:</comment> '.$client->getKey());
|
||||
$this->line('<comment>Client secret:</comment> '.$client->plainSecret);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class HashCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'passport:hash {--force : Force the operation to run without confirmation prompt}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Hash all of the existing secrets in the clients table';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! Passport::$hashesClientSecrets) {
|
||||
$this->warn('Please enable client hashing yet in your AppServiceProvider before continuing.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->option('force') || $this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) {
|
||||
$model = Passport::clientModel();
|
||||
|
||||
foreach ((new $model)->whereNotNull('secret')->cursor() as $client) {
|
||||
if (password_get_info($client->secret)['algo'] === PASSWORD_BCRYPT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$client->timestamps = false;
|
||||
|
||||
$client->forceFill([
|
||||
'secret' => $client->secret,
|
||||
])->save();
|
||||
}
|
||||
|
||||
$this->info('All client secrets were successfully hashed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'passport:install
|
||||
{--uuids : Use UUIDs for all client IDs}
|
||||
{--force : Overwrite keys they already exist}
|
||||
{--length=4096 : The length of the private key}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the commands necessary to prepare Passport for use';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$provider = in_array('users', array_keys(config('auth.providers'))) ? 'users' : null;
|
||||
|
||||
$this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]);
|
||||
|
||||
if ($this->option('uuids')) {
|
||||
$this->configureUuids();
|
||||
}
|
||||
|
||||
$this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']);
|
||||
$this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client', '--provider' => $provider]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Passport for client UUIDs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureUuids()
|
||||
{
|
||||
$this->call('vendor:publish', ['--tag' => 'passport-config']);
|
||||
$this->call('vendor:publish', ['--tag' => 'passport-migrations']);
|
||||
|
||||
config(['passport.client_uuids' => true]);
|
||||
Passport::setClientUuids(true);
|
||||
|
||||
$this->replaceInFile(config_path('passport.php'), '\'client_uuids\' => false', '\'client_uuids\' => true');
|
||||
$this->replaceInFile(database_path('migrations/2016_06_01_000001_create_oauth_auth_codes_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');');
|
||||
$this->replaceInFile(database_path('migrations/2016_06_01_000002_create_oauth_access_tokens_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');');
|
||||
$this->replaceInFile(database_path('migrations/2016_06_01_000004_create_oauth_clients_table.php'), '$table->bigIncrements(\'id\');', '$table->uuid(\'id\')->primary();');
|
||||
$this->replaceInFile(database_path('migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');');
|
||||
|
||||
if ($this->confirm('In order to finish configuring client UUIDs, we need to rebuild the Passport database tables. Would you like to rollback and re-run your last migration?')) {
|
||||
$this->call('migrate:rollback');
|
||||
$this->call('migrate');
|
||||
$this->line('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a given string in a given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @return void
|
||||
*/
|
||||
protected function replaceInFile($path, $search, $replace)
|
||||
{
|
||||
file_put_contents(
|
||||
$path,
|
||||
str_replace($search, $replace, file_get_contents($path))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Passport\Passport;
|
||||
use phpseclib\Crypt\RSA as LegacyRSA;
|
||||
use phpseclib3\Crypt\RSA;
|
||||
|
||||
class KeysCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'passport:keys
|
||||
{--force : Overwrite keys they already exist}
|
||||
{--length=4096 : The length of the private key}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create the encryption keys for API authentication';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
[$publicKey, $privateKey] = [
|
||||
Passport::keyPath('oauth-public.key'),
|
||||
Passport::keyPath('oauth-private.key'),
|
||||
];
|
||||
|
||||
if ((file_exists($publicKey) || file_exists($privateKey)) && ! $this->option('force')) {
|
||||
$this->error('Encryption keys already exist. Use the --force option to overwrite them.');
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
if (class_exists(LegacyRSA::class)) {
|
||||
$keys = (new LegacyRSA)->createKey($this->input ? (int) $this->option('length') : 4096);
|
||||
|
||||
file_put_contents($publicKey, Arr::get($keys, 'publickey'));
|
||||
file_put_contents($privateKey, Arr::get($keys, 'privatekey'));
|
||||
} else {
|
||||
$key = RSA::createKey($this->input ? (int) $this->option('length') : 4096);
|
||||
|
||||
file_put_contents($publicKey, (string) $key->getPublicKey());
|
||||
file_put_contents($privateKey, (string) $key);
|
||||
}
|
||||
|
||||
$this->info('Encryption keys generated successfully.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class PurgeCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'passport:purge
|
||||
{--revoked : Only purge revoked tokens and authentication codes}
|
||||
{--expired : Only purge expired tokens and authentication codes}
|
||||
{--hours= : The number of hours to retain expired tokens}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Purge revoked and / or expired tokens and authentication codes';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$expired = $this->option('hours')
|
||||
? Carbon::now()->subHours($this->option('hours'))
|
||||
: Carbon::now()->subDays(7);
|
||||
|
||||
if (($this->option('revoked') && $this->option('expired')) ||
|
||||
(! $this->option('revoked') && ! $this->option('expired'))) {
|
||||
Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
|
||||
Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
|
||||
Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete();
|
||||
|
||||
$this->option('hours')
|
||||
? $this->info('Purged revoked items and items expired for more than '.$this->option('hours').' hours.')
|
||||
: $this->info('Purged revoked items and items expired for more than seven days.');
|
||||
} elseif ($this->option('revoked')) {
|
||||
Passport::token()->where('revoked', 1)->delete();
|
||||
Passport::authCode()->where('revoked', 1)->delete();
|
||||
Passport::refreshToken()->where('revoked', 1)->delete();
|
||||
|
||||
$this->info('Purged revoked items.');
|
||||
} elseif ($this->option('expired')) {
|
||||
Passport::token()->whereDate('expires_at', '<', $expired)->delete();
|
||||
Passport::authCode()->whereDate('expires_at', '<', $expired)->delete();
|
||||
Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete();
|
||||
|
||||
$this->option('hours')
|
||||
? $this->info('Purged items expired for more than '.$this->option('hours').' hours.')
|
||||
: $this->info('Purged items expired for more than seven days.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Contracts;
|
||||
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
|
||||
interface AuthorizationViewResponse extends Responsable
|
||||
{
|
||||
/**
|
||||
* Specify the parameters that should be passed to the view.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function withParameters($parameters = []);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Events;
|
||||
|
||||
class AccessTokenCreated
|
||||
{
|
||||
/**
|
||||
* The newly created token ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $tokenId;
|
||||
|
||||
/**
|
||||
* The ID of the user associated with the token.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* The ID of the client associated with the token.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $clientId;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $tokenId
|
||||
* @param string|int|null $userId
|
||||
* @param string $clientId
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($tokenId, $userId, $clientId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->tokenId = $tokenId;
|
||||
$this->clientId = $clientId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Events;
|
||||
|
||||
class RefreshTokenCreated
|
||||
{
|
||||
/**
|
||||
* The newly created refresh token ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $refreshTokenId;
|
||||
|
||||
/**
|
||||
* The access token ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $accessTokenId;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $refreshTokenId
|
||||
* @param string $accessTokenId
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($refreshTokenId, $accessTokenId)
|
||||
{
|
||||
$this->accessTokenId = $accessTokenId;
|
||||
$this->refreshTokenId = $refreshTokenId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Exceptions;
|
||||
|
||||
use Illuminate\Auth\AuthenticationException as Exception;
|
||||
|
||||
class AuthenticationException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Exceptions;
|
||||
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
|
||||
class InvalidAuthTokenException extends AuthorizationException
|
||||
{
|
||||
/**
|
||||
* Create a new InvalidAuthTokenException for different auth tokens.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function different()
|
||||
{
|
||||
return new static('The provided auth token for the request is different from the session auth token.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Exceptions;
|
||||
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class MissingScopeException extends AuthorizationException
|
||||
{
|
||||
/**
|
||||
* The scopes that the user did not have.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $scopes;
|
||||
|
||||
/**
|
||||
* Create a new missing scope exception.
|
||||
*
|
||||
* @param array|string $scopes
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($scopes = [], $message = 'Invalid scope(s) provided.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
|
||||
$this->scopes = Arr::wrap($scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scopes that the user did not have.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function scopes()
|
||||
{
|
||||
return $this->scopes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Response;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException as LeagueException;
|
||||
|
||||
class OAuthServerException extends Exception
|
||||
{
|
||||
/**
|
||||
* The response to render.
|
||||
*
|
||||
* @var \Illuminate\Http\Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* Create a new OAuthServerException.
|
||||
*
|
||||
* @param \League\OAuth2\Server\Exception\OAuthServerException $e
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(LeagueException $e, Response $response)
|
||||
{
|
||||
parent::__construct($e->getMessage(), $e->getCode(), $e);
|
||||
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the exception into an HTTP response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function render($request)
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP response status code.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function statusCode()
|
||||
{
|
||||
return $this->response->getStatusCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Guards;
|
||||
|
||||
use Exception;
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use Illuminate\Auth\GuardHelpers;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Cookie\CookieValuePrefix;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Laravel\Passport\Client;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Laravel\Passport\Passport;
|
||||
use Laravel\Passport\PassportUserProvider;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use Laravel\Passport\TransientToken;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
||||
|
||||
class TokenGuard implements Guard
|
||||
{
|
||||
use GuardHelpers, Macroable;
|
||||
|
||||
/**
|
||||
* The resource server instance.
|
||||
*
|
||||
* @var \League\OAuth2\Server\ResourceServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* The user provider implementation.
|
||||
*
|
||||
* @var \Laravel\Passport\PassportUserProvider
|
||||
*/
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* The client repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\ClientRepository
|
||||
*/
|
||||
protected $clients;
|
||||
|
||||
/**
|
||||
* The encrypter implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
protected $encrypter;
|
||||
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The currently authenticated client.
|
||||
*
|
||||
* @var \Laravel\Passport\Client|null
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* Create a new token guard instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\ResourceServer $server
|
||||
* @param \Laravel\Passport\PassportUserProvider $provider
|
||||
* @param \Laravel\Passport\TokenRepository $tokens
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
ResourceServer $server,
|
||||
PassportUserProvider $provider,
|
||||
TokenRepository $tokens,
|
||||
ClientRepository $clients,
|
||||
Encrypter $encrypter,
|
||||
Request $request
|
||||
) {
|
||||
$this->server = $server;
|
||||
$this->tokens = $tokens;
|
||||
$this->clients = $clients;
|
||||
$this->provider = $provider;
|
||||
$this->encrypter = $encrypter;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user for the incoming request.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
if (! is_null($this->user)) {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
if ($this->request->bearerToken()) {
|
||||
return $this->user = $this->authenticateViaBearerToken($this->request);
|
||||
} elseif ($this->request->cookie(Passport::cookie())) {
|
||||
return $this->user = $this->authenticateViaCookie($this->request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a user's credentials.
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(array $credentials = [])
|
||||
{
|
||||
return ! is_null((new static(
|
||||
$this->server,
|
||||
$this->provider,
|
||||
$this->tokens,
|
||||
$this->clients,
|
||||
$this->encrypter,
|
||||
$credentials['request'],
|
||||
))->user());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client for the incoming request.
|
||||
*
|
||||
* @return \Laravel\Passport\Client|null
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
if (! is_null($this->client)) {
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
if ($this->request->bearerToken()) {
|
||||
if (! $psr = $this->getPsrRequestViaBearerToken($this->request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->client = $this->clients->findActive(
|
||||
$psr->getAttribute('oauth_client_id')
|
||||
);
|
||||
} elseif ($this->request->cookie(Passport::cookie())) {
|
||||
if ($token = $this->getTokenViaCookie($this->request)) {
|
||||
return $this->client = $this->clients->findActive($token['aud']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the incoming request via the Bearer token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
protected function authenticateViaBearerToken($request)
|
||||
{
|
||||
if (! $psr = $this->getPsrRequestViaBearerToken($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$client = $this->clients->findActive(
|
||||
$psr->getAttribute('oauth_client_id')
|
||||
);
|
||||
|
||||
if (! $client ||
|
||||
($client->provider &&
|
||||
$client->provider !== $this->provider->getProviderName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the access token is valid we will retrieve the user according to the user ID
|
||||
// associated with the token. We will use the provider implementation which may
|
||||
// be used to retrieve users from Eloquent. Next, we'll be ready to continue.
|
||||
$user = $this->provider->retrieveById(
|
||||
$psr->getAttribute('oauth_user_id') ?: null
|
||||
);
|
||||
|
||||
if (! $user) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, we will assign a token instance to this user which the developers may use
|
||||
// to determine if the token has a given scope, etc. This will be useful during
|
||||
// authorization such as within the developer's Laravel model policy classes.
|
||||
$token = $this->tokens->find(
|
||||
$psr->getAttribute('oauth_access_token_id')
|
||||
);
|
||||
|
||||
return $token ? $user->withAccessToken($token) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate and get the incoming PSR-7 request via the Bearer token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Psr\Http\Message\ServerRequestInterface|null
|
||||
*/
|
||||
protected function getPsrRequestViaBearerToken($request)
|
||||
{
|
||||
// First, we will convert the Symfony request to a PSR-7 implementation which will
|
||||
// be compatible with the base OAuth2 library. The Symfony bridge can perform a
|
||||
// conversion for us to a new Nyholm implementation of this PSR-7 request.
|
||||
$psr = (new PsrHttpFactory(
|
||||
new Psr17Factory,
|
||||
new Psr17Factory,
|
||||
new Psr17Factory,
|
||||
new Psr17Factory
|
||||
))->createRequest($request);
|
||||
|
||||
try {
|
||||
return $this->server->validateAuthenticatedRequest($psr);
|
||||
} catch (OAuthServerException $e) {
|
||||
$request->headers->set('Authorization', '', true);
|
||||
|
||||
Container::getInstance()->make(
|
||||
ExceptionHandler::class
|
||||
)->report($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the incoming request via the token cookie.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
protected function authenticateViaCookie($request)
|
||||
{
|
||||
if (! $token = $this->getTokenViaCookie($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this user exists, we will return this user and attach a "transient" token to
|
||||
// the user model. The transient token assumes it has all scopes since the user
|
||||
// is physically logged into the application via the application's interface.
|
||||
if ($user = $this->provider->retrieveById($token['sub'])) {
|
||||
return $user->withAccessToken(new TransientToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token cookie via the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getTokenViaCookie($request)
|
||||
{
|
||||
// If we need to retrieve the token from the cookie, it'll be encrypted so we must
|
||||
// first decrypt the cookie and then attempt to find the token value within the
|
||||
// database. If we can't decrypt the value we'll bail out with a null return.
|
||||
try {
|
||||
$token = $this->decodeJwtTokenCookie($request);
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We will compare the CSRF token in the decoded API token against the CSRF header
|
||||
// sent with the request. If they don't match then this request isn't sent from
|
||||
// a valid source and we won't authenticate the request for further handling.
|
||||
if (! Passport::$ignoreCsrfToken && (! $this->validCsrf($token, $request) ||
|
||||
time() >= $token['expiry'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode and decrypt the JWT token cookie.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
protected function decodeJwtTokenCookie($request)
|
||||
{
|
||||
$jwt = $request->cookie(Passport::cookie());
|
||||
|
||||
return (array) JWT::decode(
|
||||
Passport::$decryptsCookies
|
||||
? CookieValuePrefix::remove($this->encrypter->decrypt($jwt, Passport::$unserializesCookies))
|
||||
: $jwt,
|
||||
new Key(Passport::tokenEncryptionKey($this->encrypter), 'HS256')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the CSRF / header are valid and match.
|
||||
*
|
||||
* @param array $token
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function validCsrf($token, $request)
|
||||
{
|
||||
return isset($token['csrf']) && hash_equals(
|
||||
$token['csrf'], (string) $this->getTokenFromRequest($request)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CSRF token from the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string
|
||||
*/
|
||||
protected function getTokenFromRequest($request)
|
||||
{
|
||||
$token = $request->header('X-CSRF-TOKEN');
|
||||
|
||||
if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
|
||||
$token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized()));
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current request instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return $this
|
||||
*/
|
||||
public function setRequest(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the cookie contents should be serialized.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function serialized()
|
||||
{
|
||||
return EncryptCookies::serialized('XSRF-TOKEN');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client for the current request.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return $this
|
||||
*/
|
||||
public function setClient(Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
|
||||
trait HasApiTokens
|
||||
{
|
||||
/**
|
||||
* The current access token for the authentication user.
|
||||
*
|
||||
* @var \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null
|
||||
*/
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* Get all of the user's registered OAuth clients.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function clients()
|
||||
{
|
||||
return $this->hasMany(Passport::clientModel(), 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the access tokens for the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function tokens()
|
||||
{
|
||||
return $this->hasMany(Passport::tokenModel(), 'user_id')->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current access token being used by the user.
|
||||
*
|
||||
* @return \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null
|
||||
*/
|
||||
public function token()
|
||||
{
|
||||
return $this->accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current API token has a given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function tokenCan($scope)
|
||||
{
|
||||
return $this->accessToken ? $this->accessToken->can($scope) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new personal access token for the user.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $scopes
|
||||
* @return \Laravel\Passport\PersonalAccessTokenResult
|
||||
*/
|
||||
public function createToken($name, array $scopes = [])
|
||||
{
|
||||
return Container::getInstance()->make(PersonalAccessTokenFactory::class)->make(
|
||||
$this->getKey(), $name, $scopes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current access token for the user.
|
||||
*
|
||||
* @param \Laravel\Passport\Token|\Laravel\Passport\TransientToken|null $accessToken
|
||||
* @return $this
|
||||
*/
|
||||
public function withAccessToken($accessToken)
|
||||
{
|
||||
$this->accessToken = $accessToken;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use Nyholm\Psr7\Response as Psr7Response;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AccessTokenController
|
||||
{
|
||||
use HandlesOAuthErrors;
|
||||
|
||||
/**
|
||||
* The authorization server.
|
||||
*
|
||||
* @var \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
* @param \Laravel\Passport\TokenRepository $tokens
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server,
|
||||
TokenRepository $tokens)
|
||||
{
|
||||
$this->server = $server;
|
||||
$this->tokens = $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize a client to access the user's account.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function issueToken(ServerRequestInterface $request)
|
||||
{
|
||||
return $this->withErrorHandling(function () use ($request) {
|
||||
return $this->convertResponse(
|
||||
$this->server->respondToAccessTokenRequest($request, new Psr7Response)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use Nyholm\Psr7\Response as Psr7Response;
|
||||
|
||||
class ApproveAuthorizationController
|
||||
{
|
||||
use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession;
|
||||
|
||||
/**
|
||||
* The authorization server.
|
||||
*
|
||||
* @var \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve the authorization request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function approve(Request $request)
|
||||
{
|
||||
$this->assertValidAuthToken($request);
|
||||
|
||||
$authRequest = $this->getAuthRequestFromSession($request);
|
||||
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
return $this->withErrorHandling(function () use ($authRequest) {
|
||||
return $this->convertResponse(
|
||||
$this->server->completeAuthorizationRequest($authRequest, new Psr7Response)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Passport\Bridge\User;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Laravel\Passport\Contracts\AuthorizationViewResponse;
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\Passport;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use Nyholm\Psr7\Response as Psr7Response;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AuthorizationController
|
||||
{
|
||||
use HandlesOAuthErrors;
|
||||
|
||||
/**
|
||||
* The authorization server.
|
||||
*
|
||||
* @var \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* The guard implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected $guard;
|
||||
|
||||
/**
|
||||
* The authorization view response implementation.
|
||||
*
|
||||
* @var \Laravel\Passport\Contracts\AuthorizationViewResponse
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
* @param \Illuminate\Contracts\Auth\StatefulGuard $guard
|
||||
* @param \Laravel\Passport\Contracts\AuthorizationViewResponse $response
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server,
|
||||
StatefulGuard $guard,
|
||||
AuthorizationViewResponse $response)
|
||||
{
|
||||
$this->server = $server;
|
||||
$this->guard = $guard;
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize a client to access the user's account.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $psrRequest
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @param \Laravel\Passport\TokenRepository $tokens
|
||||
* @return \Illuminate\Http\Response|\Laravel\Passport\Contracts\AuthorizationViewResponse
|
||||
*/
|
||||
public function authorize(ServerRequestInterface $psrRequest,
|
||||
Request $request,
|
||||
ClientRepository $clients,
|
||||
TokenRepository $tokens)
|
||||
{
|
||||
$authRequest = $this->withErrorHandling(function () use ($psrRequest) {
|
||||
return $this->server->validateAuthorizationRequest($psrRequest);
|
||||
});
|
||||
|
||||
if ($this->guard->guest()) {
|
||||
return $request->get('prompt') === 'none'
|
||||
? $this->denyRequest($authRequest)
|
||||
: $this->promptForLogin($request);
|
||||
}
|
||||
|
||||
if ($request->get('prompt') === 'login' &&
|
||||
! $request->session()->get('promptedForLogin', false)) {
|
||||
$this->guard->logout();
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return $this->promptForLogin($request);
|
||||
}
|
||||
|
||||
$request->session()->forget('promptedForLogin');
|
||||
|
||||
$scopes = $this->parseScopes($authRequest);
|
||||
$user = $this->guard->user();
|
||||
$client = $clients->find($authRequest->getClient()->getIdentifier());
|
||||
|
||||
if ($request->get('prompt') !== 'consent' &&
|
||||
($client->skipsAuthorization() || $this->hasValidToken($tokens, $user, $client, $scopes))) {
|
||||
return $this->approveRequest($authRequest, $user);
|
||||
}
|
||||
|
||||
if ($request->get('prompt') === 'none') {
|
||||
return $this->denyRequest($authRequest, $user);
|
||||
}
|
||||
|
||||
$request->session()->put('authToken', $authToken = Str::random());
|
||||
$request->session()->put('authRequest', $authRequest);
|
||||
|
||||
return $this->response->withParameters([
|
||||
'client' => $client,
|
||||
'user' => $user,
|
||||
'scopes' => $scopes,
|
||||
'request' => $request,
|
||||
'authToken' => $authToken,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the authorization requests's scopes into Scope instances.
|
||||
*
|
||||
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
|
||||
* @return array
|
||||
*/
|
||||
protected function parseScopes($authRequest)
|
||||
{
|
||||
return Passport::scopesFor(
|
||||
collect($authRequest->getScopes())->map(function ($scope) {
|
||||
return $scope->getIdentifier();
|
||||
})->unique()->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a valid token exists for the given user, client, and scopes.
|
||||
*
|
||||
* @param \Laravel\Passport\TokenRepository $tokens
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @param array $scopes
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasValidToken($tokens, $user, $client, $scopes)
|
||||
{
|
||||
$token = $tokens->findValidToken($user, $client);
|
||||
|
||||
return $token && $token->scopes === collect($scopes)->pluck('id')->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve the authorization request.
|
||||
*
|
||||
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function approveRequest($authRequest, $user)
|
||||
{
|
||||
$authRequest->setUser(new User($user->getAuthIdentifier()));
|
||||
|
||||
$authRequest->setAuthorizationApproved(true);
|
||||
|
||||
return $this->withErrorHandling(function () use ($authRequest) {
|
||||
return $this->convertResponse(
|
||||
$this->server->completeAuthorizationRequest($authRequest, new Psr7Response)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny the authorization request.
|
||||
*
|
||||
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function denyRequest($authRequest, $user = null)
|
||||
{
|
||||
if (is_null($user)) {
|
||||
$uri = $authRequest->getRedirectUri()
|
||||
?? (is_array($authRequest->getClient()->getRedirectUri())
|
||||
? $authRequest->getClient()->getRedirectUri()[0]
|
||||
: $authRequest->getClient()->getRedirectUri());
|
||||
|
||||
$separator = $authRequest->getGrantTypeId() === 'implicit' ? '#' : '?';
|
||||
|
||||
$uri = $uri.(str_contains($uri, $separator) ? '&' : $separator).'state='.$authRequest->getState();
|
||||
|
||||
return $this->withErrorHandling(function () use ($uri) {
|
||||
throw OAuthServerException::accessDenied('Unauthenticated', $uri);
|
||||
});
|
||||
}
|
||||
|
||||
$authRequest->setUser(new User($user->getAuthIdentifier()));
|
||||
|
||||
$authRequest->setAuthorizationApproved(false);
|
||||
|
||||
return $this->withErrorHandling(function () use ($authRequest) {
|
||||
return $this->convertResponse(
|
||||
$this->server->completeAuthorizationRequest($authRequest, new Psr7Response)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user to login by throwing an AuthenticationException.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException
|
||||
*/
|
||||
protected function promptForLogin($request)
|
||||
{
|
||||
$request->session()->put('promptedForLogin', true);
|
||||
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Passport\RefreshTokenRepository;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
|
||||
class AuthorizedAccessTokenController
|
||||
{
|
||||
/**
|
||||
* The token repository implementation.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokenRepository;
|
||||
|
||||
/**
|
||||
* The refresh token repository implementation.
|
||||
*
|
||||
* @var \Laravel\Passport\RefreshTokenRepository
|
||||
*/
|
||||
protected $refreshTokenRepository;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Passport\TokenRepository $tokenRepository
|
||||
* @param \Laravel\Passport\RefreshTokenRepository $refreshTokenRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokenRepository, RefreshTokenRepository $refreshTokenRepository)
|
||||
{
|
||||
$this->tokenRepository = $tokenRepository;
|
||||
$this->refreshTokenRepository = $refreshTokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the authorized tokens for the authenticated user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function forUser(Request $request)
|
||||
{
|
||||
$tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier());
|
||||
|
||||
return $tokens->load('client')->filter(function ($token) {
|
||||
return ! $token->client->firstParty() && ! $token->revoked;
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $tokenId
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Request $request, $tokenId)
|
||||
{
|
||||
$token = $this->tokenRepository->findForUser(
|
||||
$tokenId, $request->user()->getAuthIdentifier()
|
||||
);
|
||||
|
||||
if (is_null($token)) {
|
||||
return new Response('', 404);
|
||||
}
|
||||
|
||||
$token->revoke();
|
||||
|
||||
$this->refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId);
|
||||
|
||||
return new Response('', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Laravel\Passport\Http\Rules\RedirectRule;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class ClientController
|
||||
{
|
||||
/**
|
||||
* The client repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\ClientRepository
|
||||
*/
|
||||
protected $clients;
|
||||
|
||||
/**
|
||||
* The validation factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Validation\Factory
|
||||
*/
|
||||
protected $validation;
|
||||
|
||||
/**
|
||||
* The redirect validation rule.
|
||||
*
|
||||
* @var \Laravel\Passport\Http\Rules\RedirectRule
|
||||
*/
|
||||
protected $redirectRule;
|
||||
|
||||
/**
|
||||
* Create a client controller instance.
|
||||
*
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @param \Illuminate\Contracts\Validation\Factory $validation
|
||||
* @param \Laravel\Passport\Http\Rules\RedirectRule $redirectRule
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
ClientRepository $clients,
|
||||
ValidationFactory $validation,
|
||||
RedirectRule $redirectRule
|
||||
) {
|
||||
$this->clients = $clients;
|
||||
$this->validation = $validation;
|
||||
$this->redirectRule = $redirectRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the clients for the authenticated user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function forUser(Request $request)
|
||||
{
|
||||
$userId = $request->user()->getAuthIdentifier();
|
||||
|
||||
$clients = $this->clients->activeForUser($userId);
|
||||
|
||||
if (Passport::$hashesClientSecrets) {
|
||||
return $clients;
|
||||
}
|
||||
|
||||
return $clients->makeVisible('secret');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new client.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Laravel\Passport\Client|array
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validation->make($request->all(), [
|
||||
'name' => 'required|max:191',
|
||||
'redirect' => ['required', $this->redirectRule],
|
||||
'confidential' => 'boolean',
|
||||
])->validate();
|
||||
|
||||
$client = $this->clients->create(
|
||||
$request->user()->getAuthIdentifier(), $request->name, $request->redirect,
|
||||
null, false, false, (bool) $request->input('confidential', true)
|
||||
);
|
||||
|
||||
if (Passport::$hashesClientSecrets) {
|
||||
return ['plainSecret' => $client->plainSecret] + $client->toArray();
|
||||
}
|
||||
|
||||
return $client->makeVisible('secret');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given client.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $clientId
|
||||
* @return \Illuminate\Http\Response|\Laravel\Passport\Client
|
||||
*/
|
||||
public function update(Request $request, $clientId)
|
||||
{
|
||||
$client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier());
|
||||
|
||||
if (! $client) {
|
||||
return new Response('', 404);
|
||||
}
|
||||
|
||||
$this->validation->make($request->all(), [
|
||||
'name' => 'required|max:191',
|
||||
'redirect' => ['required', $this->redirectRule],
|
||||
])->validate();
|
||||
|
||||
return $this->clients->update(
|
||||
$client, $request->name, $request->redirect
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given client.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $clientId
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Request $request, $clientId)
|
||||
{
|
||||
$client = $this->clients->findForUser($clientId, $request->user()->getAuthIdentifier());
|
||||
|
||||
if (! $client) {
|
||||
return new Response('', 404);
|
||||
}
|
||||
|
||||
$this->clients->delete($client);
|
||||
|
||||
return new Response('', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
trait ConvertsPsrResponses
|
||||
{
|
||||
/**
|
||||
* Convert a PSR7 response to a Illuminate Response.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $psrResponse
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function convertResponse($psrResponse)
|
||||
{
|
||||
return new Response(
|
||||
$psrResponse->getBody(),
|
||||
$psrResponse->getStatusCode(),
|
||||
$psrResponse->getHeaders()
|
||||
);
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use Nyholm\Psr7\Response as Psr7Response;
|
||||
|
||||
class DenyAuthorizationController
|
||||
{
|
||||
use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession;
|
||||
|
||||
/**
|
||||
* The authorization server.
|
||||
*
|
||||
* @var \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny the authorization request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function deny(Request $request)
|
||||
{
|
||||
$this->assertValidAuthToken($request);
|
||||
|
||||
$authRequest = $this->getAuthRequestFromSession($request);
|
||||
|
||||
$authRequest->setAuthorizationApproved(false);
|
||||
|
||||
return $this->withErrorHandling(function () use ($authRequest) {
|
||||
return $this->convertResponse(
|
||||
$this->server->completeAuthorizationRequest($authRequest, new Psr7Response)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Laravel\Passport\Exceptions\OAuthServerException;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException as LeagueException;
|
||||
use Nyholm\Psr7\Response as Psr7Response;
|
||||
|
||||
trait HandlesOAuthErrors
|
||||
{
|
||||
use ConvertsPsrResponses;
|
||||
|
||||
/**
|
||||
* Perform the given callback with exception handling.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\OAuthServerException
|
||||
*/
|
||||
protected function withErrorHandling($callback)
|
||||
{
|
||||
try {
|
||||
return $callback();
|
||||
} catch (LeagueException $e) {
|
||||
throw new OAuthServerException(
|
||||
$e,
|
||||
$this->convertResponse($e->generateHttpResponse(new Psr7Response))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Passport\Passport;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
|
||||
class PersonalAccessTokenController
|
||||
{
|
||||
/**
|
||||
* The token repository implementation.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokenRepository;
|
||||
|
||||
/**
|
||||
* The validation factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Validation\Factory
|
||||
*/
|
||||
protected $validation;
|
||||
|
||||
/**
|
||||
* Create a controller instance.
|
||||
*
|
||||
* @param \Laravel\Passport\TokenRepository $tokenRepository
|
||||
* @param \Illuminate\Contracts\Validation\Factory $validation
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokenRepository, ValidationFactory $validation)
|
||||
{
|
||||
$this->validation = $validation;
|
||||
$this->tokenRepository = $tokenRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the personal access tokens for the authenticated user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function forUser(Request $request)
|
||||
{
|
||||
$tokens = $this->tokenRepository->forUser($request->user()->getAuthIdentifier());
|
||||
|
||||
return $tokens->load('client')->filter(function ($token) {
|
||||
return $token->client->personal_access_client && ! $token->revoked;
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new personal access token for the user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Laravel\Passport\PersonalAccessTokenResult
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validation->make($request->all(), [
|
||||
'name' => 'required|max:191',
|
||||
'scopes' => 'array|in:'.implode(',', Passport::scopeIds()),
|
||||
])->validate();
|
||||
|
||||
return $request->user()->createToken(
|
||||
$request->name, $request->scopes ?: []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $tokenId
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Request $request, $tokenId)
|
||||
{
|
||||
$token = $this->tokenRepository->findForUser(
|
||||
$tokenId, $request->user()->getAuthIdentifier()
|
||||
);
|
||||
|
||||
if (is_null($token)) {
|
||||
return new Response('', 404);
|
||||
}
|
||||
|
||||
$token->revoke();
|
||||
|
||||
return new Response('', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Passport\Bridge\User;
|
||||
use Laravel\Passport\Exceptions\InvalidAuthTokenException;
|
||||
|
||||
trait RetrievesAuthRequestFromSession
|
||||
{
|
||||
/**
|
||||
* Make sure the auth token matches the one in the session.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\InvalidAuthTokenException
|
||||
*/
|
||||
protected function assertValidAuthToken(Request $request)
|
||||
{
|
||||
if ($request->has('auth_token') && $request->session()->get('authToken') !== $request->get('auth_token')) {
|
||||
$request->session()->forget(['authToken', 'authRequest']);
|
||||
|
||||
throw InvalidAuthTokenException::different();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorization request from the session.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \League\OAuth2\Server\RequestTypes\AuthorizationRequest
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getAuthRequestFromSession(Request $request)
|
||||
{
|
||||
return tap($request->session()->get('authRequest'), function ($authRequest) use ($request) {
|
||||
if (! $authRequest) {
|
||||
throw new Exception('Authorization request was not present in the session.');
|
||||
}
|
||||
|
||||
$authRequest->setUser(new User($request->user()->getAuthIdentifier()));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class ScopeController
|
||||
{
|
||||
/**
|
||||
* Get all of the available scopes for the application.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return Passport::scopes();
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Passport\ApiTokenCookieFactory;
|
||||
|
||||
class TransientTokenController
|
||||
{
|
||||
/**
|
||||
* The cookie factory instance.
|
||||
*
|
||||
* @var \Laravel\Passport\ApiTokenCookieFactory
|
||||
*/
|
||||
protected $cookieFactory;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Passport\ApiTokenCookieFactory $cookieFactory
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ApiTokenCookieFactory $cookieFactory)
|
||||
{
|
||||
$this->cookieFactory = $cookieFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh transient token cookie for the authenticated user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function refresh(Request $request)
|
||||
{
|
||||
return (new Response('Refreshed.'))->withCookie($this->cookieFactory->make(
|
||||
$request->user()->getAuthIdentifier(), $request->session()->token()
|
||||
));
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\Exceptions\MissingScopeException;
|
||||
|
||||
class CheckClientCredentials extends CheckCredentials
|
||||
{
|
||||
/**
|
||||
* Validate token credentials.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException
|
||||
*/
|
||||
protected function validateCredentials($token)
|
||||
{
|
||||
if (! $token) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate token credentials.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @param array $scopes
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\MissingScopeException
|
||||
*/
|
||||
protected function validateScopes($token, $scopes)
|
||||
{
|
||||
if (in_array('*', $token->scopes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if ($token->cant($scope)) {
|
||||
throw new MissingScopeException($scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\Exceptions\MissingScopeException;
|
||||
|
||||
class CheckClientCredentialsForAnyScope extends CheckCredentials
|
||||
{
|
||||
/**
|
||||
* Validate token credentials.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException
|
||||
*/
|
||||
protected function validateCredentials($token)
|
||||
{
|
||||
if (! $token) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate token credentials.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @param array $scopes
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\MissingScopeException
|
||||
*/
|
||||
protected function validateScopes($token, $scopes)
|
||||
{
|
||||
if (in_array('*', $token->scopes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if ($token->can($scope)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new MissingScopeException($scopes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\TokenRepository;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
||||
|
||||
abstract class CheckCredentials
|
||||
{
|
||||
/**
|
||||
* The Resource Server instance.
|
||||
*
|
||||
* @var \League\OAuth2\Server\ResourceServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Token Repository.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\ResourceServer $server
|
||||
* @param \Laravel\Passport\TokenRepository $repository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ResourceServer $server, TokenRepository $repository)
|
||||
{
|
||||
$this->server = $server;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the scopes for the middleware.
|
||||
*
|
||||
* @param array|string $scopes
|
||||
* @return string
|
||||
*/
|
||||
public static function using(...$scopes)
|
||||
{
|
||||
if (is_array($scopes[0])) {
|
||||
return static::class.':'.implode(',', $scopes[0]);
|
||||
}
|
||||
|
||||
return static::class.':'.implode(',', $scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$scopes
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$scopes)
|
||||
{
|
||||
$psr = (new PsrHttpFactory(
|
||||
new Psr17Factory,
|
||||
new Psr17Factory,
|
||||
new Psr17Factory,
|
||||
new Psr17Factory
|
||||
))->createRequest($request);
|
||||
|
||||
try {
|
||||
$psr = $this->server->validateAuthenticatedRequest($psr);
|
||||
} catch (OAuthServerException $e) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
|
||||
$this->validate($psr, $scopes);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the scopes and token on the incoming request.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $psr
|
||||
* @param array $scopes
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException
|
||||
*/
|
||||
protected function validate($psr, $scopes)
|
||||
{
|
||||
$token = $this->repository->find($psr->getAttribute('oauth_access_token_id'));
|
||||
|
||||
$this->validateCredentials($token);
|
||||
|
||||
$this->validateScopes($token, $scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate token credentials.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException
|
||||
*/
|
||||
abstract protected function validateCredentials($token);
|
||||
|
||||
/**
|
||||
* Validate token scopes.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @param array $scopes
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\MissingScopeException
|
||||
*/
|
||||
abstract protected function validateScopes($token, $scopes);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\Exceptions\MissingScopeException;
|
||||
|
||||
class CheckForAnyScope
|
||||
{
|
||||
/**
|
||||
* Specify the scopes for the middleware.
|
||||
*
|
||||
* @param array|string $scopes
|
||||
* @return string
|
||||
*/
|
||||
public static function using(...$scopes)
|
||||
{
|
||||
if (is_array($scopes[0])) {
|
||||
return static::class.':'.implode(',', $scopes[0]);
|
||||
}
|
||||
|
||||
return static::class.':'.implode(',', $scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$scopes
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException
|
||||
*/
|
||||
public function handle($request, $next, ...$scopes)
|
||||
{
|
||||
if (! $request->user() || ! $request->user()->token()) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if ($request->user()->tokenCan($scope)) {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
throw new MissingScopeException($scopes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Laravel\Passport\Exceptions\AuthenticationException;
|
||||
use Laravel\Passport\Exceptions\MissingScopeException;
|
||||
|
||||
class CheckScopes
|
||||
{
|
||||
/**
|
||||
* Specify the scopes for the middleware.
|
||||
*
|
||||
* @param array|string $scopes
|
||||
* @return string
|
||||
*/
|
||||
public static function using(...$scopes)
|
||||
{
|
||||
if (is_array($scopes[0])) {
|
||||
return static::class.':'.implode(',', $scopes[0]);
|
||||
}
|
||||
|
||||
return static::class.':'.implode(',', $scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$scopes
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException
|
||||
*/
|
||||
public function handle($request, $next, ...$scopes)
|
||||
{
|
||||
if (! $request->user() || ! $request->user()->token()) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if (! $request->user()->tokenCan($scope)) {
|
||||
throw new MissingScopeException($scope);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Passport\ApiTokenCookieFactory;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class CreateFreshApiToken
|
||||
{
|
||||
/**
|
||||
* The API token cookie factory instance.
|
||||
*
|
||||
* @var \Laravel\Passport\ApiTokenCookieFactory
|
||||
*/
|
||||
protected $cookieFactory;
|
||||
|
||||
/**
|
||||
* The authentication guard.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $guard;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param \Laravel\Passport\ApiTokenCookieFactory $cookieFactory
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ApiTokenCookieFactory $cookieFactory)
|
||||
{
|
||||
$this->cookieFactory = $cookieFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the guard for the middleware.
|
||||
*
|
||||
* @param string|null $guard
|
||||
* @return string
|
||||
*/
|
||||
public static function using($guard = null)
|
||||
{
|
||||
$guard = is_null($guard) ? '' : ':'.$guard;
|
||||
|
||||
return static::class.$guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
$this->guard = $guard;
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
if ($this->shouldReceiveFreshToken($request, $response)) {
|
||||
$response->withCookie($this->cookieFactory->make(
|
||||
$request->user($this->guard)->getAuthIdentifier(), $request->session()->token()
|
||||
));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given request should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldReceiveFreshToken($request, $response)
|
||||
{
|
||||
return $this->requestShouldReceiveFreshToken($request) &&
|
||||
$this->responseShouldReceiveFreshToken($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function requestShouldReceiveFreshToken($request)
|
||||
{
|
||||
return $request->isMethod('GET') && $request->user($this->guard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function responseShouldReceiveFreshToken($response)
|
||||
{
|
||||
return ($response instanceof Response ||
|
||||
$response instanceof JsonResponse) &&
|
||||
! $this->alreadyContainsToken($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given response already contains an API token.
|
||||
*
|
||||
* This avoids us overwriting a just "refreshed" token.
|
||||
*
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function alreadyContainsToken($response)
|
||||
{
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
if ($cookie->getName() === Passport::cookie()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Responses;
|
||||
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
use Laravel\Passport\Contracts\AuthorizationViewResponse as AuthorizationViewResponseContract;
|
||||
|
||||
class AuthorizationViewResponse implements AuthorizationViewResponseContract
|
||||
{
|
||||
/**
|
||||
* The name of the view or the callable used to generate the view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* An array of arguments that may be passed to the view response and used in the view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* Create a new response instance.
|
||||
*
|
||||
* @param callable|string $view
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($view)
|
||||
{
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add parameters to response.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function withParameters($parameters = [])
|
||||
{
|
||||
$this->parameters = $parameters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP response that represents the object.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function toResponse($request)
|
||||
{
|
||||
if (! is_callable($this->view) || is_string($this->view)) {
|
||||
return response()->view($this->view, $this->parameters);
|
||||
}
|
||||
|
||||
$response = call_user_func($this->view, $this->parameters);
|
||||
|
||||
if ($response instanceof Responsable) {
|
||||
return $response->toResponse($request);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Factory;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class RedirectRule implements Rule
|
||||
{
|
||||
/**
|
||||
* The validator instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Validation\Factory
|
||||
*/
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
* Create a new rule instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Validation\Factory $validator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Factory $validator)
|
||||
{
|
||||
$this->validator = $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
foreach (explode(',', $value) as $redirect) {
|
||||
$validator = $this->validator->make(['redirect' => $redirect], ['redirect' => new UriRule]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message()
|
||||
{
|
||||
return 'One or more redirects have an invalid URI format.';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport\Http\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class UriRule implements Rule
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
if (filter_var($value, FILTER_VALIDATE_URL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function message(): string
|
||||
{
|
||||
return 'The :attribute must be valid URI.';
|
||||
}
|
||||
}
|
||||
+758
@@ -0,0 +1,758 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Laravel\Passport\Contracts\AuthorizationViewResponse as AuthorizationViewResponseContract;
|
||||
use Laravel\Passport\Http\Responses\AuthorizationViewResponse;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
use Mockery;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class Passport
|
||||
{
|
||||
/**
|
||||
* Indicates if the implicit grant type is enabled.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public static $implicitGrantEnabled = false;
|
||||
|
||||
/**
|
||||
* Indicates if the password grant type is enabled.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public static $passwordGrantEnabled = true;
|
||||
|
||||
/**
|
||||
* The default scope.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $defaultScope;
|
||||
|
||||
/**
|
||||
* All of the scopes defined for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $scopes = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* The interval when access tokens expire.
|
||||
*
|
||||
* @var \DateInterval|null
|
||||
*/
|
||||
public static $tokensExpireIn;
|
||||
|
||||
/**
|
||||
* The date when refresh tokens expire.
|
||||
*
|
||||
* @var \DateInterval|null
|
||||
*/
|
||||
public static $refreshTokensExpireIn;
|
||||
|
||||
/**
|
||||
* The date when personal access tokens expire.
|
||||
*
|
||||
* @var \DateInterval|null
|
||||
*/
|
||||
public static $personalAccessTokensExpireIn;
|
||||
|
||||
/**
|
||||
* The name for API token cookies.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $cookie = 'laravel_token';
|
||||
|
||||
/**
|
||||
* Indicates if Passport should ignore incoming CSRF tokens.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $ignoreCsrfToken = false;
|
||||
|
||||
/**
|
||||
* The storage location of the encryption keys.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $keyPath;
|
||||
|
||||
/**
|
||||
* The access token entity class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $accessTokenEntity = 'Laravel\Passport\Bridge\AccessToken';
|
||||
|
||||
/**
|
||||
* The auth code model class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $authCodeModel = 'Laravel\Passport\AuthCode';
|
||||
|
||||
/**
|
||||
* The client model class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $clientModel = 'Laravel\Passport\Client';
|
||||
|
||||
/**
|
||||
* Indicates if client's are identified by UUIDs.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $clientUuids = false;
|
||||
|
||||
/**
|
||||
* The personal access client model class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $personalAccessClientModel = 'Laravel\Passport\PersonalAccessClient';
|
||||
|
||||
/**
|
||||
* The token model class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $tokenModel = 'Laravel\Passport\Token';
|
||||
|
||||
/**
|
||||
* The refresh token model class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $refreshTokenModel = 'Laravel\Passport\RefreshToken';
|
||||
|
||||
/**
|
||||
* Indicates if Passport migrations will be run.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $runsMigrations = true;
|
||||
|
||||
/**
|
||||
* Indicates if Passport should unserializes cookies.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $unserializesCookies = false;
|
||||
|
||||
/**
|
||||
* Indicates if Passport should decrypt cookies.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $decryptsCookies = true;
|
||||
|
||||
/**
|
||||
* Indicates if client secrets will be hashed.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $hashesClientSecrets = false;
|
||||
|
||||
/**
|
||||
* The callback that should be used to generate JWT encryption keys.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
public static $tokenEncryptionKeyCallback;
|
||||
|
||||
/**
|
||||
* Indicates the scope should inherit its parent scope.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $withInheritedScopes = false;
|
||||
|
||||
/**
|
||||
* The authorization server response type.
|
||||
*
|
||||
* @var \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface|null
|
||||
*/
|
||||
public static $authorizationServerResponseType;
|
||||
|
||||
/**
|
||||
* Indicates if Passport routes will be registered.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $registersRoutes = true;
|
||||
|
||||
/**
|
||||
* Enable the implicit grant type.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function enableImplicitGrant()
|
||||
{
|
||||
static::$implicitGrantEnabled = true;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default scope(s). Multiple scopes may be an array or specified delimited by spaces.
|
||||
*
|
||||
* @param array|string $scope
|
||||
* @return void
|
||||
*/
|
||||
public static function setDefaultScope($scope)
|
||||
{
|
||||
static::$defaultScope = is_array($scope) ? implode(' ', $scope) : $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the defined scope IDs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function scopeIds()
|
||||
{
|
||||
return static::scopes()->pluck('id')->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given scope has been defined.
|
||||
*
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasScope($id)
|
||||
{
|
||||
return $id === '*' || array_key_exists($id, static::$scopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the scopes defined for the application.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function scopes()
|
||||
{
|
||||
return collect(static::$scopes)->map(function ($description, $id) {
|
||||
return new Scope($id, $description);
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the scopes matching the given IDs.
|
||||
*
|
||||
* @param array $ids
|
||||
* @return array
|
||||
*/
|
||||
public static function scopesFor(array $ids)
|
||||
{
|
||||
return collect($ids)->map(function ($id) {
|
||||
if (isset(static::$scopes[$id])) {
|
||||
return new Scope($id, static::$scopes[$id]);
|
||||
}
|
||||
})->filter()->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the scopes for the application.
|
||||
*
|
||||
* @param array $scopes
|
||||
* @return void
|
||||
*/
|
||||
public static function tokensCan(array $scopes)
|
||||
{
|
||||
static::$scopes = $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set when access tokens expire.
|
||||
*
|
||||
* @param \DateTimeInterface|null $date
|
||||
* @return \DateInterval|static
|
||||
*/
|
||||
public static function tokensExpireIn(DateTimeInterface $date = null)
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return static::$tokensExpireIn ?? new DateInterval('P1Y');
|
||||
}
|
||||
|
||||
static::$tokensExpireIn = Carbon::now()->diff($date);
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set when refresh tokens expire.
|
||||
*
|
||||
* @param \DateTimeInterface|null $date
|
||||
* @return \DateInterval|static
|
||||
*/
|
||||
public static function refreshTokensExpireIn(DateTimeInterface $date = null)
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return static::$refreshTokensExpireIn ?? new DateInterval('P1Y');
|
||||
}
|
||||
|
||||
static::$refreshTokensExpireIn = Carbon::now()->diff($date);
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set when personal access tokens expire.
|
||||
*
|
||||
* @param \DateTimeInterface|null $date
|
||||
* @return \DateInterval|static
|
||||
*/
|
||||
public static function personalAccessTokensExpireIn(DateTimeInterface $date = null)
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return static::$personalAccessTokensExpireIn ?? new DateInterval('P1Y');
|
||||
}
|
||||
|
||||
static::$personalAccessTokensExpireIn = Carbon::now()->diff($date);
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the name for API token cookies.
|
||||
*
|
||||
* @param string|null $cookie
|
||||
* @return string|static
|
||||
*/
|
||||
public static function cookie($cookie = null)
|
||||
{
|
||||
if (is_null($cookie)) {
|
||||
return static::$cookie;
|
||||
}
|
||||
|
||||
static::$cookie = $cookie;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that Passport should ignore incoming CSRF tokens.
|
||||
*
|
||||
* @param bool $ignoreCsrfToken
|
||||
* @return static
|
||||
*/
|
||||
public static function ignoreCsrfToken($ignoreCsrfToken = true)
|
||||
{
|
||||
static::$ignoreCsrfToken = $ignoreCsrfToken;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current user for the application with the given scopes.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|\Laravel\Passport\HasApiTokens $user
|
||||
* @param array $scopes
|
||||
* @param string $guard
|
||||
* @return \Illuminate\Contracts\Auth\Authenticatable
|
||||
*/
|
||||
public static function actingAs($user, $scopes = [], $guard = 'api')
|
||||
{
|
||||
$token = app(self::tokenModel());
|
||||
|
||||
$token->scopes = $scopes;
|
||||
|
||||
$user->withAccessToken($token);
|
||||
|
||||
if (isset($user->wasRecentlyCreated) && $user->wasRecentlyCreated) {
|
||||
$user->wasRecentlyCreated = false;
|
||||
}
|
||||
|
||||
app('auth')->guard($guard)->setUser($user);
|
||||
|
||||
app('auth')->shouldUse($guard);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current client for the application with the given scopes.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @param array $scopes
|
||||
* @param string $guard
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public static function actingAsClient($client, $scopes = [], $guard = 'api')
|
||||
{
|
||||
$token = app(self::tokenModel());
|
||||
|
||||
$token->client_id = $client->getKey();
|
||||
$token->setRelation('client', $client);
|
||||
|
||||
$token->scopes = $scopes;
|
||||
|
||||
$mock = Mockery::mock(ResourceServer::class);
|
||||
$mock->shouldReceive('validateAuthenticatedRequest')
|
||||
->andReturnUsing(function (ServerRequestInterface $request) use ($token) {
|
||||
return $request->withAttribute('oauth_client_id', $token->client->id)
|
||||
->withAttribute('oauth_access_token_id', $token->id)
|
||||
->withAttribute('oauth_scopes', $token->scopes);
|
||||
});
|
||||
|
||||
app()->instance(ResourceServer::class, $mock);
|
||||
|
||||
$mock = Mockery::mock(TokenRepository::class);
|
||||
$mock->shouldReceive('find')->andReturn($token);
|
||||
|
||||
app()->instance(TokenRepository::class, $mock);
|
||||
|
||||
app('auth')->guard($guard)->setClient($client);
|
||||
|
||||
app('auth')->shouldUse($guard);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the storage location of the encryption keys.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public static function loadKeysFrom($path)
|
||||
{
|
||||
static::$keyPath = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of the encryption keys.
|
||||
*
|
||||
* @param string $file
|
||||
* @return string
|
||||
*/
|
||||
public static function keyPath($file)
|
||||
{
|
||||
$file = ltrim($file, '/\\');
|
||||
|
||||
return static::$keyPath
|
||||
? rtrim(static::$keyPath, '/\\').DIRECTORY_SEPARATOR.$file
|
||||
: storage_path($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the access token entity class name.
|
||||
*
|
||||
* @param string $accessTokenEntity
|
||||
* @return void
|
||||
*/
|
||||
public static function useAccessTokenEntity($accessTokenEntity)
|
||||
{
|
||||
static::$accessTokenEntity = $accessTokenEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the auth code model class name.
|
||||
*
|
||||
* @param string $authCodeModel
|
||||
* @return void
|
||||
*/
|
||||
public static function useAuthCodeModel($authCodeModel)
|
||||
{
|
||||
static::$authCodeModel = $authCodeModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auth code model class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function authCodeModel()
|
||||
{
|
||||
return static::$authCodeModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new auth code model instance.
|
||||
*
|
||||
* @return \Laravel\Passport\AuthCode
|
||||
*/
|
||||
public static function authCode()
|
||||
{
|
||||
return new static::$authCodeModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client model class name.
|
||||
*
|
||||
* @param string $clientModel
|
||||
* @return void
|
||||
*/
|
||||
public static function useClientModel($clientModel)
|
||||
{
|
||||
static::$clientModel = $clientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client model class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function clientModel()
|
||||
{
|
||||
return static::$clientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new client model instance.
|
||||
*
|
||||
* @return \Laravel\Passport\Client
|
||||
*/
|
||||
public static function client()
|
||||
{
|
||||
return new static::$clientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if clients are identified using UUIDs.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function clientUuids()
|
||||
{
|
||||
return static::$clientUuids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if clients are identified using UUIDs.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public static function setClientUuids($value)
|
||||
{
|
||||
static::$clientUuids = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the personal access client model class name.
|
||||
*
|
||||
* @param string $clientModel
|
||||
* @return void
|
||||
*/
|
||||
public static function usePersonalAccessClientModel($clientModel)
|
||||
{
|
||||
static::$personalAccessClientModel = $clientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the personal access client model class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function personalAccessClientModel()
|
||||
{
|
||||
return static::$personalAccessClientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new personal access client model instance.
|
||||
*
|
||||
* @return \Laravel\Passport\PersonalAccessClient
|
||||
*/
|
||||
public static function personalAccessClient()
|
||||
{
|
||||
return new static::$personalAccessClientModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the token model class name.
|
||||
*
|
||||
* @param string $tokenModel
|
||||
* @return void
|
||||
*/
|
||||
public static function useTokenModel($tokenModel)
|
||||
{
|
||||
static::$tokenModel = $tokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token model class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function tokenModel()
|
||||
{
|
||||
return static::$tokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new personal access client model instance.
|
||||
*
|
||||
* @return \Laravel\Passport\Token
|
||||
*/
|
||||
public static function token()
|
||||
{
|
||||
return new static::$tokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the refresh token model class name.
|
||||
*
|
||||
* @param string $refreshTokenModel
|
||||
* @return void
|
||||
*/
|
||||
public static function useRefreshTokenModel($refreshTokenModel)
|
||||
{
|
||||
static::$refreshTokenModel = $refreshTokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the refresh token model class name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function refreshTokenModel()
|
||||
{
|
||||
return static::$refreshTokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new refresh token model instance.
|
||||
*
|
||||
* @return \Laravel\Passport\RefreshToken
|
||||
*/
|
||||
public static function refreshToken()
|
||||
{
|
||||
return new static::$refreshTokenModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Passport to hash client credential secrets.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function hashClientSecrets()
|
||||
{
|
||||
static::$hashesClientSecrets = true;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the callback that should be invoked to generate encryption keys for encrypting JWT tokens.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return static
|
||||
*/
|
||||
public static function encryptTokensUsing($callback)
|
||||
{
|
||||
static::$tokenEncryptionKeyCallback = $callback;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an encryption key for encrypting JWT tokens.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @return string
|
||||
*/
|
||||
public static function tokenEncryptionKey(Encrypter $encrypter)
|
||||
{
|
||||
return is_callable(static::$tokenEncryptionKeyCallback) ?
|
||||
(static::$tokenEncryptionKeyCallback)($encrypter) :
|
||||
$encrypter->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which view should be used as the authorization view.
|
||||
*
|
||||
* @param callable|string $view
|
||||
* @return void
|
||||
*/
|
||||
public static function authorizationView($view)
|
||||
{
|
||||
app()->singleton(AuthorizationViewResponseContract::class, function ($app) use ($view) {
|
||||
return new AuthorizationViewResponse($view);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Passport to not register its routes.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function ignoreRoutes()
|
||||
{
|
||||
static::$registersRoutes = false;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Passport to not register its migrations.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function ignoreMigrations()
|
||||
{
|
||||
static::$runsMigrations = false;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruct Passport to enable cookie serialization.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function withCookieSerialization()
|
||||
{
|
||||
static::$unserializesCookies = true;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruct Passport to disable cookie serialization.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function withoutCookieSerialization()
|
||||
{
|
||||
static::$unserializesCookies = false;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruct Passport to enable cookie encryption.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function withCookieEncryption()
|
||||
{
|
||||
static::$decryptsCookies = true;
|
||||
|
||||
return new static;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instruct Passport to disable cookie encryption.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function withoutCookieEncryption()
|
||||
{
|
||||
static::$decryptsCookies = false;
|
||||
|
||||
return new static;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use DateInterval;
|
||||
use Illuminate\Auth\Events\Logout;
|
||||
use Illuminate\Config\Repository as Config;
|
||||
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Passport\Bridge\PersonalAccessGrant;
|
||||
use Laravel\Passport\Bridge\RefreshTokenRepository;
|
||||
use Laravel\Passport\Guards\TokenGuard;
|
||||
use Laravel\Passport\Http\Controllers\AuthorizationController;
|
||||
use Lcobucci\JWT\Encoding\JoseEncoder;
|
||||
use Lcobucci\JWT\Parser as ParserContract;
|
||||
use Lcobucci\JWT\Token\Parser;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\CryptKey;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
|
||||
use League\OAuth2\Server\Grant\ImplicitGrant;
|
||||
use League\OAuth2\Server\Grant\PasswordGrant;
|
||||
use League\OAuth2\Server\Grant\RefreshTokenGrant;
|
||||
use League\OAuth2\Server\ResourceServer;
|
||||
|
||||
class PassportServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerRoutes();
|
||||
$this->registerResources();
|
||||
$this->registerMigrations();
|
||||
$this->registerPublishing();
|
||||
$this->registerCommands();
|
||||
|
||||
$this->deleteCookieOnLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Passport routes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerRoutes()
|
||||
{
|
||||
if (Passport::$registersRoutes) {
|
||||
Route::group([
|
||||
'as' => 'passport.',
|
||||
'prefix' => config('passport.path', 'oauth'),
|
||||
'namespace' => 'Laravel\Passport\Http\Controllers',
|
||||
], function () {
|
||||
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Passport resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerResources()
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__.'/../resources/views', 'passport');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Passport migration files.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrations()
|
||||
{
|
||||
if ($this->app->runningInConsole() && Passport::$runsMigrations && ! Passport::clientUuids()) {
|
||||
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the package's publishable resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerPublishing()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->publishes([
|
||||
__DIR__.'/../database/migrations' => database_path('migrations'),
|
||||
], 'passport-migrations');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__.'/../resources/views' => base_path('resources/views/vendor/passport'),
|
||||
], 'passport-views');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__.'/../config/passport.php' => config_path('passport.php'),
|
||||
], 'passport-config');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Passport Artisan commands.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCommands()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
Console\InstallCommand::class,
|
||||
Console\ClientCommand::class,
|
||||
Console\HashCommand::class,
|
||||
Console\KeysCommand::class,
|
||||
Console\PurgeCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport');
|
||||
|
||||
Passport::setClientUuids($this->app->make(Config::class)->get('passport.client_uuids', false));
|
||||
|
||||
$this->app->when(AuthorizationController::class)
|
||||
->needs(StatefulGuard::class)
|
||||
->give(fn () => Auth::guard(config('passport.guard', null)));
|
||||
|
||||
$this->registerAuthorizationServer();
|
||||
$this->registerClientRepository();
|
||||
$this->registerJWTParser();
|
||||
$this->registerResourceServer();
|
||||
$this->registerGuard();
|
||||
|
||||
Passport::authorizationView('passport::authorize');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the authorization server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerAuthorizationServer()
|
||||
{
|
||||
$this->app->singleton(AuthorizationServer::class, function () {
|
||||
return tap($this->makeAuthorizationServer(), function ($server) {
|
||||
$server->setDefaultScope(Passport::$defaultScope);
|
||||
|
||||
$server->enableGrantType(
|
||||
$this->makeAuthCodeGrant(), Passport::tokensExpireIn()
|
||||
);
|
||||
|
||||
$server->enableGrantType(
|
||||
$this->makeRefreshTokenGrant(), Passport::tokensExpireIn()
|
||||
);
|
||||
|
||||
if (Passport::$passwordGrantEnabled) {
|
||||
$server->enableGrantType(
|
||||
$this->makePasswordGrant(), Passport::tokensExpireIn()
|
||||
);
|
||||
}
|
||||
|
||||
$server->enableGrantType(
|
||||
new PersonalAccessGrant, Passport::personalAccessTokensExpireIn()
|
||||
);
|
||||
|
||||
$server->enableGrantType(
|
||||
new ClientCredentialsGrant, Passport::tokensExpireIn()
|
||||
);
|
||||
|
||||
if (Passport::$implicitGrantEnabled) {
|
||||
$server->enableGrantType(
|
||||
$this->makeImplicitGrant(), Passport::tokensExpireIn()
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure an instance of the Auth Code grant.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Grant\AuthCodeGrant
|
||||
*/
|
||||
protected function makeAuthCodeGrant()
|
||||
{
|
||||
return tap($this->buildAuthCodeGrant(), function ($grant) {
|
||||
$grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Auth Code grant instance.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Grant\AuthCodeGrant
|
||||
*/
|
||||
protected function buildAuthCodeGrant()
|
||||
{
|
||||
return new AuthCodeGrant(
|
||||
$this->app->make(Bridge\AuthCodeRepository::class),
|
||||
$this->app->make(Bridge\RefreshTokenRepository::class),
|
||||
new DateInterval('PT10M')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure a Refresh Token grant instance.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Grant\RefreshTokenGrant
|
||||
*/
|
||||
protected function makeRefreshTokenGrant()
|
||||
{
|
||||
$repository = $this->app->make(RefreshTokenRepository::class);
|
||||
|
||||
return tap(new RefreshTokenGrant($repository), function ($grant) {
|
||||
$grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure a Password grant instance.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Grant\PasswordGrant
|
||||
*/
|
||||
protected function makePasswordGrant()
|
||||
{
|
||||
$grant = new PasswordGrant(
|
||||
$this->app->make(Bridge\UserRepository::class),
|
||||
$this->app->make(Bridge\RefreshTokenRepository::class)
|
||||
);
|
||||
|
||||
$grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
|
||||
|
||||
return $grant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure an instance of the Implicit grant.
|
||||
*
|
||||
* @return \League\OAuth2\Server\Grant\ImplicitGrant
|
||||
*/
|
||||
protected function makeImplicitGrant()
|
||||
{
|
||||
return new ImplicitGrant(Passport::tokensExpireIn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the authorization service instance.
|
||||
*
|
||||
* @return \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
public function makeAuthorizationServer()
|
||||
{
|
||||
return new AuthorizationServer(
|
||||
$this->app->make(Bridge\ClientRepository::class),
|
||||
$this->app->make(Bridge\AccessTokenRepository::class),
|
||||
$this->app->make(Bridge\ScopeRepository::class),
|
||||
$this->makeCryptKey('private'),
|
||||
app('encrypter')->getKey(),
|
||||
Passport::$authorizationServerResponseType
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the client repository.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerClientRepository()
|
||||
{
|
||||
$this->app->singleton(ClientRepository::class, function ($container) {
|
||||
$config = $container->make('config')->get('passport.personal_access_client');
|
||||
|
||||
return new ClientRepository($config['id'] ?? null, $config['secret'] ?? null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the JWT Parser.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerJWTParser()
|
||||
{
|
||||
$this->app->singleton(ParserContract::class, function () {
|
||||
return new Parser(new JoseEncoder);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the resource server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerResourceServer()
|
||||
{
|
||||
$this->app->singleton(ResourceServer::class, function ($container) {
|
||||
return new ResourceServer(
|
||||
$container->make(Bridge\AccessTokenRepository::class),
|
||||
$this->makeCryptKey('public')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CryptKey instance without permissions check.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \League\OAuth2\Server\CryptKey
|
||||
*/
|
||||
protected function makeCryptKey($type)
|
||||
{
|
||||
$key = str_replace('\\n', "\n", $this->app->make(Config::class)->get('passport.'.$type.'_key') ?? '');
|
||||
|
||||
if (! $key) {
|
||||
$key = 'file://'.Passport::keyPath('oauth-'.$type.'.key');
|
||||
}
|
||||
|
||||
return new CryptKey($key, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the token guard.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerGuard()
|
||||
{
|
||||
Auth::resolved(function ($auth) {
|
||||
$auth->extend('passport', function ($app, $name, array $config) {
|
||||
return tap($this->makeGuard($config), function ($guard) {
|
||||
app()->refresh('request', $guard, 'setRequest');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an instance of the token guard.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Laravel\Passport\Guards\TokenGuard
|
||||
*/
|
||||
protected function makeGuard(array $config)
|
||||
{
|
||||
return new TokenGuard(
|
||||
$this->app->make(ResourceServer::class),
|
||||
new PassportUserProvider(Auth::createUserProvider($config['provider']), $config['provider']),
|
||||
$this->app->make(TokenRepository::class),
|
||||
$this->app->make(ClientRepository::class),
|
||||
$this->app->make('encrypter'),
|
||||
$this->app->make('request')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the cookie deletion event handler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function deleteCookieOnLogout()
|
||||
{
|
||||
Event::listen(Logout::class, function () {
|
||||
if (Request::hasCookie(Passport::cookie())) {
|
||||
Cookie::queue(Cookie::forget(Passport::cookie()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
|
||||
class PassportUserProvider implements UserProvider
|
||||
{
|
||||
/**
|
||||
* The user provider instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\UserProvider
|
||||
*/
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* The user provider name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $providerName;
|
||||
|
||||
/**
|
||||
* Create a new passport user provider.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider $provider
|
||||
* @param string $providerName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(UserProvider $provider, $providerName)
|
||||
{
|
||||
$this->provider = $provider;
|
||||
$this->providerName = $providerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function retrieveById($identifier)
|
||||
{
|
||||
return $this->provider->retrieveById($identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function retrieveByToken($identifier, $token)
|
||||
{
|
||||
return $this->provider->retrieveByToken($identifier, $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function updateRememberToken(Authenticatable $user, $token)
|
||||
{
|
||||
$this->provider->updateRememberToken($user, $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
return $this->provider->retrieveByCredentials($credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateCredentials(Authenticatable $user, array $credentials)
|
||||
{
|
||||
return $this->provider->validateCredentials($user, $credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the user provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProviderName()
|
||||
{
|
||||
return $this->providerName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PersonalAccessClient extends Model
|
||||
{
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'oauth_personal_access_clients';
|
||||
|
||||
/**
|
||||
* The guarded attributes on the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get all of the authentication codes for the client.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(Passport::clientModel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Lcobucci\JWT\Parser as JwtParser;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use Nyholm\Psr7\Response;
|
||||
use Nyholm\Psr7\ServerRequest;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class PersonalAccessTokenFactory
|
||||
{
|
||||
/**
|
||||
* The authorization server instance.
|
||||
*
|
||||
* @var \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* The client repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\ClientRepository
|
||||
*/
|
||||
protected $clients;
|
||||
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var \Laravel\Passport\TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* The JWT token parser instance.
|
||||
*
|
||||
* @var \Lcobucci\JWT\Parser
|
||||
*/
|
||||
protected $jwt;
|
||||
|
||||
/**
|
||||
* Create a new personal access token factory instance.
|
||||
*
|
||||
* @param \League\OAuth2\Server\AuthorizationServer $server
|
||||
* @param \Laravel\Passport\ClientRepository $clients
|
||||
* @param \Laravel\Passport\TokenRepository $tokens
|
||||
* @param \Lcobucci\JWT\Parser $jwt
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AuthorizationServer $server,
|
||||
ClientRepository $clients,
|
||||
TokenRepository $tokens,
|
||||
JwtParser $jwt)
|
||||
{
|
||||
$this->jwt = $jwt;
|
||||
$this->tokens = $tokens;
|
||||
$this->server = $server;
|
||||
$this->clients = $clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new personal access token.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @param string $name
|
||||
* @param array $scopes
|
||||
* @return \Laravel\Passport\PersonalAccessTokenResult
|
||||
*/
|
||||
public function make($userId, $name, array $scopes = [])
|
||||
{
|
||||
$response = $this->dispatchRequestToAuthorizationServer(
|
||||
$this->createRequest($this->clients->personalAccessClient(), $userId, $scopes)
|
||||
);
|
||||
|
||||
$token = tap($this->findAccessToken($response), function ($token) use ($userId, $name) {
|
||||
$this->tokens->save($token->forceFill([
|
||||
'user_id' => $userId,
|
||||
'name' => $name,
|
||||
]));
|
||||
});
|
||||
|
||||
return new PersonalAccessTokenResult(
|
||||
$response['access_token'], $token
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request instance for the given client.
|
||||
*
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @param mixed $userId
|
||||
* @param array $scopes
|
||||
* @return \Psr\Http\Message\ServerRequestInterface
|
||||
*/
|
||||
protected function createRequest($client, $userId, array $scopes)
|
||||
{
|
||||
$secret = Passport::$hashesClientSecrets ? $this->clients->getPersonalAccessClientSecret() : $client->secret;
|
||||
|
||||
return (new ServerRequest('POST', 'not-important'))->withParsedBody([
|
||||
'grant_type' => 'personal_access',
|
||||
'client_id' => $client->getKey(),
|
||||
'client_secret' => $secret,
|
||||
'user_id' => $userId,
|
||||
'scope' => implode(' ', $scopes),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the given request to the authorization server.
|
||||
*
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @return array
|
||||
*/
|
||||
protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $request)
|
||||
{
|
||||
return json_decode($this->server->respondToAccessTokenRequest(
|
||||
$request, new Response
|
||||
)->getBody()->__toString(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the access token instance for the parsed response.
|
||||
*
|
||||
* @param array $response
|
||||
* @return \Laravel\Passport\Token
|
||||
*/
|
||||
public function findAccessToken(array $response)
|
||||
{
|
||||
return $this->tokens->find(
|
||||
$this->jwt->parse($response['access_token'])->claims()->get('jti')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
|
||||
class PersonalAccessTokenResult implements Arrayable, Jsonable
|
||||
{
|
||||
/**
|
||||
* The access token.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $accessToken;
|
||||
|
||||
/**
|
||||
* The token model instance.
|
||||
*
|
||||
* @var \Laravel\Passport\Token
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Create a new result instance.
|
||||
*
|
||||
* @param string $accessToken
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($accessToken, $token)
|
||||
{
|
||||
$this->token = $token;
|
||||
$this->accessToken = $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instance as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'accessToken' => $this->accessToken,
|
||||
'token' => $this->token,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object to its JSON representation.
|
||||
*
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
public function toJson($options = 0)
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class RefreshToken extends Model
|
||||
{
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'oauth_refresh_tokens';
|
||||
|
||||
/**
|
||||
* The "type" of the primary key ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyType = 'string';
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The guarded attributes on the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'revoked' => 'bool',
|
||||
'expires_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Get the access token that the refresh token belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function accessToken()
|
||||
{
|
||||
return $this->belongsTo(Passport::tokenModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke the token instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function revoke()
|
||||
{
|
||||
return $this->forceFill(['revoked' => true])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token is a transient JWT token.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transient()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
class RefreshTokenRepository
|
||||
{
|
||||
/**
|
||||
* Creates a new refresh token.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Laravel\Passport\RefreshToken
|
||||
*/
|
||||
public function create($attributes)
|
||||
{
|
||||
return Passport::refreshToken()->create($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a refresh token by the given ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Laravel\Passport\RefreshToken
|
||||
*/
|
||||
public function find($id)
|
||||
{
|
||||
return Passport::refreshToken()->where('id', $id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given token instance.
|
||||
*
|
||||
* @param \Laravel\Passport\RefreshToken $token
|
||||
* @return void
|
||||
*/
|
||||
public function save(RefreshToken $token)
|
||||
{
|
||||
$token->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes the refresh token.
|
||||
*
|
||||
* @param string $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function revokeRefreshToken($id)
|
||||
{
|
||||
return Passport::refreshToken()->where('id', $id)->update(['revoked' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes refresh tokens by access token id.
|
||||
*
|
||||
* @param string $tokenId
|
||||
* @return mixed
|
||||
*/
|
||||
public function revokeRefreshTokensByAccessTokenId($tokenId)
|
||||
{
|
||||
return Passport::refreshToken()->where('access_token_id', $tokenId)->update(['revoked' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the refresh token has been revoked.
|
||||
*
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function isRefreshTokenRevoked($id)
|
||||
{
|
||||
if ($token = $this->find($id)) {
|
||||
return $token->revoked;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
trait ResolvesInheritedScopes
|
||||
{
|
||||
/**
|
||||
* Resolve all possible scopes.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return array
|
||||
*/
|
||||
protected function resolveInheritedScopes($scope)
|
||||
{
|
||||
$parts = explode(':', $scope);
|
||||
|
||||
$partsCount = count($parts);
|
||||
|
||||
$scopes = [];
|
||||
|
||||
for ($i = 1; $i <= $partsCount; $i++) {
|
||||
$scopes[] = implode(':', array_slice($parts, 0, $i));
|
||||
}
|
||||
|
||||
return $scopes;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
|
||||
class Scope implements Arrayable, Jsonable
|
||||
{
|
||||
/**
|
||||
* The name / ID of the scope.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The scope description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* Create a new scope instance.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $description
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($id, $description)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the instance as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'description' => $this->description,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object to its JSON representation.
|
||||
*
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
public function toJson($options = 0)
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Token extends Model
|
||||
{
|
||||
use ResolvesInheritedScopes;
|
||||
|
||||
/**
|
||||
* The database table used by the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'oauth_access_tokens';
|
||||
|
||||
/**
|
||||
* The "type" of the primary key ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyType = 'string';
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The guarded attributes on the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'scopes' => 'array',
|
||||
'revoked' => 'bool',
|
||||
'expires_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the client that the token belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(Passport::clientModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that the token belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
$provider = config('auth.guards.api.provider');
|
||||
|
||||
$model = config('auth.providers.'.$provider.'.model');
|
||||
|
||||
return $this->belongsTo($model, 'user_id', (new $model)->getKeyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token has a given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function can($scope)
|
||||
{
|
||||
if (in_array('*', $this->scopes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$scopes = Passport::$withInheritedScopes
|
||||
? $this->resolveInheritedScopes($scope)
|
||||
: [$scope];
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
if (array_key_exists($scope, array_flip($this->scopes))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token is missing a given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function cant($scope)
|
||||
{
|
||||
return ! $this->can($scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke the token instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function revoke()
|
||||
{
|
||||
return $this->forceFill(['revoked' => true])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token is a transient JWT token.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transient()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class TokenRepository
|
||||
{
|
||||
/**
|
||||
* Creates a new Access Token.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Laravel\Passport\Token
|
||||
*/
|
||||
public function create($attributes)
|
||||
{
|
||||
return Passport::token()->create($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a token by the given ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Laravel\Passport\Token
|
||||
*/
|
||||
public function find($id)
|
||||
{
|
||||
return Passport::token()->where('id', $id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a token by the given user ID and token ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @param int $userId
|
||||
* @return \Laravel\Passport\Token|null
|
||||
*/
|
||||
public function findForUser($id, $userId)
|
||||
{
|
||||
return Passport::token()->where('id', $id)->where('user_id', $userId)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the token instances for the given user ID.
|
||||
*
|
||||
* @param mixed $userId
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function forUser($userId)
|
||||
{
|
||||
return Passport::token()->where('user_id', $userId)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a valid token instance for the given user and client.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return \Laravel\Passport\Token|null
|
||||
*/
|
||||
public function getValidToken($user, $client)
|
||||
{
|
||||
return $client->tokens()
|
||||
->whereUserId($user->getAuthIdentifier())
|
||||
->where('revoked', 0)
|
||||
->where('expires_at', '>', Carbon::now())
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given token instance.
|
||||
*
|
||||
* @param \Laravel\Passport\Token $token
|
||||
* @return void
|
||||
*/
|
||||
public function save(Token $token)
|
||||
{
|
||||
$token->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke an access token.
|
||||
*
|
||||
* @param string $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function revokeAccessToken($id)
|
||||
{
|
||||
return Passport::token()->where('id', $id)->update(['revoked' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the access token has been revoked.
|
||||
*
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function isAccessTokenRevoked($id)
|
||||
{
|
||||
if ($token = $this->find($id)) {
|
||||
return $token->revoked;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a valid token for the given user and client.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Laravel\Passport\Client $client
|
||||
* @return \Laravel\Passport\Token|null
|
||||
*/
|
||||
public function findValidToken($user, $client)
|
||||
{
|
||||
return $client->tokens()
|
||||
->whereUserId($user->getAuthIdentifier())
|
||||
->where('revoked', 0)
|
||||
->where('expires_at', '>', Carbon::now())
|
||||
->latest('expires_at')
|
||||
->first();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Passport;
|
||||
|
||||
class TransientToken
|
||||
{
|
||||
/**
|
||||
* Determine if the token has a given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function can($scope)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token is missing a given scope.
|
||||
*
|
||||
* @param string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public function cant($scope)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the token is a transient JWT token.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transient()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user