From 7d0c1bb737f3683cd770ebd757d938f39a9b55ef Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sun, 18 Feb 2018 20:24:41 -0500 Subject: [PATCH 1/7] Created test vehicle module oauth2test --- Zotlabs/Module/Oauth2test.php | 43 +++++++++++++++++++++++++++++++++++ view/css/mod_oauth2test.css | 4 ++++ view/tpl/oauth2test.tpl | 13 +++++++++++ 3 files changed, 60 insertions(+) create mode 100644 Zotlabs/Module/Oauth2test.php create mode 100644 view/css/mod_oauth2test.css create mode 100644 view/tpl/oauth2test.tpl diff --git a/Zotlabs/Module/Oauth2test.php b/Zotlabs/Module/Oauth2test.php new file mode 100644 index 000000000..14aa6137a --- /dev/null +++ b/Zotlabs/Module/Oauth2test.php @@ -0,0 +1,43 @@ + z_root(), + '$endpoints' => array( + array( + 'oauth2test', + array( + array( + 'action', 'create_db' + ) + ), + 'oauth2test_create_db', + 'Create the OAuth2 database tables' + ) + ) + )); + + return $o; + } + + function post() { + + logger(json_encode($_POST), LOGGER_DEBUG); + + switch ($_POST['action']) { + case 'create_db': + logger('Creating database tables...', LOGGER_DEBUG); + break; + + default: + break; + } + + } + +} diff --git a/view/css/mod_oauth2test.css b/view/css/mod_oauth2test.css new file mode 100644 index 000000000..0ef2896b5 --- /dev/null +++ b/view/css/mod_oauth2test.css @@ -0,0 +1,4 @@ +.oath2test-form-box { + border: #ccc thin solid; + padding: 1em; +} \ No newline at end of file diff --git a/view/tpl/oauth2test.tpl b/view/tpl/oauth2test.tpl new file mode 100644 index 000000000..d4887063c --- /dev/null +++ b/view/tpl/oauth2test.tpl @@ -0,0 +1,13 @@ +

OAuth 2.0 Test Vehicle

+ +{{foreach $endpoints as $ept}} +
+
+

{{$ept.3}}

+

{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}& {{/foreach}} +

+ + +
+
+{{/foreach}} \ No newline at end of file From 89a825cd038df7da609d64ef0254ba58caaede31 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Tue, 20 Feb 2018 21:11:38 -0500 Subject: [PATCH 2/7] OAuth2TestVehicle module can create and delete oauth2 database tables. --- Zotlabs/Module/Oauth2test.php | 43 ------- Zotlabs/Module/Oauth2testvehicle.php | 107 ++++++++++++++++++ Zotlabs/Storage/ZotOauth2Pdo.php | 10 ++ ...uth2test.css => mod_oauth2testvehicle.css} | 0 .../{oauth2test.tpl => oauth2testvehicle.tpl} | 0 5 files changed, 117 insertions(+), 43 deletions(-) delete mode 100644 Zotlabs/Module/Oauth2test.php create mode 100644 Zotlabs/Module/Oauth2testvehicle.php create mode 100644 Zotlabs/Storage/ZotOauth2Pdo.php rename view/css/{mod_oauth2test.css => mod_oauth2testvehicle.css} (100%) rename view/tpl/{oauth2test.tpl => oauth2testvehicle.tpl} (100%) diff --git a/Zotlabs/Module/Oauth2test.php b/Zotlabs/Module/Oauth2test.php deleted file mode 100644 index 14aa6137a..000000000 --- a/Zotlabs/Module/Oauth2test.php +++ /dev/null @@ -1,43 +0,0 @@ - z_root(), - '$endpoints' => array( - array( - 'oauth2test', - array( - array( - 'action', 'create_db' - ) - ), - 'oauth2test_create_db', - 'Create the OAuth2 database tables' - ) - ) - )); - - return $o; - } - - function post() { - - logger(json_encode($_POST), LOGGER_DEBUG); - - switch ($_POST['action']) { - case 'create_db': - logger('Creating database tables...', LOGGER_DEBUG); - break; - - default: - break; - } - - } - -} diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php new file mode 100644 index 000000000..2a2590928 --- /dev/null +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -0,0 +1,107 @@ + z_root(), + /* + endpoints => array( + array( + 'path_to_endpoint', + array( + array('field_name_1', 'value'), + array('field_name_2', 'value'), + ... + ), + 'submit_button_name', + 'Description of API action' + ) + ) + */ + '$endpoints' => array( + array( + 'oauth2testvehicle', + array( + array( + 'action', 'create_db' + ) + ), + 'oauth2test_create_db', + 'Create the OAuth2 database tables' + ), + array( + 'oauth2testvehicle', + array( + array( + 'action', 'delete_db' + ) + ), + 'oauth2test_delete_db', + 'Delete the OAuth2 database tables' + ) + ) + )); + + return $o; + } + + function post() { + + logger(json_encode($_POST), LOGGER_DEBUG); + + switch ($_POST['action']) { + + case 'delete_db': + $status = true; + // Use the \OAuth2\Storage\Pdo class to create the OAuth2 tables + // by passing it the database connection + $pdo = \DBA::$dba->db; + $storage = new \Zotlabs\Storage\ZotOauth2Pdo($pdo); + logger('Deleting existing database tables...', LOGGER_DEBUG); + foreach ($storage->getConfig() as $key => $table) { + logger('Deleting table ' . dbesc($table), LOGGER_DEBUG); + $r = q("DROP TABLE IF EXISTS %s;", dbesc($table)); + if (!$r) { + logger('Errors encountered deleting database table ' . $table . '.', LOGGER_DEBUG); + $status = false; + } + } + if (!$status) { + notice('Errors encountered deleting database tables.' . EOL); + } else { + info('Database tables deleted successfully.' . EOL); + } + + break; + + case 'create_db': + $status = true; + logger('Creating database tables...', LOGGER_DEBUG); + @include('.htconfig.php'); + $pdo = \DBA::$dba->db; + $storage = new \Zotlabs\Storage\ZotOauth2Pdo($pdo); + foreach (explode(';', $storage->getBuildSql($db_data)) as $statement) { + try { + $result = $pdo->exec($statement); + } catch (\PDOException $e) { + $status = false; + logger('Error executing database statement: ' . $statement, LOGGER_DEBUG); + } + } + + if (!$status) { + notice('Errors encountered creating database tables.' . EOL); + } else { + info('Database tables created successfully.' . EOL); + } + + default: + break; + } + } + +} diff --git a/Zotlabs/Storage/ZotOauth2Pdo.php b/Zotlabs/Storage/ZotOauth2Pdo.php new file mode 100644 index 000000000..b2c3ce228 --- /dev/null +++ b/Zotlabs/Storage/ZotOauth2Pdo.php @@ -0,0 +1,10 @@ +config; + } +} diff --git a/view/css/mod_oauth2test.css b/view/css/mod_oauth2testvehicle.css similarity index 100% rename from view/css/mod_oauth2test.css rename to view/css/mod_oauth2testvehicle.css diff --git a/view/tpl/oauth2test.tpl b/view/tpl/oauth2testvehicle.tpl similarity index 100% rename from view/tpl/oauth2test.tpl rename to view/tpl/oauth2testvehicle.tpl From 43fca182e3915734587abf389d819546ebade3a4 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Thu, 22 Feb 2018 15:10:05 -0500 Subject: [PATCH 3/7] The authorization step with client registration and authorization code retrieval working. Might not conform perfectly to OAuth2 spec, but it is a start. --- Zotlabs/Module/Authorize.php | 79 +++++++++++++++++++++------- Zotlabs/Module/Oauth2testvehicle.php | 56 ++++++++++++++------ view/tpl/oauth2testvehicle.tpl | 4 +- view/tpl/oauth_authorize.tpl | 16 ++++-- 4 files changed, 113 insertions(+), 42 deletions(-) diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php index 254700b4e..f98453fb5 100644 --- a/Zotlabs/Module/Authorize.php +++ b/Zotlabs/Module/Authorize.php @@ -4,15 +4,14 @@ namespace Zotlabs\Module; use Zotlabs\Identity\OAuth2Storage; - class Authorize extends \Zotlabs\Web\Controller { function init() { // workaround for HTTP-auth in CGI mode if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { - $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; - if(strlen($userpass)) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)); + if (strlen($userpass)) { list($name, $password) = explode(':', $userpass); $_SERVER['PHP_AUTH_USER'] = $name; $_SERVER['PHP_AUTH_PW'] = $password; @@ -20,43 +19,83 @@ class Authorize extends \Zotlabs\Web\Controller { } if (x($_SERVER, 'HTTP_AUTHORIZATION')) { - $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; - if(strlen($userpass)) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)); + if (strlen($userpass)) { list($name, $password) = explode(':', $userpass); $_SERVER['PHP_AUTH_USER'] = $name; $_SERVER['PHP_AUTH_PW'] = $password; } } + } - $s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db)); + function get() { + if (!local_channel()) { + return login(); + } else { + // display an authorization form + $app = array('name' => 'Test App', 'icon' => '/images/icons/plugin.png'); + $o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array( + '$title' => '', + '$authorize' => 'Do you authorize the app "' . $app['name'] . '" to access your channel data?', + '$app' => $app, + '$yes' => t('Allow'), + '$no' => t('Deny'), + '$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''), + '$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''), + '$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : '') + )); + return $o; + } + } + + function post() { + if (!local_channel()) { + return $this->get(); + } + + $storage = new OAuth2Storage(\DBA::$dba->db); + $s = new \Zotlabs\Identity\OAuth2Server($storage); + + + // If no client_id was provided, generate a new one. + if (x($_POST, 'client_id')) { + $client_id = $_POST['client_id']; + logger('client_id was provided: ' . $client_id); + } else { + $client_id = $_POST['client_id'] = random_string(16); + logger('client_id was not provided. Generated new id: ' . $client_id); + } + // If no redirect_uri was provided, generate a fake one. + if (x($_POST, 'redirect_uri')) { + $redirect_uri = $_POST['redirect_uri']; + } else { + $redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com'; + } + + logger('redirect_uri is : ' . $redirect_uri); + // If the client is not registered, add to the database + if (!$storage->getClientDetails($client_id)) { + $client_secret = random_string(16); + $storage->setClientDetails($client_id, $client_secret, $redirect_uri); + } $request = \OAuth2\Request::createFromGlobals(); + logger(json_encode($request, JSON_PRETTY_PRINT), LOGGER_DEBUG); $response = new \OAuth2\Response(); // validate the authorize request - if (! $s->validateAuthorizeRequest($request, $response)) { + if (!$s->validateAuthorizeRequest($request, $response)) { $response->send(); killme(); } - // display an authorization form - if (empty($_POST)) { - - return ' -
-
- - -
'; - } - // print the authorization code if the user has authorized your client - $is_authorized = ($_POST['authorized'] === 'yes'); + $is_authorized = ($_POST['authorize'] === 'allow'); $s->handleAuthorizeRequest($request, $response, $is_authorized, local_channel()); if ($is_authorized) { // this is only here so that you get to see your code in the cURL request. Otherwise, // we'd redirect back to the client - $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40); + $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40); echo("SUCCESS! Authorization Code: $code"); } diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php index 2a2590928..6e9f31c47 100644 --- a/Zotlabs/Module/Oauth2testvehicle.php +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -4,23 +4,34 @@ namespace Zotlabs\Module; class OAuth2TestVehicle extends \Zotlabs\Web\Controller { + function init() { + + // If there is a 'code' and 'state' parameter then this is a client app + // callback issued after the authorization code request + if ($_REQUEST['code'] && $_REQUEST['state']) { + logger('Authorization callback invoked.', LOGGER_DEBUG); + logger(json_encode($_REQUEST, JSON_PRETTY_PRINT), LOGGER_DEBUG); + info('Authorization callback invoked.' . EOL); + return $this->get(); + } + } function get() { $o .= replace_macros(get_markup_template('oauth2testvehicle.tpl'), array( '$baseurl' => z_root(), /* - endpoints => array( + endpoints => array( array( - 'path_to_endpoint', - array( - array('field_name_1', 'value'), - array('field_name_2', 'value'), - ... - ), - 'submit_button_name', - 'Description of API action' + 'path_to_endpoint', + array( + array('field_name_1', 'value'), + array('field_name_2', 'value'), + ... + ), + 'submit_button_name', + 'Description of API action' + ) ) - ) */ '$endpoints' => array( array( @@ -31,7 +42,8 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { ) ), 'oauth2test_create_db', - 'Create the OAuth2 database tables' + 'Create the OAuth2 database tables', + 'POST' ), array( 'oauth2testvehicle', @@ -41,7 +53,20 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { ) ), 'oauth2test_delete_db', - 'Delete the OAuth2 database tables' + 'Delete the OAuth2 database tables', + 'POST' + ), + array( + 'authorize', + array( + array('response_type', 'code'), + array('client_id', urlencode('test_app_client_id')), + array('redirect_uri', urlencode('http://hub.localhost/oauth2testvehicle')), + array('state', 'xyz') + ), + 'oauth_authorize', + 'Authorize a test client app', + 'GET' ) ) )); @@ -53,8 +78,9 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { logger(json_encode($_POST), LOGGER_DEBUG); + switch ($_POST['action']) { - + case 'delete_db': $status = true; // Use the \OAuth2\Storage\Pdo class to create the OAuth2 tables @@ -64,7 +90,7 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { logger('Deleting existing database tables...', LOGGER_DEBUG); foreach ($storage->getConfig() as $key => $table) { logger('Deleting table ' . dbesc($table), LOGGER_DEBUG); - $r = q("DROP TABLE IF EXISTS %s;", dbesc($table)); + $r = q("DROP TABLE %s;", dbesc($table)); if (!$r) { logger('Errors encountered deleting database table ' . $table . '.', LOGGER_DEBUG); $status = false; @@ -77,7 +103,7 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { } break; - + case 'create_db': $status = true; logger('Creating database tables...', LOGGER_DEBUG); diff --git a/view/tpl/oauth2testvehicle.tpl b/view/tpl/oauth2testvehicle.tpl index d4887063c..aebc71bb2 100644 --- a/view/tpl/oauth2testvehicle.tpl +++ b/view/tpl/oauth2testvehicle.tpl @@ -2,9 +2,9 @@ {{foreach $endpoints as $ept}}
-
+

{{$ept.3}}

-

{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}& {{/foreach}} +

{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}&{{/foreach}}

diff --git a/view/tpl/oauth_authorize.tpl b/view/tpl/oauth_authorize.tpl index 2b7afa80e..f5da11cdc 100755 --- a/view/tpl/oauth_authorize.tpl +++ b/view/tpl/oauth_authorize.tpl @@ -3,8 +3,14 @@

{{$app.name}}

-
-

{{$authorize}}

- -
-
+

{{$authorize}}

+
+
+ + + + + +
+
+
\ No newline at end of file From 64ee42fc3d00765bc5c60e451b86230ea38ffdfb Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sat, 24 Feb 2018 06:48:30 -0500 Subject: [PATCH 4/7] Add channel ID to user_id in clients table. Added TODO comments about dynamic client registration protocol. --- Zotlabs/Module/Authorize.php | 27 +++++++++++++++++---------- Zotlabs/Module/Oauth2testvehicle.php | 11 +++++++++-- view/tpl/oauth2testvehicle.tpl | 2 +- view/tpl/oauth_authorize.tpl | 4 ++-- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php index f98453fb5..2c0c9248f 100644 --- a/Zotlabs/Module/Authorize.php +++ b/Zotlabs/Module/Authorize.php @@ -32,17 +32,23 @@ class Authorize extends \Zotlabs\Web\Controller { if (!local_channel()) { return login(); } else { - // display an authorization form - $app = array('name' => 'Test App', 'icon' => '/images/icons/plugin.png'); + // TODO: Fully implement the dynamic client registration protocol: + // OpenID Connect Dynamic Client Registration 1.0 Client Metadata + // http://openid.net/specs/openid-connect-registration-1_0.html + $app = array( + 'name' => (x($_REQUEST, 'client_name') ? urldecode($_REQUEST['client_name']) : 'Unknown App'), + 'icon' => (x($_REQUEST, 'logo_uri') ? urldecode($_REQUEST['logo_uri']) : '/images/icons/plugin.png'), + 'url' => (x($_REQUEST, 'client_uri') ? urldecode($_REQUEST['client_uri']) : ''), + ); $o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array( '$title' => '', - '$authorize' => 'Do you authorize the app "' . $app['name'] . '" to access your channel data?', + '$authorize' => 'Do you authorize the app ' . $app['name'] . ' to access your channel data?', '$app' => $app, '$yes' => t('Allow'), '$no' => t('Deny'), '$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''), '$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''), - '$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : '') + '$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''), )); return $o; } @@ -56,14 +62,15 @@ class Authorize extends \Zotlabs\Web\Controller { $storage = new OAuth2Storage(\DBA::$dba->db); $s = new \Zotlabs\Identity\OAuth2Server($storage); - + // TODO: The automatic client registration protocol below should adhere more + // closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined + // at https://tools.ietf.org/html/rfc7591 + // If no client_id was provided, generate a new one. if (x($_POST, 'client_id')) { $client_id = $_POST['client_id']; - logger('client_id was provided: ' . $client_id); } else { $client_id = $_POST['client_id'] = random_string(16); - logger('client_id was not provided. Generated new id: ' . $client_id); } // If no redirect_uri was provided, generate a fake one. if (x($_POST, 'redirect_uri')) { @@ -72,15 +79,15 @@ class Authorize extends \Zotlabs\Web\Controller { $redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com'; } - logger('redirect_uri is : ' . $redirect_uri); // If the client is not registered, add to the database if (!$storage->getClientDetails($client_id)) { $client_secret = random_string(16); - $storage->setClientDetails($client_id, $client_secret, $redirect_uri); + // Client apps are registered per channel + $user_id = local_channel(); + $storage->setClientDetails($client_id, $client_secret, $redirect_uri, null, null, $user_id); } $request = \OAuth2\Request::createFromGlobals(); - logger(json_encode($request, JSON_PRETTY_PRINT), LOGGER_DEBUG); $response = new \OAuth2\Response(); // validate the authorize request diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php index 6e9f31c47..79958f025 100644 --- a/Zotlabs/Module/Oauth2testvehicle.php +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -8,6 +8,7 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { // If there is a 'code' and 'state' parameter then this is a client app // callback issued after the authorization code request + // TODO: Check state value and compare to original sent value if ($_REQUEST['code'] && $_REQUEST['state']) { logger('Authorization callback invoked.', LOGGER_DEBUG); logger(json_encode($_REQUEST, JSON_PRETTY_PRINT), LOGGER_DEBUG); @@ -61,8 +62,14 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { array( array('response_type', 'code'), array('client_id', urlencode('test_app_client_id')), - array('redirect_uri', urlencode('http://hub.localhost/oauth2testvehicle')), - array('state', 'xyz') + array('redirect_uri', 'http://hub.localhost/oauth2testvehicle'), + array('state', 'xyz'), + // OpenID Connect Dynamic Client Registration 1.0 Client Metadata + // http://openid.net/specs/openid-connect-registration-1_0.html + array('client_name', urlencode('Killer App')), + array('logo_uri', urlencode('https://client.example.com/website/img/icon.png')), + array('client_uri', urlencode('https://client.example.com/website')), + array('application_type', 'web'), // would be 'native' for mobile app ), 'oauth_authorize', 'Authorize a test client app', diff --git a/view/tpl/oauth2testvehicle.tpl b/view/tpl/oauth2testvehicle.tpl index aebc71bb2..18bbfb1ff 100644 --- a/view/tpl/oauth2testvehicle.tpl +++ b/view/tpl/oauth2testvehicle.tpl @@ -2,7 +2,7 @@ {{foreach $endpoints as $ept}}
-
+

{{$ept.3}}

{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}&{{/foreach}}

diff --git a/view/tpl/oauth_authorize.tpl b/view/tpl/oauth_authorize.tpl index f5da11cdc..72701ce52 100755 --- a/view/tpl/oauth_authorize.tpl +++ b/view/tpl/oauth_authorize.tpl @@ -2,8 +2,8 @@
-

{{$app.name}}

-

{{$authorize}}

+

{{$app.name}}

+

{{$authorize}}

From 70b8f3240f9bc38a41e314f613f6c1bd69f5b430 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sun, 25 Feb 2018 08:36:40 -0500 Subject: [PATCH 5/7] An authorization token is received, but I had to modify the Request class in vendor/bshaffer/oauth2-server-php/ to accept $_REQUEST instead of $_POST. --- Zotlabs/Module/Authorize.php | 9 ++- Zotlabs/Module/Oauth2testvehicle.php | 76 +++++++++++++++---- Zotlabs/Module/Token.php | 3 +- .../oauth2-server-php/src/OAuth2/Request.php | 2 +- 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php index 2c0c9248f..f505b4681 100644 --- a/Zotlabs/Module/Authorize.php +++ b/Zotlabs/Module/Authorize.php @@ -79,17 +79,18 @@ class Authorize extends \Zotlabs\Web\Controller { $redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com'; } + $request = \OAuth2\Request::createFromGlobals(); + $response = new \OAuth2\Response(); + // If the client is not registered, add to the database if (!$storage->getClientDetails($client_id)) { $client_secret = random_string(16); // Client apps are registered per channel $user_id = local_channel(); - $storage->setClientDetails($client_id, $client_secret, $redirect_uri, null, null, $user_id); + $storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id); + $response->setParameter('client_secret', $client_secret); } - $request = \OAuth2\Request::createFromGlobals(); - $response = new \OAuth2\Response(); - // validate the authorize request if (!$s->validateAuthorizeRequest($request, $response)) { $response->send(); diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php index 79958f025..37a0b9b0e 100644 --- a/Zotlabs/Module/Oauth2testvehicle.php +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -9,6 +9,11 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { // If there is a 'code' and 'state' parameter then this is a client app // callback issued after the authorization code request // TODO: Check state value and compare to original sent value + // "You should first compare this state value to ensure it matches the + // one you started with. You can typically store the state value in a + // cookie, and compare it when the user comes back. This ensures your + // redirection endpoint isn't able to be tricked into attempting to + // exchange arbitrary authorization codes." if ($_REQUEST['code'] && $_REQUEST['state']) { logger('Authorization callback invoked.', LOGGER_DEBUG); logger(json_encode($_REQUEST, JSON_PRETTY_PRINT), LOGGER_DEBUG); @@ -35,17 +40,6 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { ) */ '$endpoints' => array( - array( - 'oauth2testvehicle', - array( - array( - 'action', 'create_db' - ) - ), - 'oauth2test_create_db', - 'Create the OAuth2 database tables', - 'POST' - ), array( 'oauth2testvehicle', array( @@ -57,11 +51,22 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { 'Delete the OAuth2 database tables', 'POST' ), + array( + 'oauth2testvehicle', + array( + array( + 'action', 'create_db' + ) + ), + 'oauth2test_create_db', + 'Create the OAuth2 database tables', + 'POST' + ), array( 'authorize', array( array('response_type', 'code'), - array('client_id', urlencode('test_app_client_id')), + array('client_id', urlencode('killer_app')), array('redirect_uri', 'http://hub.localhost/oauth2testvehicle'), array('state', 'xyz'), // OpenID Connect Dynamic Client Registration 1.0 Client Metadata @@ -74,6 +79,27 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { 'oauth_authorize', 'Authorize a test client app', 'GET' + ), + /* + * POST https://api.authorization-server.com/token + grant_type=authorization_code& + code=AUTH_CODE_HERE& + redirect_uri=REDIRECT_URI& + client_id=CLIENT_ID + */ + array( + 'oauth2testvehicle', + array( + array('action', 'request_token'), + array('grant_type', 'authorization_code'), + array('code', (x($_REQUEST, 'code') ? $_REQUEST['code'] : 'no_authorization_code')), + array('redirect_uri', 'http://hub.localhost/oauth2testvehicle'), + array('client_id', urlencode('killer_app')), + array('client_secret', (x($_REQUEST, 'client_secret') ? $_REQUEST['client_secret'] : 'no_client_secret')), + ), + 'oauth_token_request', + 'Request a token', + 'POST' ) ) )); @@ -83,11 +109,31 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { function post() { - logger(json_encode($_POST), LOGGER_DEBUG); - + //logger(json_encode($_POST, JSON_PRETTY_PRINT), LOGGER_DEBUG); switch ($_POST['action']) { - + case 'request_token': + $grant_type = (x($_POST, 'grant_type') ? $_POST['grant_type'] : ''); + $redirect_uri = (x($_POST, 'redirect_uri') ? $_POST['redirect_uri'] : ''); + $client_id = (x($_POST, 'client_id') ? $_POST['client_id'] : ''); + $code = (x($_POST, 'code') ? $_POST['code'] : ''); + $client_secret = (x($_POST, 'client_secret') ? $_POST['client_secret'] : ''); + $url = z_root() . '/token/?'; + $url .= 'grant_type=' . urlencode($grant_type); + $url .= '&redirect_uri=' . urlencode($redirect_uri); + $url .= '&client_id=' . urlencode($client_id); + $url .= '&code=' . urlencode($code); + $post = z_fetch_url($url, false, 0, array( + 'custom' => 'POST', + 'http_auth' => $client_id . ':' . $client_secret, + )); + //logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG); + $response = json_decode($post['body'], true); + logger(json_encode($response, JSON_PRETTY_PRINT), LOGGER_DEBUG); + if($response['access_token']) { + info('Access token received: ' . $response['access_token'] . EOL); + } + break; case 'delete_db': $status = true; // Use the \OAuth2\Storage\Pdo class to create the OAuth2 tables diff --git a/Zotlabs/Module/Token.php b/Zotlabs/Module/Token.php index f7c074233..32cf95c61 100644 --- a/Zotlabs/Module/Token.php +++ b/Zotlabs/Module/Token.php @@ -29,7 +29,8 @@ class Token extends \Zotlabs\Web\Controller { } $s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db)); - $s->handleTokenRequest(\OAuth2\Request::createFromGlobals())->send(); + $request = \OAuth2\Request::createFromGlobals(); + $s->handleTokenRequest($request)->send(); killme(); } diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php index c96cb972f..2903e9f6c 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php @@ -226,7 +226,7 @@ class Request implements RequestInterface $class = get_called_class(); /** @var Request $request */ - $request = new $class($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); + $request = new $class($_GET, $_REQUEST, array(), $_COOKIE, $_FILES, $_SERVER); $contentType = $request->server('CONTENT_TYPE', ''); $requestMethod = $request->server('REQUEST_METHOD', 'GET'); From 45e0fc6802b360710becf7ddaf6aed6a9de1d876 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Mon, 26 Feb 2018 18:16:43 -0500 Subject: [PATCH 6/7] Successful OAuth2 sequence demonstrated with the test vehicle, including an authenticated API call using an access_token. --- Zotlabs/Module/Authorize.php | 36 +++------ Zotlabs/Module/Oauth2testvehicle.php | 106 +++++++++++++++++---------- include/api_auth.php | 57 +++++++++++--- include/network.php | 4 +- view/tpl/oauth2testvehicle.tpl | 16 +++- 5 files changed, 137 insertions(+), 82 deletions(-) diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php index f505b4681..c76dfb9df 100644 --- a/Zotlabs/Module/Authorize.php +++ b/Zotlabs/Module/Authorize.php @@ -6,28 +6,6 @@ use Zotlabs\Identity\OAuth2Storage; class Authorize extends \Zotlabs\Web\Controller { - function init() { - - // workaround for HTTP-auth in CGI mode - if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { - $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)); - if (strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } - - if (x($_SERVER, 'HTTP_AUTHORIZATION')) { - $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)); - if (strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } - } - function get() { if (!local_channel()) { return login(); @@ -37,7 +15,7 @@ class Authorize extends \Zotlabs\Web\Controller { // http://openid.net/specs/openid-connect-registration-1_0.html $app = array( 'name' => (x($_REQUEST, 'client_name') ? urldecode($_REQUEST['client_name']) : 'Unknown App'), - 'icon' => (x($_REQUEST, 'logo_uri') ? urldecode($_REQUEST['logo_uri']) : '/images/icons/plugin.png'), + 'icon' => (x($_REQUEST, 'logo_uri') ? urldecode($_REQUEST['logo_uri']) : z_root() . '/images/icons/plugin.png'), 'url' => (x($_REQUEST, 'client_uri') ? urldecode($_REQUEST['client_uri']) : ''), ); $o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array( @@ -76,20 +54,26 @@ class Authorize extends \Zotlabs\Web\Controller { if (x($_POST, 'redirect_uri')) { $redirect_uri = $_POST['redirect_uri']; } else { - $redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com'; + $redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com/oauth'; } $request = \OAuth2\Request::createFromGlobals(); $response = new \OAuth2\Response(); // If the client is not registered, add to the database - if (!$storage->getClientDetails($client_id)) { + if (!$client = $storage->getClientDetails($client_id)) { $client_secret = random_string(16); // Client apps are registered per channel $user_id = local_channel(); $storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id); - $response->setParameter('client_secret', $client_secret); + } + if (!$client = $storage->getClientDetails($client_id)) { + // There was an error registering the client. + $response->send(); + killme(); + } + $response->setParameter('client_secret', $client['client_secret']); // validate the authorize request if (!$s->validateAuthorizeRequest($request, $response)) { diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php index 37a0b9b0e..29c6ec50e 100644 --- a/Zotlabs/Module/Oauth2testvehicle.php +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -2,6 +2,12 @@ namespace Zotlabs\Module; +/** + * The OAuth2TestVehicle class is a way to test the registration of an OAuth2 + * client app. It allows you to walk through the steps of registering a client, + * requesting an authorization code for that client, and then requesting an + * access token for use in authentication against the Hubzilla API endpoints. + */ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { function init() { @@ -14,17 +20,19 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { // cookie, and compare it when the user comes back. This ensures your // redirection endpoint isn't able to be tricked into attempting to // exchange arbitrary authorization codes." - if ($_REQUEST['code'] && $_REQUEST['state']) { - logger('Authorization callback invoked.', LOGGER_DEBUG); - logger(json_encode($_REQUEST, JSON_PRETTY_PRINT), LOGGER_DEBUG); - info('Authorization callback invoked.' . EOL); - return $this->get(); - } + $_SESSION['redirect_uri'] = 'http://hub.localhost/oauth2testvehicle'; + $_SESSION['authorization_code'] = (x($_REQUEST, 'code') ? $_REQUEST['code'] : $_SESSION['authorization_code']); + $_SESSION['state'] = (x($_REQUEST, 'state') ? $_REQUEST['state'] : $_SESSION['state'] ); + $_SESSION['client_id'] = (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : $_SESSION['client_id'] ); + $_SESSION['client_secret'] = (x($_REQUEST, 'client_secret') ? $_REQUEST['client_secret'] : $_SESSION['client_secret']); + $_SESSION['access_token'] = (x($_REQUEST, 'access_token') ? $_REQUEST['access_token'] : $_SESSION['access_token'] ); + $_SESSION['api_response'] = (x($_SESSION, 'api_response') ? $_SESSION['api_response'] : ''); } function get() { - + $o .= replace_macros(get_markup_template('oauth2testvehicle.tpl'), array( '$baseurl' => z_root(), + '$api_response' => $_SESSION['api_response'], /* endpoints => array( array( @@ -49,7 +57,8 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { ), 'oauth2test_delete_db', 'Delete the OAuth2 database tables', - 'POST' + 'POST', + ($_SESSION['success'] === 'delete_db'), ), array( 'oauth2testvehicle', @@ -60,58 +69,76 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { ), 'oauth2test_create_db', 'Create the OAuth2 database tables', - 'POST' + 'POST', + ($_SESSION['success'] === 'create_db'), ), array( 'authorize', array( array('response_type', 'code'), - array('client_id', urlencode('killer_app')), - array('redirect_uri', 'http://hub.localhost/oauth2testvehicle'), + array('client_id', (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : 'oauth2_test_app')), + array('redirect_uri', $_SESSION['redirect_uri']), array('state', 'xyz'), // OpenID Connect Dynamic Client Registration 1.0 Client Metadata // http://openid.net/specs/openid-connect-registration-1_0.html - array('client_name', urlencode('Killer App')), - array('logo_uri', urlencode('https://client.example.com/website/img/icon.png')), + array('client_name', 'OAuth2 Test App'), + array('logo_uri', urlencode(z_root() . '/images/icons/plugin.png')), array('client_uri', urlencode('https://client.example.com/website')), array('application_type', 'web'), // would be 'native' for mobile app ), 'oauth_authorize', 'Authorize a test client app', - 'GET' + 'GET', + (($_REQUEST['code'] && $_REQUEST['state']) ? true : false), ), - /* - * POST https://api.authorization-server.com/token - grant_type=authorization_code& - code=AUTH_CODE_HERE& - redirect_uri=REDIRECT_URI& - client_id=CLIENT_ID - */ array( 'oauth2testvehicle', array( array('action', 'request_token'), array('grant_type', 'authorization_code'), - array('code', (x($_REQUEST, 'code') ? $_REQUEST['code'] : 'no_authorization_code')), - array('redirect_uri', 'http://hub.localhost/oauth2testvehicle'), - array('client_id', urlencode('killer_app')), - array('client_secret', (x($_REQUEST, 'client_secret') ? $_REQUEST['client_secret'] : 'no_client_secret')), + array('code', $_SESSION['authorization_code']), + array('redirect_uri', $_SESSION['redirect_uri']), + array('client_id', ($_SESSION['client_id'] ? $_SESSION['client_id'] : 'oauth2_test_app')), + array('client_secret', $_SESSION['client_secret']), ), 'oauth_token_request', 'Request a token', - 'POST' + 'POST', + ($_SESSION['success'] === 'request_token'), + ), + array( + 'oauth2testvehicle', + array( + array('action', 'api_files'), + array('access_token', $_SESSION['access_token']), + ), + 'oauth_api_files', + 'API: Get channel files', + 'POST', + ($_SESSION['success'] === 'api_files'), ) ) )); - + $_SESSION['success'] = ''; return $o; } function post() { - //logger(json_encode($_POST, JSON_PRETTY_PRINT), LOGGER_DEBUG); - switch ($_POST['action']) { + case 'api_files': + $access_token = $_SESSION['access_token']; + $url = z_root() . '/api/z/1.0/files/'; + $headers = []; + $headers[] = 'Authorization: Bearer ' . $access_token; + $post = z_fetch_url($url, false, 0, array( + 'custom' => 'GET', + 'headers' => $headers, + )); + logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG); + $response = json_decode($post['body'], true); + $_SESSION['api_response'] = json_encode($response, JSON_PRETTY_PRINT); + break; case 'request_token': $grant_type = (x($_POST, 'grant_type') ? $_POST['grant_type'] : ''); $redirect_uri = (x($_POST, 'redirect_uri') ? $_POST['redirect_uri'] : ''); @@ -119,19 +146,21 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { $code = (x($_POST, 'code') ? $_POST['code'] : ''); $client_secret = (x($_POST, 'client_secret') ? $_POST['client_secret'] : ''); $url = z_root() . '/token/?'; - $url .= 'grant_type=' . urlencode($grant_type); + $url .= 'grant_type=' . $grant_type; $url .= '&redirect_uri=' . urlencode($redirect_uri); - $url .= '&client_id=' . urlencode($client_id); - $url .= '&code=' . urlencode($code); + $url .= '&client_id=' . $client_id; + $url .= '&code=' . $code; $post = z_fetch_url($url, false, 0, array( 'custom' => 'POST', 'http_auth' => $client_id . ':' . $client_secret, )); - //logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG); + logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG); $response = json_decode($post['body'], true); logger(json_encode($response, JSON_PRETTY_PRINT), LOGGER_DEBUG); if($response['access_token']) { info('Access token received: ' . $response['access_token'] . EOL); + $_SESSION['success'] = 'request_token'; + $_SESSION['access_token'] = $response['access_token']; } break; case 'delete_db': @@ -140,26 +169,23 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { // by passing it the database connection $pdo = \DBA::$dba->db; $storage = new \Zotlabs\Storage\ZotOauth2Pdo($pdo); - logger('Deleting existing database tables...', LOGGER_DEBUG); foreach ($storage->getConfig() as $key => $table) { - logger('Deleting table ' . dbesc($table), LOGGER_DEBUG); $r = q("DROP TABLE %s;", dbesc($table)); if (!$r) { - logger('Errors encountered deleting database table ' . $table . '.', LOGGER_DEBUG); $status = false; } } if (!$status) { notice('Errors encountered deleting database tables.' . EOL); + $_SESSION['success'] = ''; } else { info('Database tables deleted successfully.' . EOL); + $_SESSION['success'] = 'delete_db'; } - break; case 'create_db': $status = true; - logger('Creating database tables...', LOGGER_DEBUG); @include('.htconfig.php'); $pdo = \DBA::$dba->db; $storage = new \Zotlabs\Storage\ZotOauth2Pdo($pdo); @@ -168,15 +194,17 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { $result = $pdo->exec($statement); } catch (\PDOException $e) { $status = false; - logger('Error executing database statement: ' . $statement, LOGGER_DEBUG); } } if (!$status) { notice('Errors encountered creating database tables.' . EOL); + $_SESSION['success'] = ''; } else { info('Database tables created successfully.' . EOL); + $_SESSION['success'] = 'create_db'; } + break; default: break; diff --git a/include/api_auth.php b/include/api_auth.php index 5c0bcb317..e2f7ab155 100644 --- a/include/api_auth.php +++ b/include/api_auth.php @@ -14,25 +14,58 @@ function api_login(&$a){ // login with oauth try { - $oauth = new ZotOAuth1(); - $req = OAuth1Request::from_request(); + // OAuth 2.0 + $storage = new \Zotlabs\Identity\OAuth2Storage(\DBA::$dba->db); + $server = new \Zotlabs\Identity\OAuth2Server($storage); + $request = \OAuth2\Request::createFromGlobals(); + if ($server->verifyResourceRequest($request)) { + $token = $server->getAccessTokenData($request); + $uid = $token['user_id']; + $r = q("SELECT * FROM channel WHERE channel_id = %d LIMIT 1", + intval($uid) + ); + if (count($r)) { + $record = $r[0]; + } else { + header('HTTP/1.0 401 Unauthorized'); + echo('This api requires login'); + killme(); + } - list($consumer,$token) = $oauth->verify_request($req); + $_SESSION['uid'] = $record['channel_id']; + $_SESSION['addr'] = $_SERVER['REMOTE_ADDR']; - if (!is_null($token)){ - $oauth->loginUser($token->uid); + $x = q("select * from account where account_id = %d LIMIT 1", + intval($record['channel_account_id']) + ); + if ($x) { + require_once('include/security.php'); + authenticate_success($x[0], null, true, false, true, true); + $_SESSION['allow_api'] = true; + call_hooks('logged_in', App::$user); + return; + } + } else { + // OAuth 1.0 + $oauth = new ZotOAuth1(); + $req = OAuth1Request::from_request(); - App::set_oauth_key($consumer->key); + list($consumer, $token) = $oauth->verify_request($req); - call_hooks('logged_in', App::$user); - return; + if (!is_null($token)) { + $oauth->loginUser($token->uid); + + App::set_oauth_key($consumer->key); + + call_hooks('logged_in', App::$user); + return; + } + killme(); } - killme(); - } - catch(Exception $e) { + } catch (Exception $e) { logger($e->getMessage()); } - + // workarounds for HTTP-auth in CGI mode foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) { diff --git a/include/network.php b/include/network.php index f8cb68613..9768a2544 100644 --- a/include/network.php +++ b/include/network.php @@ -88,6 +88,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $instance_headers[] = 'Cookie: PHPSESSID=' . session_id(); } } + logger('headers: ' . json_encode($instance_headers, JSON_PRETTY_PRINT)); + if($instance_headers) @curl_setopt($ch, CURLOPT_HTTPHEADER, $instance_headers); @@ -143,7 +145,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $base = $s; $curl_info = @curl_getinfo($ch); $http_code = $curl_info['http_code']; - //logger('fetch_url:' . $http_code . ' data: ' . $s); + logger('fetch_url:' . $http_code . ' data: ' . $s); $header = ''; // Pull out multiple headers, e.g. proxy and continuation headers diff --git a/view/tpl/oauth2testvehicle.tpl b/view/tpl/oauth2testvehicle.tpl index 18bbfb1ff..ce46b58c0 100644 --- a/view/tpl/oauth2testvehicle.tpl +++ b/view/tpl/oauth2testvehicle.tpl @@ -4,10 +4,18 @@

{{$ept.3}}

-

{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}&{{/foreach}} -

+ {{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}&{{/foreach}} +
- +  
-{{/foreach}} \ No newline at end of file +{{/foreach}} +
+

API response

+
+	
+	{{$api_response}}
+	
+	
+
\ No newline at end of file From aa6f7481a023c04b30ffc6aec2016e2b7b3b386f Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sat, 10 Mar 2018 15:43:13 -0500 Subject: [PATCH 7/7] Fixed access_token request bug and returned oauth2-server-php library to unmodified state. --- Zotlabs/Module/Oauth2testvehicle.php | 15 ++++++++------- .../oauth2-server-php/src/OAuth2/Request.php | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Zotlabs/Module/Oauth2testvehicle.php b/Zotlabs/Module/Oauth2testvehicle.php index 29c6ec50e..82e309f1c 100644 --- a/Zotlabs/Module/Oauth2testvehicle.php +++ b/Zotlabs/Module/Oauth2testvehicle.php @@ -145,13 +145,14 @@ class OAuth2TestVehicle extends \Zotlabs\Web\Controller { $client_id = (x($_POST, 'client_id') ? $_POST['client_id'] : ''); $code = (x($_POST, 'code') ? $_POST['code'] : ''); $client_secret = (x($_POST, 'client_secret') ? $_POST['client_secret'] : ''); - $url = z_root() . '/token/?'; - $url .= 'grant_type=' . $grant_type; - $url .= '&redirect_uri=' . urlencode($redirect_uri); - $url .= '&client_id=' . $client_id; - $url .= '&code=' . $code; - $post = z_fetch_url($url, false, 0, array( - 'custom' => 'POST', + $url = z_root() . '/token/'; + $params = http_build_query(array( + 'grant_type' => $grant_type, + 'redirect_uri' => urlencode($redirect_uri), + 'client_id' => $client_id, + 'code' => $code, + )); + $post = z_post_url($url, $params, 0, array( 'http_auth' => $client_id . ':' . $client_secret, )); logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG); diff --git a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php index 2903e9f6c..c96cb972f 100644 --- a/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php +++ b/vendor/bshaffer/oauth2-server-php/src/OAuth2/Request.php @@ -226,7 +226,7 @@ class Request implements RequestInterface $class = get_called_class(); /** @var Request $request */ - $request = new $class($_GET, $_REQUEST, array(), $_COOKIE, $_FILES, $_SERVER); + $request = new $class($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); $contentType = $request->server('CONTENT_TYPE', ''); $requestMethod = $request->server('REQUEST_METHOD', 'GET');