From 43fca182e3915734587abf389d819546ebade3a4 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Thu, 22 Feb 2018 15:10:05 -0500 Subject: 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 +++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 20 deletions(-) (limited to 'Zotlabs/Module/Authorize.php') 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; } } + } + + 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'; + } - $s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db)); + 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"); } -- cgit v1.2.3 From 64ee42fc3d00765bc5c60e451b86230ea38ffdfb Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sat, 24 Feb 2018 06:48:30 -0500 Subject: Add channel ID to user_id in clients table. Added TODO comments about dynamic client registration protocol. --- Zotlabs/Module/Authorize.php | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'Zotlabs/Module/Authorize.php') 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 -- cgit v1.2.3 From 70b8f3240f9bc38a41e314f613f6c1bd69f5b430 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Sun, 25 Feb 2018 08:36:40 -0500 Subject: 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 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Zotlabs/Module/Authorize.php') 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(); -- cgit v1.2.3 From 45e0fc6802b360710becf7ddaf6aed6a9de1d876 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Mon, 26 Feb 2018 18:16:43 -0500 Subject: Successful OAuth2 sequence demonstrated with the test vehicle, including an authenticated API call using an access_token. --- Zotlabs/Module/Authorize.php | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) (limited to 'Zotlabs/Module/Authorize.php') 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)) { -- cgit v1.2.3