You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sc...@apache.org on 2015/09/03 16:02:12 UTC
airavata-php-gateway git commit: Adding OAuth request_code grant flow
support for PGA
Repository: airavata-php-gateway
Updated Branches:
refs/heads/master 088dfff02 -> cc8308999
Adding OAuth request_code grant flow support for PGA
Project: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/commit/cc830899
Tree: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/tree/cc830899
Diff: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/diff/cc830899
Branch: refs/heads/master
Commit: cc83089998a0c33cd5bf713f086b8220545f0dcb
Parents: 088dfff
Author: Supun Nakandala <sc...@apache.org>
Authored: Thu Sep 3 19:31:33 2015 +0530
Committer: Supun Nakandala <sc...@apache.org>
Committed: Thu Sep 3 19:31:33 2015 +0530
----------------------------------------------------------------------
app/config/pga_config.php.template | 24 ++-
app/controllers/AccountController.php | 54 ++++++-
app/filters.php | 23 ++-
app/libraries/Airavata/API/Airavata.php | 42 +-----
app/libraries/Wsis/Stubs/OAuthManager.php | 147 +++++++++++++++++++
app/libraries/Wsis/Stubs/UserProfileManager.php | 5 +
app/libraries/Wsis/Wsis.php | 52 +++++++
app/routes.php | 2 +
8 files changed, 300 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/config/pga_config.php.template
----------------------------------------------------------------------
diff --git a/app/config/pga_config.php.template b/app/config/pga_config.php.template
index 19c4707..58323d0 100644
--- a/app/config/pga_config.php.template
+++ b/app/config/pga_config.php.template
@@ -26,12 +26,32 @@ return array(
/**
* Tenant admin's username
*/
- 'admin-username' => 'test@testphprg.scigap.org',
+ 'admin-username' => 'master@master.airavata.scigap.org',
/**
* Tenant admin's password
*/
- 'admin-password' => 'testadmin@scigap.org',
+ 'admin-password' => 'master',
+
+ /**
+ * Authentication mode (basic, oauth)
+ */
+ 'auth-mode' => 'basic',
+
+ /**
+ * OAuth client key
+ */
+ 'oauth-client-key' => 'iGEREhSBLuGapdcXwMU0b8jEpA4a',
+
+ /**
+ * OAuth client secret
+ */
+ 'oauth-client-secret' => 'g4Lgp05JIJcNQryJkNKjXJYi8A8a',
+
+ /**
+ * OAuth callback url
+ */
+ 'oauth-callback-url' => 'http://localhost/airavata-php-gateway/public/callback-url',
/**
* Identity server domain
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/controllers/AccountController.php
----------------------------------------------------------------------
diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php
index 64a0b09..8dcbd0f 100755
--- a/app/controllers/AccountController.php
+++ b/app/controllers/AccountController.php
@@ -60,8 +60,6 @@ class AccountController extends BaseController
//update user profile
WSIS::updateUserProfile($username, $email, $first_name, $last_name);
- //creating a default project for user
- ProjectUtilities::create_default_project($username);
CommonUtilities::print_success_message('New user created!');
return View::make('account/login');
}
@@ -69,7 +67,55 @@ class AccountController extends BaseController
public function loginView()
{
- return View::make('account/login');
+ if(Config::get('pga_config.wsis')['auth-mode'] == "oauth"){
+ $url = WSIS::getOAuthRequestCodeUrl();
+ return Redirect::away($url);
+ }else{
+ return View::make('account/login');
+ }
+ }
+
+ public function oauthCallback()
+ {
+ if (!isset($_GET["code"])) {
+ CommonUtilities::print_error_message("Require the code parameter to validate!");
+ }
+
+ $code = $_GET["code"];
+ $response = WSIS::getOAuthToken($code);
+ $accessToken = $response->access_token;
+ $refreshToken = $response->refresh_token;
+ $expirationTime = time() + $response->expires_in - 5; //5 seconds safe margin
+ $authzToken = new Airavata\Model\Security\AuthzToken();
+ $authzToken->accessToken = $accessToken;
+ Session::put('authz-token',$authzToken);
+ Session::put('oauth-refresh-code',$refreshToken);
+ Session::put('oauth-expiration-time',$expirationTime);
+
+ $userProfile = WSIS::getUserProfileFromOAuthToken($accessToken);
+ Session::put("user-profile", $userProfile);
+
+ $userRoles = $userProfile['roles'];
+ if (in_array(Config::get('pga_config.wsis')['admin-role-name'], $userRoles)) {
+ Session::put("admin", true);
+ }
+ if (in_array(Config::get('pga_config.wsis')['read-only-admin'], $userRoles)) {
+ Session::put("admin-read-only", true);
+ }
+
+ $username = $userProfile['username'];
+ CommonUtilities::store_id_in_session($username);
+ CommonUtilities::print_success_message('Login successful! You will be redirected to your home page shortly.');
+ Session::put("gateway_id", Config::get('pga_config.airavata')['gateway-id']);
+
+ //creating a default project for user
+ $projects = ProjectUtilities::get_all_user_projects(Config::get('pga_config.airavata')['gateway-id'], $username);
+ if($projects == null || count($projects) == 0){
+ //creating a default project for user
+ ProjectUtilities::create_default_project($username);
+ }
+
+ return Redirect::to("home");
}
public function loginSubmit()
@@ -95,9 +141,7 @@ class AccountController extends BaseController
CommonUtilities::store_id_in_session($username);
CommonUtilities::print_success_message('Login successful! You will be redirected to your home page shortly.');
- //TODO::If this option is not safe, have to find a better method to send credentials to identity server on every connection.
Session::put("gateway_id", Config::get('pga_config.airavata')['gateway-id']);
- Session::put("password", $_POST["password"]);
//creating a default project for user
$projects = ProjectUtilities::get_all_user_projects(Config::get('pga_config.airavata')['gateway-id'], $username);
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/filters.php
----------------------------------------------------------------------
diff --git a/app/filters.php b/app/filters.php
index 80336ab..ac98976 100755
--- a/app/filters.php
+++ b/app/filters.php
@@ -12,13 +12,26 @@
*/
App::before(function ($request) {
- $authzToken = new Airavata\Model\Security\AuthzToken();
- $authzToken->accessToken = "emptyToken";
- $apiVersion = Airavata::getAPIVersion($authzToken);
+ //Check Airavata Server is up
+ $apiVersion = Airavata::getAPIVersion();
if (empty($apiVersion))
return View::make("server-down");
- else
- Session::put('authz-token',$authzToken);
+
+ //Check OAuth token has expired
+ if(Config::get('pga_config.wsis')['auth-mode']=="oauth" && Session::has('authz-token')){
+ $currentTime = time();
+ if($currentTime > Session::get('oauth-expiration-time')){
+ $response = WSIS::getRefreshedOAutheToken(Session::get('oauth-refresh-code'));
+ $accessToken = $response->access_token;
+ $refreshToken = $response->refresh_token;
+ $expirationTime = time()/1000 + $response->expires_in - 300;
+ $authzToken = new Airavata\Model\Security\AuthzToken();
+ $authzToken->accessToken = $accessToken;
+ Session::put('authz-token',$authzToken);
+ Session::put('oauth-refresh-code',$refreshToken);
+ Session::put('oauth-expiration-time',$expirationTime);
+ }
+ }
});
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/libraries/Airavata/API/Airavata.php
----------------------------------------------------------------------
diff --git a/app/libraries/Airavata/API/Airavata.php b/app/libraries/Airavata/API/Airavata.php
index cab3cef..c068aa6 100644
--- a/app/libraries/Airavata/API/Airavata.php
+++ b/app/libraries/Airavata/API/Airavata.php
@@ -20,14 +20,13 @@ interface AiravataIf {
/**
* Fetch Apache Airavata API version
*
- * @param \Airavata\Model\Security\AuthzToken $authzToken
* @return string
* @throws \Airavata\API\Error\InvalidRequestException
* @throws \Airavata\API\Error\AiravataClientException
* @throws \Airavata\API\Error\AiravataSystemException
* @throws \Airavata\API\Error\AuthorizationException
*/
- public function getAPIVersion(\Airavata\Model\Security\AuthzToken $authzToken);
+ public function getAPIVersion();
/**
* @param \Airavata\Model\Security\AuthzToken $authzToken
* @param \Airavata\Model\Workspace\Gateway $gateway
@@ -2555,16 +2554,15 @@ class AiravataClient implements \Airavata\API\AiravataIf {
$this->output_ = $output ? $output : $input;
}
- public function getAPIVersion(\Airavata\Model\Security\AuthzToken $authzToken)
+ public function getAPIVersion()
{
- $this->send_getAPIVersion($authzToken);
+ $this->send_getAPIVersion();
return $this->recv_getAPIVersion();
}
- public function send_getAPIVersion(\Airavata\Model\Security\AuthzToken $authzToken)
+ public function send_getAPIVersion()
{
$args = new \Airavata\API\Airavata_getAPIVersion_args();
- $args->authzToken = $authzToken;
$bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
if ($bin_accel)
{
@@ -10204,26 +10202,12 @@ class AiravataClient implements \Airavata\API\AiravataIf {
class Airavata_getAPIVersion_args {
static $_TSPEC;
- /**
- * @var \Airavata\Model\Security\AuthzToken
- */
- public $authzToken = null;
- public function __construct($vals=null) {
+ public function __construct() {
if (!isset(self::$_TSPEC)) {
self::$_TSPEC = array(
- 1 => array(
- 'var' => 'authzToken',
- 'type' => TType::STRUCT,
- 'class' => '\Airavata\Model\Security\AuthzToken',
- ),
);
}
- if (is_array($vals)) {
- if (isset($vals['authzToken'])) {
- $this->authzToken = $vals['authzToken'];
- }
- }
}
public function getName() {
@@ -10245,14 +10229,6 @@ class Airavata_getAPIVersion_args {
}
switch ($fid)
{
- case 1:
- if ($ftype == TType::STRUCT) {
- $this->authzToken = new \Airavata\Model\Security\AuthzToken();
- $xfer += $this->authzToken->read($input);
- } else {
- $xfer += $input->skip($ftype);
- }
- break;
default:
$xfer += $input->skip($ftype);
break;
@@ -10266,14 +10242,6 @@ class Airavata_getAPIVersion_args {
public function write($output) {
$xfer = 0;
$xfer += $output->writeStructBegin('Airavata_getAPIVersion_args');
- if ($this->authzToken !== null) {
- if (!is_object($this->authzToken)) {
- throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
- }
- $xfer += $output->writeFieldBegin('authzToken', TType::STRUCT, 1);
- $xfer += $this->authzToken->write($output);
- $xfer += $output->writeFieldEnd();
- }
$xfer += $output->writeFieldStop();
$xfer += $output->writeStructEnd();
return $xfer;
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/libraries/Wsis/Stubs/OAuthManager.php
----------------------------------------------------------------------
diff --git a/app/libraries/Wsis/Stubs/OAuthManager.php b/app/libraries/Wsis/Stubs/OAuthManager.php
new file mode 100644
index 0000000..5188fd6
--- /dev/null
+++ b/app/libraries/Wsis/Stubs/OAuthManager.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace Wsis\Stubs;
+
+class OAuthManager
+{
+
+ public $CurlHeaders;
+ public $ResponseCode;
+
+ private $_AuthorizeUrl;
+ private $_AccessTokenUrl;
+ private $_UserInfoUrl;
+ private $_verifyPeer;
+ private $_cafilePath;
+
+ public function __construct($serverUrl, $verifyPeer, $cafilePath)
+ {
+ $this->_AuthorizeUrl = $serverUrl . "oauth2/authorize";
+ $this->_AccessTokenUrl = $serverUrl . "oauth2/token";
+ $this->_UserInfoUrl = $serverUrl . "oauth2/userinfo?schema=openid";
+ $this->_verifyPeer = $verifyPeer;
+ $this->_cafilePath = $cafilePath;
+ $this->CurlHeaders = array();
+ $this->ResponseCode = 0;
+ }
+
+ public function requestAccessCode($client_id, $redirect_url)
+ {
+ return ($this->_AuthorizeUrl . "?client_id=" . $client_id . "&response_type=code&scope=openid&redirect_uri=" . $redirect_url);
+ }
+
+ // Convert an authorization code from callback into an access token.
+ public function getAccessToken($client_id, $client_secret, $auth_code, $redirect_url)
+ {
+ // Init cUrl.
+ $r = $this->initCurl($this->_AccessTokenUrl);
+
+ // Add client ID and client secret to the headers.
+ curl_setopt($r, CURLOPT_HTTPHEADER, array(
+ "Authorization: Basic " . base64_encode($client_id . ":" . $client_secret),
+ ));
+
+ // Assemble POST parameters for the request.
+ $post_fields = "code=" . urlencode($auth_code) . "&grant_type=authorization_code&redirect_uri=" . $redirect_url;
+
+ // Obtain and return the access token from the response.
+ curl_setopt($r, CURLOPT_POST, true);
+ curl_setopt($r, CURLOPT_POSTFIELDS, $post_fields);
+
+ $response = curl_exec($r);
+ if ($response == false) {
+ die("curl_exec() failed. Error: " . curl_error($r));
+ }
+
+ //Parse JSON return object.
+ return json_decode($response);
+ }
+
+ // To get a refreshed access token
+ public function getRefreshedAccessToken($client_id, $client_secret, $refresh_token)
+ {
+ // Init cUrl.
+ $r = $this->initCurl($this->_AccessTokenUrl);
+
+ // Add client ID and client secret to the headers.
+ curl_setopt($r, CURLOPT_HTTPHEADER, array(
+ "Authorization: Basic " . base64_encode($client_id . ":" . $client_secret),
+ ));
+
+ // Assemble POST parameters for the request.
+ $post_fields = "refresh_token=" . urlencode($refresh_token) . "&grant_type=refresh_token";
+
+ // Obtain and return the access token from the response.
+ curl_setopt($r, CURLOPT_POST, true);
+ curl_setopt($r, CURLOPT_POSTFIELDS, $post_fields);
+
+ $response = curl_exec($r);
+ if ($response == false) {
+ die("curl_exec() failed. Error: " . curl_error($r));
+ }
+
+ //Parse JSON return object.
+ return json_decode($response);
+ }
+
+ private function initCurl($url)
+ {
+ $r = null;
+
+ if (($r = @curl_init($url)) == false) {
+ header("HTTP/1.1 500", true, 500);
+ die("Cannot initialize cUrl session. Is cUrl enabled for your PHP installation?");
+ }
+
+ curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
+
+ // Decode compressed responses.
+ curl_setopt($r, CURLOPT_ENCODING, 1);
+
+ curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->_verifyPeer);
+ curl_setopt($r, CURLOPT_CAINFO, $this->_cafilePath);
+
+ return ($r);
+ }
+
+
+ public function getUserProfile($access_token)
+ {
+ $r = $this->initCurl($this->_UserInfoUrl);
+
+ curl_setopt($r, CURLOPT_HTTPHEADER, array(
+ "Authorization: Bearer " . $access_token
+ ));
+
+ $response = curl_exec($r);
+ if ($response == false) {
+ die("curl_exec() failed. Error: " . curl_error($r));
+ }
+
+ //Parse JSON return object.
+ return json_decode($response);
+ }
+
+ // A generic function that executes an API request.
+ public function execRequest($url, $access_token, $get_params)
+ {
+ // Create request string.
+ $full_url = http_build_query($url, $get_params);
+
+ $r = $this->initCurl($full_url);
+
+ curl_setopt($r, CURLOPT_HTTPHEADER, array(
+ "Authorization: Basic " . base64_encode($access_token)
+ ));
+
+ $response = curl_exec($r);
+ if ($response == false) {
+ die("curl_exec() failed. Error: " . curl_error($r));
+ }
+
+ //Parse JSON return object.
+ return json_decode($response);
+ }
+}
+
+?>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/libraries/Wsis/Stubs/UserProfileManager.php
----------------------------------------------------------------------
diff --git a/app/libraries/Wsis/Stubs/UserProfileManager.php b/app/libraries/Wsis/Stubs/UserProfileManager.php
index eff2a35..6d5bcc8 100644
--- a/app/libraries/Wsis/Stubs/UserProfileManager.php
+++ b/app/libraries/Wsis/Stubs/UserProfileManager.php
@@ -38,6 +38,11 @@ class UserProfileManager {
$profile = new UserProfileDTO();
$fieldValues = array();
+ $usernameDTO = new UserFieldDTO();
+ $usernameDTO->claimUri = "http://wso2.org/claims/sub";
+ $usernameDTO->fieldValue = $username;
+ array_push($fieldValues, $usernameDTO);
+
$emailDTO = new UserFieldDTO();
$emailDTO->claimUri = "http://wso2.org/claims/emailaddress";
$emailDTO->fieldValue = $email;
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/libraries/Wsis/Wsis.php
----------------------------------------------------------------------
diff --git a/app/libraries/Wsis/Wsis.php b/app/libraries/Wsis/Wsis.php
index 456b02b..e3f8e26 100755
--- a/app/libraries/Wsis/Wsis.php
+++ b/app/libraries/Wsis/Wsis.php
@@ -6,6 +6,9 @@ use Wsis\Stubs\UserProfileManager;
use Wsis\Stubs\UserStoreManager;
use Wsis\Stubs\TenantManager;
use Wsis\Stubs\UserInformationRecoveryManager;
+use Wsis\Stubs\OAuthManager;
+
+use Illuminate\Support\Facades\Config;
class Wsis {
@@ -34,6 +37,12 @@ class Wsis {
private $userInfoRecoveryManager;
/**
+ * @var
+ * @access private
+ */
+ private $oauthManger;
+
+ /**
* @var string
* @access private
*/
@@ -87,6 +96,7 @@ class Wsis {
$this->tenantManager = new TenantManager($service_url, $parameters);
$this->userProfileManager = new UserProfileManager($service_url, $parameters);
$this->userInfoRecoveryManager = new UserInformationRecoveryManager($service_url, $parameters);
+ $this->oauthManger = new OAuthManager(Config::get('pga_config.wsis')['service-url'], $verify_peer, $cafile_path);
} catch (Exception $ex) {
throw new Exception("Unable to instantiate WSO2 IS client", 0, $ex);
}
@@ -142,6 +152,48 @@ class Wsis {
}
/**
+ * Function to get OAuth request code url
+ * @return mixed
+ */
+ public function getOAuthRequestCodeUrl(){
+ $url = $this->oauthManger->requestAccessCode(Config::get('pga_config.wsis')['oauth-client-key'],
+ Config::get('pga_config.wsis')['oauth-callback-url']);
+ return $url;
+ }
+
+ /**
+ * Function to get OAuth Access token
+ * @return string
+ */
+ public function getOAuthToken($code){
+ $response = $this->oauthManger->getAccessToken(Config::get('pga_config.wsis')['oauth-client-key'],
+ Config::get('pga_config.wsis')['oauth-client-secret'], $code,
+ Config::get('pga_config.wsis')['oauth-callback-url']);
+ return $response;
+ }
+
+ /**
+ * Method to get refreshed access token
+ * @param $refreshToken
+ * @return mixed
+ */
+ public function getRefreshedOAutheToken($refreshToken){
+ $response = $this->oauthManger->getRefreshedAccessToken(Config::get('pga_config.wsis')['oauth-client-key'],
+ Config::get('pga_config.wsis')['oauth-client-secret'], $refreshToken);
+ return $response;
+ }
+
+ /**
+ * Function to get user profile from OAuth token
+ * @param $token
+ */
+ public function getUserProfileFromOAuthToken($token){
+ $userProfile = $this->oauthManger->getUserProfile($token);
+ return array('username'=>$userProfile->sub, 'email'=>$userProfile->email, 'firstname'=>$userProfile->given_name,
+ 'lastname'=>$userProfile->family_name, 'roles'=>explode(",",$userProfile->roles));
+ }
+
+ /**
* Function to check whether username exists
*
* @param string $username
http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/cc830899/app/routes.php
----------------------------------------------------------------------
diff --git a/app/routes.php b/app/routes.php
index bb707a4..361291a 100755
--- a/app/routes.php
+++ b/app/routes.php
@@ -24,6 +24,8 @@ Route::get("login", "AccountController@loginView");
Route::post("login", "AccountController@loginSubmit");
+Route::get("callback-url", "AccountController@oauthCallback");
+
Route::get("logout", "AccountController@logout");
Route::get("forgot-password", "AccountController@forgotPassword");