airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From machris...@apache.org
Subject airavata-php-gateway git commit: AIRAVATA-2342 Retrieves user's realm roles using Keycloak API
Date Thu, 23 Mar 2017 14:02:05 GMT
Repository: airavata-php-gateway
Updated Branches:
  refs/heads/keycloak-integration 8b483beba -> c92cc2b9b


AIRAVATA-2342 Retrieves user's realm roles using Keycloak API


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/c92cc2b9
Tree: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/tree/c92cc2b9
Diff: http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/diff/c92cc2b9

Branch: refs/heads/keycloak-integration
Commit: c92cc2b9b8d583889c8875e429850c94ee2c348d
Parents: 8b483be
Author: Marcus Christie <machrist@iu.edu>
Authored: Thu Mar 23 09:59:45 2017 -0400
Committer: Marcus Christie <machrist@iu.edu>
Committed: Thu Mar 23 09:59:45 2017 -0400

----------------------------------------------------------------------
 app/controllers/AccountController.php           |  1 +
 app/filters.php                                 | 33 ++++----
 app/libraries/Keycloak/API/RoleMapper.php       | 83 ++++++++++++++++++++
 app/libraries/Keycloak/Keycloak.php             | 23 +++++-
 .../Keycloak/KeycloakServiceProvider.php        | 62 ++++++++-------
 5 files changed, 154 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c92cc2b9/app/controllers/AccountController.php
----------------------------------------------------------------------
diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php
index e98db86..1f69fcf 100644
--- a/app/controllers/AccountController.php
+++ b/app/controllers/AccountController.php
@@ -187,6 +187,7 @@ class AccountController extends BaseController
         $expirationTime = time() + $response->expires_in - 5; //5 seconds safe margin
 
         $userProfile = Keycloak::getUserProfileFromOAuthToken($accessToken);
