Skip to content

Instantly share code, notes, and snippets.

@mhulu
Last active May 6, 2017 10:16
Show Gist options
  • Save mhulu/a4bded998287528d1f6efd2c1a66f156 to your computer and use it in GitHub Desktop.
Save mhulu/a4bded998287528d1f6efd2c1a66f156 to your computer and use it in GitHub Desktop.
Laravel5.4 passport multi auth demo

run php artisan passport:client --password

change config/auth.php

    ...
    'api_manager' => [
      'driver' => 'passport',
      'provider' => 'managers'
    ]
  ],
  'providers' => [
    ...
    'managers' => [
      'driver' => 'eloquent',
      'model' => App\Manager::class
    ]
  ]

Change passport UserRepository.php and PasswordGrant.php

Usage like LoginProxy

    $user = $this->user->where('mobile', $mobile)->first();
    if(!is_null($user)) {
      return $this->proxy('password', [
        'username' => $mobile,
        'password' => $password,
        'provider' => $provider
      ]);
    }
  }
<?php
namespace Star\ICenter\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Star\ICenter\Proxy\LoginProxy;
use Star\ICenter\Requests\LoginRequest;
class LoginController extends Controller {
private $loginProxy;
public function __construct(LoginProxy $loginProxy) {
$this->loginProxy = $loginProxy;
}
public function login(LoginRequest $request) {
$mobile = $request->get('mobile');
$password = $request->get('password');
$provider = $request->get('provider');
return $this->loginProxy->attemptLogin($mobile, $password, $provider);
}
public function refresh(Request $request) {
return $this->response($this->loginProxy->attemptRefresh());
}
public function logout() {
$this->loginProxy->logout();
return $this->response(null, 204);
}
}
<?php
namespace Star\ICenter\Proxy;
use App\User;
use GuzzleHttp\Client;
use Star\utils\StarJson;
class LoginProxy {
const REFRESH_TOKEN = 'refreshToken';
private $client;
private $user;
public function __construct(User $user, Client $client) {
$this->user = $user;
$this->client = $client;
}
public function attemptLogin($mobile, $password) {
$user = $this->user->where('mobile', $mobile)->first();
if (!is_null($user)) {
return $this->proxy('password', [
'username' => $mobile,
'password' => $password,
]);
}
return StarJson::create(401);
}
/**
* Attempt to refresh the access token used a refresh token that
* has been saved in a cookie
*/
public function attemptRefresh() {
$refreshToken = $this->request->cookie(self::REFRESH_TOKEN);
return $this->proxy('refresh_token', [
'refresh_token' => $refreshToken,
]);
}
/**
* Proxy a request to the OAuth server.
*
* @param string $grantType what type of grant type should be proxied
* @param array $data the data to send to the server
*/
public function proxy($grant_type, array $data = []) {
$data = array_merge($data, [
'client_id' => env('PASSWORD_CLIENT_ID'),
'client_secret' => env('PASSWORD_CLIENT_SECRET'),
'grant_type' => $grant_type,
'scope' => '*',
]);
$response = $this->client->post(url('/oauth/token'), [
'form_params' => $data,
]);
// if (!$response->isSuccessful()) {
// return StarJson::create(401);
// }
$data = json_decode($response->getBody()->getContents());
return StarJson::create(200, [
'token_type' => $data->token_type,
'access_token' => $data->access_token,
'refresh_token' => $data->refresh_token,
'expires_in' => $data->expires_in,
// 'provider' => 'patients',
]);
}
/**
* Logs out the user. We revoke access token and refresh token.
* Also instruct the client to forget the refresh cookie.
*/
public function logout() {
$accessToken = $this->auth->user()->token();
$refreshToken = $this->db
->table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true,
]);
$accessToken->revoke();
}
}
<?php
/**
* OAuth 2.0 Password grant.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Password grant class.
*/
class PasswordGrant extends AbstractGrant {
/**
* @param UserRepositoryInterface $userRepository
* @param RefreshTokenRepositoryInterface $refreshTokenRepository
*/
public function __construct(
UserRepositoryInterface $userRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository
) {
$this->setUserRepository($userRepository);
$this->setRefreshTokenRepository($refreshTokenRepository);
$this->refreshTokenTTL = new \DateInterval('P1M');
}
/**
* {@inheritdoc}
*/
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
$user = $this->validateUser($request, $client);
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier());
// Issue and persist new tokens
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes);
$refreshToken = $this->issueRefreshToken($accessToken);
// Inject tokens into response
$responseType->setAccessToken($accessToken);
$responseType->setRefreshToken($refreshToken);
return $responseType;
}
/**
* @param ServerRequestInterface $request
* @param ClientEntityInterface $client
*
* @throws OAuthServerException
*
* @return UserEntityInterface
*/
protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client) {
$username = $this->getRequestParameter('username', $request);
$provider = $this->getRequestParameter('provider', $request);
if (is_null($username)) {
throw OAuthServerException::invalidRequest('username');
}
$password = $this->getRequestParameter('password', $request);
if (is_null($password)) {
throw OAuthServerException::invalidRequest('password');
}
// $user = $this->userRepository->getUserEntityByUserCredentials(
$user = $this->userRepository->getEntityByUserCredentials(
$username,
$password,
$this->getIdentifier(),
$client,
$provider
);
if ($user instanceof UserEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidCredentials();
}
return $user;
}
/**
* {@inheritdoc}
*/
public function getIdentifier() {
return 'password';
}
}
<?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 = 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, '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());
}
// Change to multi-auth by https://github.com/laravel/passport/issues/161
public function getEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity, $provider) {
$provider = config('auth.guards.' . $provider . '.provider');
if (is_null($model = config('auth.providers.' . $provider . '.model'))) {
throw new RuntimeException('Unable to determine authentication model from configuration.');
}
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());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment