I am using Laravel Passport to secure my REST API. Currently I create Personal Access Tokens using $user->createToken('APP_NAME')->accessToken
, but these have no expiration date. So I wanted to create a Password Access Token. I noticed, that these are generated by the AccessTokenController.issueToken()
method.
But I could not find anything on how I can call it.
My current solution
$input = $request->all(); $user = User::where('email', $input['email'])->first(); if ($user) { if ($input['password'] == $user->password) { $token = $user->createToken($this->app_name)->accessToken; return [ 'token' => $token, 'user' => $user ]; } else return new ResponseGeneratorError('Password mismatch', 400); } else return new ResponseGeneratorError('User does not exist', 400);
Advertisement
Answer
I found a solution here:
<?php namespace AppTraits; use AppUser; use DateTime; use GuzzleHttpPsr7Response; use IlluminateEventsDispatcher; use LaravelPassportBridgeAccessToken; use LaravelPassportBridgeAccessTokenRepository; use LaravelPassportBridgeClient; use LaravelPassportBridgeRefreshTokenRepository; use LaravelPassportPassport; use LaravelPassportTokenRepository; use LeagueOAuth2ServerCryptKey; use LeagueOAuth2ServerEntitiesAccessTokenEntityInterface; use LeagueOAuth2ServerExceptionOAuthServerException; use LeagueOAuth2ServerExceptionUniqueTokenIdentifierConstraintViolationException; use LeagueOAuth2ServerResponseTypesBearerTokenResponse; # https://github.com/laravel/passport/issues/71 /** * Trait PassportToken * * @package AppTraits */ trait PassportToken { /** * Generate a new unique identifier. * * @param int $length * * @throws OAuthServerException * * @return string */ private function generateUniqueIdentifier($length = 40) { try { return bin2hex(random_bytes($length)); // @codeCoverageIgnoreStart } catch (TypeError $e) { throw OAuthServerException::serverError('An unexpected error has occurred'); } catch (Error $e) { throw OAuthServerException::serverError('An unexpected error has occurred'); } catch (Exception $e) { // If you get this message, the CSPRNG failed hard. throw OAuthServerException::serverError('Could not generate a random string'); } // @codeCoverageIgnoreEnd } private function issueRefreshToken(AccessTokenEntityInterface $accessToken) { $maxGenerationAttempts = 10; $refreshTokenRepository = app(RefreshTokenRepository::class); $refreshToken = $refreshTokenRepository->getNewRefreshToken(); $refreshToken->setExpiryDateTime((new DateTime())->add(Passport::refreshTokensExpireIn())); $refreshToken->setAccessToken($accessToken); while ($maxGenerationAttempts-- > 0) { $refreshToken->setIdentifier($this->generateUniqueIdentifier()); try { $refreshTokenRepository->persistNewRefreshToken($refreshToken); return $refreshToken; } catch (UniqueTokenIdentifierConstraintViolationException $e) { if ($maxGenerationAttempts === 0) { throw $e; } } } } protected function createPassportTokenByUser(User $user, $clientId) { $accessToken = new AccessToken($user->id); $accessToken->setIdentifier($this->generateUniqueIdentifier()); $accessToken->setClient(new Client($clientId, null, null)); $accessToken->setExpiryDateTime((new DateTime())->add(Passport::tokensExpireIn())); $accessTokenRepository = new AccessTokenRepository(new TokenRepository(), new Dispatcher()); $accessTokenRepository->persistNewAccessToken($accessToken); $refreshToken = $this->issueRefreshToken($accessToken); return [ 'access_token' => $accessToken, 'refresh_token' => $refreshToken, ]; } protected function sendBearerTokenResponse($accessToken, $refreshToken) { $response = new BearerTokenResponse(); $response->setAccessToken($accessToken); $response->setRefreshToken($refreshToken); $privateKey = new CryptKey('file://' . Passport::keyPath('oauth-private.key'), null, false); $response->setPrivateKey($privateKey); $response->setEncryptionKey(app('encrypter')->getKey()); return $response->generateHttpResponse(new Response); } /** * @param AppUser $user * @param $clientId * @param bool $output default = true * @return array | LeagueOAuth2ServerResponseTypesBearerTokenResponse */ protected function getBearerTokenByUser(User $user, $clientId, $output = true) { $passportToken = $this->createPassportTokenByUser($user, $clientId); $bearerToken = $this->sendBearerTokenResponse($passportToken['access_token'], $passportToken['refresh_token']); if (!$output) { $bearerToken = json_decode($bearerToken->getBody()->__toString(), true); } return $bearerToken; } }
I changed new CryptKey('file://' . Passport::keyPath('oauth-private.key'))
to new CryptKey('file://' . Passport::keyPath('oauth-private.key'), null, false)
to avoid a permissions not correct Error (fix from here)