2017-05-18 15:15:53 +01:00
|
|
|
|
<?php
|
|
|
|
|
|
2018-01-15 14:02:13 +00:00
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
2017-05-18 15:15:53 +01:00
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
use App\Services\TokenService;
|
2022-09-24 18:28:05 +01:00
|
|
|
|
use GuzzleHttp\Client as GuzzleClient;
|
|
|
|
|
use GuzzleHttp\Exception\BadResponseException;
|
2018-01-31 22:21:57 +00:00
|
|
|
|
use Illuminate\Http\JsonResponse;
|
2022-09-24 18:28:05 +01:00
|
|
|
|
use Illuminate\Http\Request;
|
2019-10-27 16:29:15 +00:00
|
|
|
|
use IndieAuth\Client;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
|
|
|
|
class TokenEndpointController extends Controller
|
|
|
|
|
{
|
|
|
|
|
/**
|
2022-09-24 18:28:05 +01:00
|
|
|
|
* @var Client The IndieAuth Client.
|
2017-05-18 15:15:53 +01:00
|
|
|
|
*/
|
2020-08-09 15:54:10 +01:00
|
|
|
|
protected Client $client;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
|
|
|
|
/**
|
2022-09-24 18:28:05 +01:00
|
|
|
|
* @var GuzzleClient The GuzzleHttp client.
|
|
|
|
|
*/
|
|
|
|
|
protected GuzzleClient $guzzle;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var TokenService The Token handling service.
|
2017-05-18 15:15:53 +01:00
|
|
|
|
*/
|
2020-08-09 15:54:10 +01:00
|
|
|
|
protected TokenService $tokenService;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inject the dependencies.
|
|
|
|
|
*
|
2022-07-09 10:08:26 +01:00
|
|
|
|
* @param Client $client
|
2022-09-24 18:28:05 +01:00
|
|
|
|
* @param GuzzleClient $guzzle
|
2022-07-09 10:08:26 +01:00
|
|
|
|
* @param TokenService $tokenService
|
2017-05-18 15:15:53 +01:00
|
|
|
|
*/
|
|
|
|
|
public function __construct(
|
2017-09-04 19:34:39 +01:00
|
|
|
|
Client $client,
|
2022-09-24 18:28:05 +01:00
|
|
|
|
GuzzleClient $guzzle,
|
2017-09-04 19:34:39 +01:00
|
|
|
|
TokenService $tokenService
|
2017-05-18 15:15:53 +01:00
|
|
|
|
) {
|
2017-09-04 19:34:39 +01:00
|
|
|
|
$this->client = $client;
|
2022-09-24 18:28:05 +01:00
|
|
|
|
$this->guzzle = $guzzle;
|
2017-09-04 19:34:39 +01:00
|
|
|
|
$this->tokenService = $tokenService;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If the user has auth’d via the IndieAuth protocol, issue a valid token.
|
|
|
|
|
*
|
2022-09-24 18:28:05 +01:00
|
|
|
|
* @param Request $request
|
2020-08-09 15:54:10 +01:00
|
|
|
|
* @return JsonResponse
|
2017-05-18 15:15:53 +01:00
|
|
|
|
*/
|
2022-09-24 18:28:05 +01:00
|
|
|
|
public function create(Request $request): JsonResponse
|
2017-05-18 15:15:53 +01:00
|
|
|
|
{
|
2022-09-24 18:28:05 +01:00
|
|
|
|
if (empty($request->input('me'))) {
|
|
|
|
|
return response()->json([
|
|
|
|
|
'error' => 'Missing {me} param from input',
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
2022-09-24 18:28:05 +01:00
|
|
|
|
$authorizationEndpoint = $this->client::discoverAuthorizationEndpoint(normalize_url($request->input('me')));
|
|
|
|
|
|
|
|
|
|
if (empty($authorizationEndpoint)) {
|
2018-01-31 22:21:57 +00:00
|
|
|
|
return response()->json([
|
2022-09-24 18:28:05 +01:00
|
|
|
|
'error' => sprintf('Could not discover the authorization endpoint for %s', $request->input('me'))
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$auth = $this->verifyIndieAuthCode(
|
|
|
|
|
$authorizationEndpoint,
|
|
|
|
|
$request->input('code'),
|
|
|
|
|
$request->input('me'),
|
|
|
|
|
$request->input('redirect_uri'),
|
|
|
|
|
$request->input('client_id'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($auth === null || !array_key_exists('me', $auth)) {
|
|
|
|
|
return response()->json([
|
|
|
|
|
'error' => 'There was an error verifying the IndieAuth code',
|
2018-01-31 22:21:57 +00:00
|
|
|
|
], 401);
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-24 18:28:05 +01:00
|
|
|
|
$scope = $auth['scope'] ?? '';
|
|
|
|
|
$tokenData = [
|
|
|
|
|
'me' => $request->input('me'),
|
|
|
|
|
'client_id' => $request->input('client_id'),
|
|
|
|
|
'scope' => $scope,
|
|
|
|
|
];
|
|
|
|
|
$token = $this->tokenService->getNewToken($tokenData);
|
|
|
|
|
$content = [
|
|
|
|
|
'me' => $request->input('me'),
|
|
|
|
|
'scope' => $scope,
|
|
|
|
|
'access_token' => $token,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return response()->json($content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function verifyIndieAuthCode(
|
|
|
|
|
string $authorizationEndpoint,
|
|
|
|
|
string $code,
|
|
|
|
|
string $me,
|
|
|
|
|
string $redirectUri,
|
|
|
|
|
string $clientId
|
|
|
|
|
): ?array {
|
|
|
|
|
try {
|
|
|
|
|
$response = $this->guzzle->request('POST', $authorizationEndpoint, [
|
|
|
|
|
'headers' => [
|
|
|
|
|
'Accept' => 'application/json',
|
|
|
|
|
],
|
|
|
|
|
'form_params' => [
|
|
|
|
|
'code' => $code,
|
|
|
|
|
'me' => $me,
|
|
|
|
|
'redirect_uri' => $redirectUri,
|
|
|
|
|
'client_id' => $clientId,
|
|
|
|
|
],
|
|
|
|
|
]);
|
|
|
|
|
} catch (BadResponseException) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$authData = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);
|
|
|
|
|
} catch (\JsonException) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $authData;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
|
|
|
|
}
|