+        Log::debug("userProfile", array($userProfile));
         $username = $userProfile['username'];
 
         $userRoles = $userProfile['roles'];

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c92cc2b9/app/filters.php
----------------------------------------------------------------------
diff --git a/app/filters.php b/app/filters.php
index 4dc9f38..a7d492a 100755
--- a/app/filters.php
+++ b/app/filters.php
@@ -20,22 +20,23 @@ App::before(function ($request) {
     if(Session::has('authz-token')){
         $currentTime = time();
         if($currentTime > Session::get('oauth-expiration-time')){
-            $response = WSIS::getRefreshedOAutheToken(Session::get('oauth-refresh-code'));
-            if(isset($response->access_token)){
-                $accessToken = $response->access_token;
-                $refreshToken = $response->refresh_token;
-                $expirationTime = time() + $response->expires_in - 300;
-                $authzToken = Session::get('authz-token');
-                $authzToken->accessToken = $accessToken;
-                $authzToken->claimsMap['gatewayID'] = Config::get('pga_config.airavata')['gateway-id'];
-                $authzToken->claimsMap['userName'] = Session::get('username');
-                Session::put('authz-token',$authzToken);
-                Session::put('oauth-refresh-code',$refreshToken);
-                Session::put('oauth-expiration-time',$expirationTime);
-            }else{
-                Session::flush();
-                return Redirect::to('home');
-            }
+            // TODO: implement for Keycloak
+            // $response = WSIS::getRefreshedOAutheToken(Session::get('oauth-refresh-code'));
+            // if(isset($response->access_token)){
+            //     $accessToken = $response->access_token;
+            //     $refreshToken = $response->refresh_token;
+            //     $expirationTime = time() + $response->expires_in - 300;
+            //     $authzToken = Session::get('authz-token');
+            //     $authzToken->accessToken = $accessToken;
+            //     $authzToken->claimsMap['gatewayID'] = Config::get('pga_config.airavata')['gateway-id'];
+            //     $authzToken->claimsMap['userName'] = Session::get('username');
+            //     Session::put('authz-token',$authzToken);
+            //     Session::put('oauth-refresh-code',$refreshToken);
+            //     Session::put('oauth-expiration-time',$expirationTime);
+            // }else{
+            //     Session::flush();
+            //     return Redirect::to('home');
+            // }
         }
     }
 });

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c92cc2b9/app/libraries/Keycloak/API/RoleMapper.php
----------------------------------------------------------------------
diff --git a/app/libraries/Keycloak/API/RoleMapper.php b/app/libraries/Keycloak/API/RoleMapper.php
new file mode 100644
index 0000000..2e6d170
--- /dev/null
+++ b/app/libraries/Keycloak/API/RoleMapper.php
@@ -0,0 +1,83 @@
+<?php
+namespace Keycloak\API;
+
+use Log;
+
+/**
+ * RoleMapper class
+ *
+ * This class provide an easy to use interface for
+ * the Keycloak RoleMapper REST API.
+ */
+class RoleMapper {
+
+    private $base_endpoint_url;
+    private $admin_username;
+    private $admin_password;
+    private $verify_peer;
+
+    public function __construct($base_endpoint_url, $admin_username, $admin_password, $verify_peer)
{
+        $this->base_endpoint_url = $base_endpoint_url;
+        $this->admin_username = $admin_username;
+        $this->admin_password = $admin_password;
+        $this->verify_peer = $verify_peer;
+    }
+
+    /**
+     * Get realm-level role mappings for a user
+     * GET /admin/realms/{realm}/users/{id}/role-mappings/realm
+     *
+     * Returns Array of RoleRepresentations
+     */
+    public function getRealmRoleMappingsForUser($realm, $user_id){
+
+        // curl -H "Authorization: bearer $access_token" https://149.165.156.62:8443/auth/admin/realms/airavata/users/2c9ad2c6-0212-4aef-a5fb-9df862578934/role-mappings/realm
+
+        // get access token for admin API
+        $access_token = $this->getAPIAccessToken();
+        $r = curl_init($this->base_endpoint_url . '/admin/realms/' . rawurlencode($realm)
. '/users/' . rawurlencode($user_id) . '/role-mappings/realm');
+        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($r, CURLOPT_ENCODING, 1);
+        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
+        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));
+        }
+        $result = json_decode($response);
+        // Log::debug("getRealmRoleMappingsForUser result", array($result));
+        return $result;
+    }
+
+    // TODO: factor this out into base class?
+    private function getAPIAccessToken() {
+
+        // http://www.keycloak.org/docs/2.5/server_development/topics/admin-rest-api.html
+        // curl -d client_id=admin-cli -d username=username \
+        //   -d "password=password" -d grant_type=password https://149.165.156.62:8443/auth/realms/master/protocol/openid-connect/token
+
+        $r = curl_init($this->base_endpoint_url . '/realms/master/protocol/openid-connect/token');
+        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($r, CURLOPT_ENCODING, 1);
+        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
+
+        // Assemble POST parameters for the request.
+        $post_fields = "client_id=admin-cli&username=" . urlencode($this->admin_username)
. "&password=" . urlencode($this->admin_password) . "&grant_type=password";
+
+        // 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));
+        }
+
+        $result = json_decode($response);
+        // Log::debug("API Access Token result", array($result));
+        return $result->access_token;
+    }
+}

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c92cc2b9/app/libraries/Keycloak/Keycloak.php
----------------------------------------------------------------------
diff --git a/app/libraries/Keycloak/Keycloak.php b/app/libraries/Keycloak/Keycloak.php
index c1c6f33..93ac99d 100644
--- a/app/libraries/Keycloak/Keycloak.php
+++ b/app/libraries/Keycloak/Keycloak.php
@@ -2,29 +2,37 @@
 
 namespace Keycloak;
 
