friendship ended with social-app. php is my new best friend

work on oauth

Changed files
+67 -20
lib
public
templates
vendor
chillerlan
php-oauth
+53 -11
index.php
···
require_once('vendor/autoload.php');
require_once('config.php');
require_once('lib/bskyToucher.php');
+
require_once('lib/bskyProvider.php');
use flight\Engine;
use League\CommonMark\CommonMarkConverter;
use React\Promise\Deferred;
use React\EventLoop\Loop;
use React\Promise\Promise;
+
use GuzzleHttp\Client;
use Tracy\Debugger;
use Tracy\OutputDebugger;
use Matrix\Async;
+
use GuzzleHttp\Psr7\HttpFactory;
+
use chillerlan\OAuth\OAuthOptions;
+
use Smallnest\Bsky\BskyProvider;
$bskyToucher = new BskyToucher();
···
'favFeeds' => $favoriteFeeds,
'pages' => PAGES,
'links' => LINKS,
-
'ogdomain' => SITE_DOMAIN
+
'ogdomain' => 'https://'.SITE_DOMAIN
]);
Flight::route('/', function () {
···
'ogtitle' => SITE_TITLE,
'ogdesc' => SITE_DESC,
'ogimage' => '',
-
'ogurl' => SITE_DOMAIN.'/'
+
'ogurl' => 'https://'.SITE_DOMAIN.'/'
]));
});
···
'ogtitle' => SITE_TITLE." | ".$userInfo->displayName." (@".$handle.")",
'ogdesc' => '', //$post->content,
'ogimage' => '', //getPostOgImage($post),
-
'ogurl' => SITE_DOMAIN.'/u/'.$handle.'/'.$rkey
+
'ogurl' => 'https://'.SITE_DOMAIN.'/u/'.$handle.'/'.$rkey
]));
});
···
'ogtitle' => SITE_TITLE." | ".$user->displayName." (@".$user->handle.")",
'ogdesc' => $user->description,
'ogimage' => $user->avatar,
-
'ogurl' => SITE_DOMAIN.'/u/'.$user->handle.'/'
+
'ogurl' => 'https://'.SITE_DOMAIN.'/u/'.$user->handle.'/'
]));
});
···
'ogtitle' => SITE_TITLE." | ".$feedInfo->title,
'ogdesc' => $feedInfo->description,
'ogimage' => $feedInfo->avatar,
-
'ogurl' => SITE_DOMAIN.'/f/'.$did.'/'.$name
+
'ogurl' => 'https://'.SITE_DOMAIN.'/f/'.$did.'/'.$name
]));
});
···
'ogtitle' => SITE_TITLE." | search".(array_key_exists('s', $_GET) ? ': '.$_GET['s'] : ''),
'ogdesc' => SITE_DESC,
'ogimage' => '',
-
'ogurl' => SITE_DOMAIN.'/u/'.$handle.'/'.$rkey
+
'ogurl' => 'https://'.SITE_DOMAIN.'/u/'.$handle.'/'.$rkey
]));
});
-
Flight::route('GET /login', function(): void {
+
Flight::route('/login', function(): void {
+
$options = new OAuthOptions([
+
'key' => 'http://'.SITE_DOMAIN.CLIENT_ID,
+
'secret' => CLIENT_SECRET,
+
'callbackURL' => 'http://'.SITE_DOMAIN.'/login',
+
'sessionStart' => true,
+
]);
+
$http = new React\Http\Browser();
+
$client = new GuzzleHttp\Client([
+
'headers' => [
+
'User-Agent' => USER_AGENT_STR
+
]
+
]);
+
$httpFactory = new HttpFactory();
+
$provider = new BskyProvider($options, $client, $httpFactory, $httpFactory, $httpFactory);
+
$name = $provider->getName();
+
if (isset($_GET['login']) && $_GET['login'] === $name) {
+
$username = $_GET['username'];
+
$bskyToucher = new BskyToucher();
+
$userInfo = $bskyToucher->getUserInfo($username);
+
if (!$userInfo) die(1);
+
$pds = $userInfo->pds;
+
$provider->setPds($pds);
+
$authUrl = $provider->getAuthorizationUrl();
+
header('Location: '.$authUrl);
+
die(1);
+
} else if (isset($_GET['code'], $_GET['state'])) {
+
$token = $provider->getAccessToken($_GET['code'], $_GET['state']);
+
+
// save the token in a permanent storage
+
// [...]
+
+
// access granted, redirect
+
header('Location: ?granted='.$name);
+
die(1);
+
} else if (isset($_GET['granted']) && $_GET['granted'] === $name) {
+
die(1);
+
} else if (isset($_GET['error'])) {
+
die(1);
+
}
$latte = new Latte\Engine;
$latte->render('./templates/login.latte', array_merge(Flight::get('standardParams'), [
'mainClass' => 'form',
'ogtitle' => SITE_TITLE." | login",
'ogdesc' => SITE_DESC,
'ogimage' => '',
-
'ogurl' => SITE_DOMAIN.'/login'
+
'ogurl' => 'https://'.SITE_DOMAIN.'/login'
]));
});
-
Flight::route('POST /login', function(): void {
-
// whatever stupid token exchange dance needs to happen to direct them to oauth
-
});
+
// https://shimaenaga.veryroundbird.house/oauth/authorize?client_id=https%3A%2F%2Ftangled.org%2Foauth%2Fclient-metadata.json&request_uri=urn%3Aietf%3Aparams%3Aoauth%3Arequest_uri%3Areq-2399ff42af66498132ebf8de809254b7
Flight::route('/createaccount', function(): void {
$latte = new Latte\Engine;
+7 -5
lib/bskyProvider.php
···
public const SCOPE_TRANSITION_GENERIC = 'transition:generic';
public const AUTH_METHOD = self::AUTH_METHOD_HEADER;
-
protected string $authorizationURL = 'https://bsky.app/oauth2/authorize';
-
protected string $accessTokenURL = 'https://bsky.app/oauth2/token';
-
protected string $apiURL = 'https://bsky.app/api';
+
protected string $authorizationURL = 'https://bsky.app/oauth/authorize';
+
protected string $accessTokenURL = 'https://bsky.app/oauth/token';
+
protected string $apiURL = 'https://bsky.app/xrpc';
+
protected string $parAuthorizationURL = 'https://bsky.app/oauth/par';
public const DEFAULT_SCOPES = [
self::SCOPE_ATPROTO,
···
// set the provider URLs
$this->authorizationURL = (string)$pds->withPath('/oauth/authorize');
$this->accessTokenURL = (string)$pds->withPath('/oauth/token');
-
$this->apiURL = (string)$pds->withPath('/api');
-
+
$this->apiURL = (string)$pds->withPath('/xrpc');
+
$this->parAuthorizationURL = (string)$pds->withPath('/oauth/par');
+
return $this;
}
}
-1
lib/bskyToucher.php
···
require_once('config.php');
require_once('vendor/autoload.php');
-
require_once('bskyProvider.php');
//if (DB_TYPE === 'sqlite') require_once('db.php');
if (DB_TYPE === 'mysql') require_once('maria-db.php');
+1 -1
public/client-metadata.json
···
"client_uri": "https://localhost:5173",
"dpop_bound_access_tokens": true,
"grant_types": ["authorization_code", "refresh_token"],
-
"redirect_uris": ["http://localhost:5173/oauth/callback.php"],
+
"redirect_uris": ["http://localhost:5173/login"],
"response_types": ["code"],
"scope": "atproto transition:generic",
"dpop_bound_access_tokens": true,
+1
templates/login.latte
···
<input type="text" name="username" id="username" />
</div>
<div class="form-input btn-row">
+
<input type="hidden" name="login" value="BskyProvider" />
<button type="submit" class="btn btn-primary">Log In</button>
</div>
</form>
+2 -2
vendor/chillerlan/php-oauth/src/Core/OAuth2Provider.php
···
*/
public function getAuthorizationURL(array|null $params = null, array|null $scopes = null):UriInterface{
$queryParams = $this->getAuthorizationURLRequestParams(($params ?? []), ($scopes ?? $this::DEFAULT_SCOPES));
-
+
if($this instanceof PAR){
return $this->getParRequestUri($queryParams);
}
···
if($this::USES_BASIC_AUTH_IN_ACCESS_TOKEN_REQUEST){
$request = $this->addBasicAuthHeader($request);
}
-
+
return $this->http->sendRequest($request);
}
+3
vendor/chillerlan/php-oauth/src/Core/PARTrait.php
···
public function getParRequestUri(array $body):UriInterface{
// send the request with the same method and parameters as the token requests
// @link https://datatracker.ietf.org/doc/html/rfc9126#name-request
+
print_r($this->parAuthorizationURL);
$response = $this->sendAccessTokenRequest($this->parAuthorizationURL, $body);
$status = $response->getStatusCode();
$json = MessageUtil::decodeJSON($response, true);
+
print_r($body);
+
print_r($json);
// something went horribly wrong
if($status !== 200){