signifly /
laravel-janitor
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Signifly\Janitor; |
||
| 4 | |||
| 5 | use GuzzleHttp\Client as HttpClient; |
||
| 6 | use Illuminate\Auth\Events\Attempting; |
||
| 7 | use Illuminate\Auth\Events\Authenticated; |
||
| 8 | use Illuminate\Auth\Events\Failed; |
||
| 9 | use Illuminate\Auth\Events\Login; |
||
| 10 | use Illuminate\Auth\Events\Logout; |
||
| 11 | use Illuminate\Http\Response; |
||
| 12 | use Illuminate\Support\Arr; |
||
| 13 | use Illuminate\Support\Facades\Auth; |
||
| 14 | use Illuminate\Support\Facades\DB; |
||
| 15 | use Laravel\Passport\Passport; |
||
| 16 | use Signifly\Janitor\Exceptions\InvalidClientCredentialsException; |
||
| 17 | use Signifly\Janitor\Exceptions\InvalidCredentialsException; |
||
| 18 | use Symfony\Component\HttpKernel\Exception\HttpException; |
||
| 19 | |||
| 20 | class PassportProxy extends AbstractProxy |
||
| 21 | { |
||
| 22 | /** |
||
| 23 | * Attempt to log the user in by username and password. |
||
| 24 | * |
||
| 25 | * @param string $username |
||
| 26 | * @param mixed $password |
||
| 27 | * @return array |
||
| 28 | */ |
||
| 29 | public function attemptLogin($username, $password): array |
||
| 30 | { |
||
| 31 | $credentials = [ |
||
| 32 | $this->getUsernameField() => $username, |
||
| 33 | 'password' => $password, |
||
| 34 | ]; |
||
| 35 | |||
| 36 | event(new Attempting($this->getGuard(), $credentials, false)); |
||
| 37 | |||
| 38 | $user = $this->getUserProvider() |
||
| 39 | ->retrieveByCredentials($credentials); |
||
| 40 | |||
| 41 | if (is_null($user)) { |
||
| 42 | event(new Failed($this->getGuard(), $user, $credentials)); |
||
| 43 | throw InvalidCredentialsException::forUsername($username); |
||
| 44 | } |
||
| 45 | |||
| 46 | $response = $this->proxy('password', [ |
||
| 47 | 'username' => $username, |
||
| 48 | 'password' => $password, |
||
| 49 | ], $user); |
||
| 50 | |||
| 51 | event(new Authenticated($this->getGuard(), $user)); |
||
| 52 | event(new Login($this->getGuard(), $user, false)); |
||
| 53 | |||
| 54 | return $response; |
||
| 55 | } |
||
| 56 | |||
| 57 | /** |
||
| 58 | * Attempt refreshing the token. |
||
| 59 | * |
||
| 60 | * @param string|null $refreshToken |
||
| 61 | * @return array |
||
| 62 | */ |
||
| 63 | public function attemptRefresh($refreshToken = null): array |
||
| 64 | { |
||
| 65 | return $this->proxy('refresh_token', [ |
||
| 66 | 'refresh_token' => $refreshToken, |
||
| 67 | ]); |
||
| 68 | } |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Attempt to log the user out. |
||
| 72 | * |
||
| 73 | * @return void |
||
| 74 | */ |
||
| 75 | public function attemptLogout(): void |
||
| 76 | { |
||
| 77 | $user = Auth::user(); |
||
| 78 | |||
| 79 | $accessToken = $this->getAccessToken(); |
||
| 80 | |||
| 81 | DB::table('oauth_refresh_tokens') |
||
| 82 | ->where('access_token_id', $accessToken->id) |
||
| 83 | ->update([ |
||
| 84 | 'revoked' => true, |
||
| 85 | ]); |
||
| 86 | |||
| 87 | if (! $accessToken->revoke()) { |
||
| 88 | throw new HttpException(409, 'Could not revoke access token.'); |
||
| 89 | } |
||
| 90 | |||
| 91 | event(new Logout($this->getGuard(), $user)); |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Proxy request to passport. |
||
| 96 | * |
||
| 97 | * @param string $grantType |
||
| 98 | * @param array $data |
||
| 99 | * @param \Illuminate\Contracts\Auth\Authenticatable|null $user |
||
| 100 | * @return array |
||
| 101 | */ |
||
| 102 | public function proxy($grantType, array $data = [], $user = null): array |
||
| 103 | { |
||
| 104 | $data = array_merge($data, $this->getClientCredentials(), [ |
||
| 105 | 'grant_type' => $grantType, |
||
| 106 | ]); |
||
| 107 | |||
| 108 | $client = new HttpClient(['http_errors' => false]); |
||
| 109 | $response = $client->post($this->config['oauth_token_url'], [ |
||
| 110 | 'form_params' => $data, |
||
| 111 | ]); |
||
| 112 | |||
| 113 | if ($response->getStatusCode() !== Response::HTTP_OK) { |
||
| 114 | event(new Failed($this->getGuard(), $user, $data)); |
||
| 115 | throw InvalidCredentialsException::withDefaultMessage(); |
||
| 116 | } |
||
| 117 | |||
| 118 | $data = json_decode((string) $response->getBody(), true); |
||
| 119 | |||
| 120 | return Arr::only($data, [ |
||
| 121 | 'access_token', |
||
| 122 | 'expires_in', |
||
| 123 | 'refresh_token', |
||
| 124 | 'token_type', |
||
| 125 | ]); |
||
| 126 | } |
||
| 127 | |||
| 128 | /** |
||
| 129 | * Get access token. |
||
| 130 | * |
||
| 131 | * @return object |
||
| 132 | */ |
||
| 133 | protected function getAccessToken() |
||
| 134 | { |
||
| 135 | return Auth::user()->token(); |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 136 | } |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Get the client credentials. |
||
| 140 | * |
||
| 141 | * @return array |
||
| 142 | */ |
||
| 143 | protected function getClientCredentials(): array |
||
| 144 | { |
||
| 145 | $clientModel = $this->config['client_model'] ?? Passport::clientModel(); |
||
| 146 | |||
| 147 | $client = $clientModel::where('password_client', true) |
||
| 148 | ->where('revoked', false) |
||
| 149 | ->first(); |
||
| 150 | |||
| 151 | if (! $client) { |
||
| 152 | throw InvalidClientCredentialsException::withDefaultMessage(); |
||
| 153 | } |
||
| 154 | |||
| 155 | return [ |
||
| 156 | 'client_id' => $client->id, |
||
| 157 | 'client_secret' => $client->secret, |
||
| 158 | 'scope' => '', |
||
| 159 | ]; |
||
| 160 | } |
||
| 161 | } |
||
| 162 |