diff --git a/composer.json b/composer.json
index d957407..63dfb2b 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
"mf2/mf2": "^0.4.3",
"indieweb/mention-client": "~1.1",
"indieweb/representative-h-card": "0.1.*",
- "indieauth/client": "0.2.*",
+ "indieauth/client": "^1.0",
"firebase/php-jwt": "~3.0",
"league/route": "~1.2",
"league/plates": "~3.1",
diff --git a/composer.lock b/composer.lock
index b4310a3..355be3c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,51 +1,11 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d36cff93d0bbe63f248f5c5ad541f2c9",
+ "content-hash": "2e3a9f1ddef93aa21e064fcee6c98176",
"packages": [
- {
- "name": "barnabywalters/mf-cleaner",
- "version": "v0.1.4",
- "source": {
- "type": "git",
- "url": "https://github.com/barnabywalters/php-mf-cleaner.git",
- "reference": "ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/barnabywalters/php-mf-cleaner/zipball/ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4",
- "reference": "ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4",
- "shasum": ""
- },
- "require-dev": {
- "php": ">=5.3",
- "phpunit/phpunit": "*"
- },
- "suggest": {
- "mf2/mf2": "To parse microformats2 structures from (X)HTML"
- },
- "type": "library",
- "autoload": {
- "files": [
- "src/BarnabyWalters/Mf2/Functions.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Barnaby Walters",
- "email": "barnaby@waterpigs.co.uk"
- }
- ],
- "description": "Cleans up microformats2 array structures",
- "time": "2014-10-06T23:11:15+00:00"
- },
{
"name": "camspiers/json-pretty",
"version": "1.0.2",
@@ -400,24 +360,27 @@
},
{
"name": "indieauth/client",
- "version": "0.2.2",
+ "version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/indieweb/indieauth-client-php.git",
- "reference": "225ece31ddafaee3348eabdc915422c457498a84"
+ "reference": "d551eeb268100b87ebc7a05ae796a858550e700a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/225ece31ddafaee3348eabdc915422c457498a84",
- "reference": "225ece31ddafaee3348eabdc915422c457498a84",
+ "url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/d551eeb268100b87ebc7a05ae796a858550e700a",
+ "reference": "d551eeb268100b87ebc7a05ae796a858550e700a",
"shasum": ""
},
"require": {
- "barnabywalters/mf-cleaner": "0.*",
- "indieweb/link-rel-parser": "0.1.*",
- "mf2/mf2": "~0.3",
+ "indieweb/representative-h-card": "^0.1.2",
+ "mf2/mf2": ">=0.3.2",
+ "p3k/http": ">=0.1.6",
"php": ">5.3.0"
},
+ "require-dev": {
+ "phpunit/phpunit": "4.8.*"
+ },
"type": "library",
"autoload": {
"psr-0": {
@@ -426,16 +389,16 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "Apache 2.0"
+ "Apache-2.0"
],
"authors": [
{
"name": "Aaron Parecki",
- "homepage": "http://aaronparecki.com"
+ "homepage": "https://aaronparecki.com"
}
],
"description": "IndieAuth Client Library",
- "time": "2017-07-01T15:43:45+00:00"
+ "time": "2020-11-26T19:41:45+00:00"
},
{
"name": "indieweb/link-rel-parser",
@@ -1385,12 +1348,12 @@
"version": "v1.0.3",
"source": {
"type": "git",
- "url": "https://github.com/nrk/predis.git",
+ "url": "https://github.com/predis/predis.git",
"reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nrk/predis/zipball/84060b9034d756b4d79641667d7f9efe1aeb8e04",
+ "url": "https://api.github.com/repos/predis/predis/zipball/84060b9034d756b4d79641667d7f9efe1aeb8e04",
"reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04",
"shasum": ""
},
@@ -1740,10 +1703,51 @@
"xml",
"zf"
],
+ "abandoned": "laminas/laminas-xml",
"time": "2018-04-30T15:11:04+00:00"
}
],
"packages-dev": [
+ {
+ "name": "barnabywalters/mf-cleaner",
+ "version": "v0.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barnabywalters/php-mf-cleaner.git",
+ "reference": "ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barnabywalters/php-mf-cleaner/zipball/ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4",
+ "reference": "ef6a16628db6e8aee2b4f8bb8093d18c24b74cd4",
+ "shasum": ""
+ },
+ "require-dev": {
+ "php": ">=5.3",
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "mf2/mf2": "To parse microformats2 structures from (X)HTML"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/BarnabyWalters/Mf2/Functions.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Barnaby Walters",
+ "email": "barnaby@waterpigs.co.uk"
+ }
+ ],
+ "description": "Cleans up microformats2 array structures",
+ "time": "2014-10-06T23:11:15+00:00"
+ },
{
"name": "doctrine/instantiator",
"version": "1.0.5",
@@ -2190,6 +2194,7 @@
"keywords": [
"tokenizer"
],
+ "abandoned": true,
"time": "2015-09-15T10:49:45+00:00"
},
{
@@ -2321,6 +2326,7 @@
"mock",
"xunit"
],
+ "abandoned": true,
"time": "2016-03-24T05:58:25+00:00"
},
{
@@ -2893,5 +2899,6 @@
"platform": {
"php": ">=5.5"
},
- "platform-dev": []
+ "platform-dev": [],
+ "plugin-api-version": "1.1.0"
}
diff --git a/controllers/Auth.php b/controllers/Auth.php
index f520756..7d21257 100644
--- a/controllers/Auth.php
+++ b/controllers/Auth.php
@@ -41,14 +41,29 @@ class Auth {
return $response;
}
+ // Check if the user's URL defines an authorization endpoint
+ $authorizationEndpoint = IndieAuth\Client::discoverAuthorizationEndpoint($me);
+ if(!$authorizationEndpoint) {
+ $authorizationEndpoint = Config::$defaultAuthorizationEndpoint;
+ }
+
+ $codeVerifier = IndieAuth\Client::generatePKCECodeVerifier();
$state = JWT::encode([
+ 'az' => $authorizationEndpoint,
'me' => $me,
+ 'code_verifier' => $codeVerifier,
'return_to' => $request->get('return_to'),
'time' => time(),
'exp' => time()+300 // verified by the JWT library
], Config::$secretKey);
- $authorizationURL = IndieAuth\Client::buildAuthorizationURL(Config::$defaultAuthorizationEndpoint, $me, self::_buildRedirectURI(), Config::$clientID, $state);
+ $authorizationURL = IndieAuth\Client::buildAuthorizationURL($authorizationEndpoint, [
+ 'me' => $me,
+ 'redirect_uri' => self::_buildRedirectURI(),
+ 'client_id' => Config::$clientID,
+ 'state' => $state,
+ 'code_verifier' => $codeVerifier,
+ ]);
$response->setStatusCode(302);
$response->headers->set('Location', $authorizationURL);
@@ -87,26 +102,46 @@ class Auth {
return $response;
}
- $authorizationEndpoint = Config::$defaultAuthorizationEndpoint;
+ $authorizationEndpoint = $state->az;
// Verify the code with the auth server
- $token = IndieAuth\Client::verifyIndieAuthCode($authorizationEndpoint, $request->get('code'), $state->me, self::_buildRedirectURI(), Config::$clientID, true);
-
- if(!array_key_exists('auth', $token) || !array_key_exists('me', $token['auth'])) {
- // The auth server didn't return a "me" URL
+ $data = IndieAuth\Client::exchangeAuthorizationCode($state->az, [
+ 'code' => $request->get('code'),
+ 'redirect_uri' => self::_buildRedirectURI(),
+ 'client_id' => Config::$clientID,
+ 'code_verifier' => $state->code_verifier,
+ ]);
+
+ if(!isset($data['response']['me'])) {
+ // The authorization server didn't return a "me" URL
$response->setContent(view('login', [
'title' => 'Sign In to Telegraph',
'error' => 'Invalid Auth Server Response',
- 'error_description' => 'The authorization server ('.$authorizationEndpoint.') did not return a valid response:
HTTP '.$token['response_code']."\n\n".htmlspecialchars($token['response']).'' + 'error_description' => 'The authorization server ('.$authorizationEndpoint.') did not return a valid response:
HTTP '.$data['response_code']."\n\n".htmlspecialchars(json_encode($data)).'' ])); return $response; } + // Verify the authorization endpoint matches + if($data['response']['me'] != $state->me) { + $newAuthorizationEndpoint = IndieAuth\Client::discoverAuthorizationEndpoint($data['response']['me']); + if($newAuthorizationEndpoint != $authorizationEndpoint) { + $response->setContent(view('login', [ + 'title' => 'Sign In to Telegraph', + 'error' => 'Invalid Authorization Endpoint', + 'error_description' => 'The authorization endpoint for the returned profile URL ('.$data['response']['me'].') did not match the authorization endpoint used to begin the login.' + ])); + return $response; + } + } + + $me = $data['response']['me']; + // Create or load the user - $user = ORM::for_table('users')->where('url', $token['auth']['me'])->find_one(); + $user = ORM::for_table('users')->where('url', $me)->find_one(); if(!$user) { $user = ORM::for_table('users')->create(); - $user->url = $token['auth']['me']; + $user->url = $me; $user->created_at = date('Y-m-d H:i:s'); $user->last_login = date('Y-m-d H:i:s'); $user->save(); @@ -114,7 +149,7 @@ class Auth { // Create a site for them with the default role $site = ORM::for_table('sites')->create(); $site->name = 'My Website'; - $site->url = $token['auth']['me']; + $site->url = $me; $site->created_by = $user->id; $site->created_at = date('Y-m-d H:i:s'); $site->save();