+use Keycloak\API\RoleMapper;
+
 use Log;
 use Illuminate\Routing\UrlGenerator;
 use Illuminate\Support\Facades\Config;
 
 class Keycloak {
 
+    private $realm;
     private $openid_connect_discovery_url;
     private $client_id;
     private $client_secret;
     private $callback_url;
     private $verify_peer;
 
+    private $role_mapper;
+
     /**
      * Constructor
      *
      */
-    public function __construct($openid_connect_discovery_url, $client_id, $client_secret,
$callback_url, $verify_peer) {
+    public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret,
$callback_url, $verify_peer, $base_endpoint_url, $admin_username, $admin_password) {
 
+        $this->realm = $realm;
         $this->openid_connect_discovery_url = $openid_connect_discovery_url;
         $this->client_id = $client_id;
         $this->client_secret = $client_secret;
         $this->callback_url = $callback_url;
         $this->verify_peer = $verify_peer;
+
+        $this->role_mapper = new RoleMapper($base_endpoint_url, $admin_username, $admin_password,
$verify_peer);
     }
 
     public function getOAuthRequestCodeUrl(){
@@ -100,8 +108,14 @@ class Keycloak {
         $firstname = $userinfo->given_name;
         $lastname = $userinfo->family_name;
         $email = $userinfo->email;
-        // TODO: get roles from Keycloak API
-        return array('username'=>$username, 'firstname'=>$firstname, 'lastname'=>$lastname,
'email'=>$email, 'roles'=>array());
+
+        // get roles from Keycloak API
+        $role_mappings = $this->role_mapper->getRealmRoleMappingsForUser($this->realm,
$userinfo->sub);
+        $roles = [];
+        foreach ($role_mappings as $role_mapping) {
+            $roles[] = $role_mapping->name;
+        }
+        return array('username'=>$username, 'firstname'=>$firstname, 'lastname'=>$lastname,
'email'=>$email, 'roles'=>$roles);
     }
 
     private function getOpenIDConnectDiscoveryConfiguration() {
@@ -114,6 +128,9 @@ class Keycloak {
         curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
 
         $result = curl_exec($r);
+        if ($result == false) {
+            die("curl_exec() failed. Error: " . curl_error($r));
+        }
 
         $json = json_decode($result);
 

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/c92cc2b9/app/libraries/Keycloak/KeycloakServiceProvider.php
----------------------------------------------------------------------
diff --git a/app/libraries/Keycloak/KeycloakServiceProvider.php b/app/libraries/Keycloak/KeycloakServiceProvider.php
index b7e033c..b8bfcbb 100644
--- a/app/libraries/Keycloak/KeycloakServiceProvider.php
+++ b/app/libraries/Keycloak/KeycloakServiceProvider.php
@@ -5,40 +5,44 @@ use Illuminate\Support\Facades\Config;
 
 class KeycloakServiceProvider extends ServiceProvider {
 
-	/**
-	 * Indicates if loading of the provider is deferred.
-	 *
-	 * @var bool
-	 */
-	protected $defer = false;
+    /**
+    * Indicates if loading of the provider is deferred.
+    *
+    * @var bool
+    */
+    protected $defer = false;
 
     /**
-     * Bootstrap the application events.
-     *
-     * @return void
-     */
+    * Bootstrap the application events.
+    *
+    * @return void
+    */
     public function boot()
     {
         $this->package('keycloak/keycloak');
     }
 
-	/**
-	 * Register the service provider.
-	 *
-	 * @return void
-	 */
-	public function register()
-	{
+    /**
+    * Register the service provider.
+    *
+    * @return void
+    */
+    public function register()
+    {
         //registering service provider
         $this->app['keycloak'] = $this->app->share(function($app)
         {
             $identityServerConfig = Config::get('pga_config.wsis');
             return new Keycloak(
+                $identityServerConfig['tenant-domain'],
                 $identityServerConfig['openid-connect-discovery-url'],
                 $identityServerConfig['oauth-client-key'],
                 $identityServerConfig['oauth-client-secret'],
                 $identityServerConfig['oauth-callback-url'],
-                $identityServerConfig['verify-peer']
+                $identityServerConfig['verify-peer'],
+                $identityServerConfig['service-url'],
+                $identityServerConfig['admin-username'],
+                $identityServerConfig['admin-password']
             );
         });
 
@@ -48,16 +52,16 @@ class KeycloakServiceProvider extends ServiceProvider {
             $loader = \Illuminate\Foundation\AliasLoader::getInstance();
             $loader->alias('Keycloak', 'Keycloak\Facades\Keycloak');
         });
-	}
-
-	/**
-	 * Get the services provided by the provider.
-	 *
-	 * @return array
-	 */
-	public function provides()
-	{
-		return array('wsis');
-	}
+    }
+
+    /**
+    * Get the services provided by the provider.
+    *
+    * @return array
+    */
+    public function provides()
+    {
+        return array('keycloak');
+    }
 
 }


Mime
View raw message