You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2017/06/23 21:34:18 UTC

airavata-php-gateway git commit: AIRAVATA-2430 First attempt at implementing authentication options

Repository: airavata-php-gateway
Updated Branches:
  refs/heads/develop 41e471b02 -> 6882604f0


AIRAVATA-2430 First attempt at implementing authentication options


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

Branch: refs/heads/develop
Commit: 6882604f02ec272766a250f1e918252e6adf8e75
Parents: 41e471b
Author: Marcus Christie <ma...@iu.edu>
Authored: Fri Jun 23 17:09:55 2017 -0400
Committer: Marcus Christie <ma...@iu.edu>
Committed: Fri Jun 23 17:34:11 2017 -0400

----------------------------------------------------------------------
 app/config/pga_config.php.template      | 19 +++++++++
 app/controllers/AccountController.php   | 60 +++++++++++++++++++++-------
 app/controllers/AdminController.php     |  6 +--
 app/libraries/Keycloak/Keycloak.php     |  5 ++-
 app/views/account/login.blade.php       | 49 ++++-------------------
 app/views/partials/login-form.blade.php | 43 ++++++++++++++++++++
 6 files changed, 121 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/config/pga_config.php.template
----------------------------------------------------------------------
diff --git a/app/config/pga_config.php.template b/app/config/pga_config.php.template
index c293dc6..c20202c 100644
--- a/app/config/pga_config.php.template
+++ b/app/config/pga_config.php.template
@@ -57,6 +57,25 @@ return array(
         'oauth-client-secret' => 'KNTf_LPLuGBDbRVZwkrP_fF5z2Ea',
 
         /**
+         * Authentication options
+         */
+        'auth-options' => [
+            // Example of password based login
+            [
+                'oauth-grant-type' => 'password',
+                'name' => 'Airavata PHP Gateway',
+            ],
+            // Example of external identity provider login
+            [
+                'oauth-grant-type' => 'authorization_code',
+                // kc_idp_hint is used to skip Keycloak login screen and redirect immediately to this identity provider
+                // http://www.keycloak.org/docs/2.5/server_admin/topics/identity-broker/suggested.html
+                'oauth-authorize-url-extra-params' => 'kc_idp_hint=oidc',
+                'name' => 'CILogon',
+            ],
+        ],
+
+        /**
          * OAuth Grant Type (password or authorization_code)
          */
         'oauth-grant-type' => 'password',

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/controllers/AccountController.php
----------------------------------------------------------------------
diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php
index 425d71e..ddec450 100644
--- a/app/controllers/AccountController.php
+++ b/app/controllers/AccountController.php
@@ -62,14 +62,38 @@ class AccountController extends BaseController
 
     public function loginView()
     {
-        if(Config::get('pga_config.wsis')['oauth-grant-type'] == "authorization_code"){
-            $url = Keycloak::getOAuthRequestCodeUrl();
-            return Redirect::away($url);
-        }else{
-            if(CommonUtilities::id_in_session()){
-                return Redirect::to("home");
-            }else
-                return View::make('account/login');
+        // If user already logged in, redirect to home
+        if(CommonUtilities::id_in_session()){
+            return Redirect::to("home");
+        }
+
+        $auth_options = Config::get('pga_config.wsis')['auth-options'];
+        // Only support for one password option
+        $auth_password_option = null;
+        // Support for many external identity providers (authorization code auth flow)
+        $auth_code_options = array();
+        foreach ($auth_options as $auth_option) {
+            if ($auth_option["oauth-grant-type"] == "password") {
+                $auth_password_option = $auth_option;
+            } else if ($auth_option["oauth-grant-type"] == "authorization_code") {
+                $extra_params = isset($auth_option["oauth-authorize-url-extra-params"]) ? $auth_option["oauth-authorize-url-extra-params"] : null;
+                $auth_url = Keycloak::getOAuthRequestCodeUrl($extra_params);
+                $auth_option["auth_url"] = $auth_url;
+                $auth_code_options[] = $auth_option;
+            } else {
+                throw new Exception("Unrecognized oauth-grant-type: " . $auth_option["oauth-grant-type"]);
+            }
+        }
+
+        // If no username/password option and only one external identity
+        // provider, just redirect immediately
+        if ($auth_password_option == null && count($auth_code_options)) {
+            return Redirect::away($auth_code_options[0]["auth_url"]);
+        } else {
+            return View::make('account/login', array(
+                "auth_password_option" => $auth_password_option,
+                "auth_code_options" => $auth_code_options,
+            ));
         }
     }
 
@@ -169,16 +193,18 @@ class AccountController extends BaseController
         $userRoles = $userProfile['roles'];
         $userEmail = $userProfile['email'];
         $firstName = $userProfile['firstname'];
-        $lastName = $userProfile['lastName'];
+        $lastName = $userProfile['lastname'];
 
         # As a workaround to figuring out if the user is logging in for the first
         # time, if the user has no roles, assume they are logging in for the first
         # time and add them to the initial role
         if (!$this->hasAnyRoles($userRoles)){
-            $this->addUserToInitialRole($username);
+            IamAdminServicesUtilities::addInitialRoleToUser($username);
             # Reload the roles
             $userProfile = Keycloak::getUserProfileFromOAuthToken($accessToken);
             $userRoles = $userProfile['roles'];
+            # Notify admin
+            $this->sendAccountCreationNotification2Admin($username);
         }
 
         $authzToken = new Airavata\Model\Security\AuthzToken();
@@ -188,6 +214,7 @@ class AccountController extends BaseController
         Session::put('oauth-refresh-code',$refreshToken);
         Session::put('oauth-expiration-time',$expirationTime);
 
+        Session::put("roles", $userRoles);
         if (in_array(Config::get('pga_config.wsis')['admin-role-name'], $userRoles)) {
             Session::put("admin", true);
         }
@@ -204,7 +231,13 @@ class AccountController extends BaseController
         if(Session::get("admin") || Session::get("admin-read-only") || Session::get("authorized-user")){
             return $this->initializeWithAiravata($username, $userEmail, $firstName, $lastName);
         }
-        return Redirect::to("home");
+
+        if(Session::has("admin") || Session::has("admin-read-only")){
+
+            return Redirect::to("admin/dashboard");
+        }else{
+            return Redirect::to("account/dashboard");
+        }
     }
 
     private function hasAnyRoles($roles) {
@@ -444,10 +477,7 @@ class AccountController extends BaseController
     public function logout()
     {
        Session::flush();
-       if(Config::get('pga_config.wsis')['oauth-grant-type'] == "authorization_code"){
-           return Redirect::away(Keycloak::getOAuthLogoutUrl(URL::to("/")));
-       }
-       return Redirect::to('home');
+       return Redirect::away(Keycloak::getOAuthLogoutUrl(URL::to("/")));
     }
 
     public function allocationRequestView(){

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/controllers/AdminController.php
----------------------------------------------------------------------
diff --git a/app/controllers/AdminController.php b/app/controllers/AdminController.php
index d86f2b2..c75e0d4 100644
--- a/app/controllers/AdminController.php
+++ b/app/controllers/AdminController.php
@@ -334,13 +334,11 @@ class AdminController extends BaseController {
 		$mail->Subject = "Your user account (".$username.") privileges changed!";
 		$userProfile = Keycloak::getUserProfile($username);
 		$wsisConfig = Config::get('pga_config.wsis');
-		if( $wsisConfig['tenant-domain'] == "")
-			$username = $username;
-		else
-			$username = $username . "@" . $wsisConfig['tenant-domain'];
+		$tenant = $wsisConfig['tenant-domain'];
 
 		$str = "Please re-login into the portal to use new privileges" ."<br/><br/>";
 		$str = $str . "Gateway Portal: " . $_SERVER['SERVER_NAME'] ."<br/>";
+		$str = $str . "Tenant: " . $tenant . "<br/>";
 		$str = $str . "Username: " . $username ."<br/>";
 		$str = $str . "Name: " . $userProfile["firstname"] . " " . $userProfile["lastname"] . "<br/>";
 		$str = $str . "Email: " . $userProfile["email"] ;

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/libraries/Keycloak/Keycloak.php
----------------------------------------------------------------------
diff --git a/app/libraries/Keycloak/Keycloak.php b/app/libraries/Keycloak/Keycloak.php
index 951e14b..32b7020 100644
--- a/app/libraries/Keycloak/Keycloak.php
+++ b/app/libraries/Keycloak/Keycloak.php
@@ -100,7 +100,7 @@ class Keycloak {
         return $result;
      }
 
-    public function getOAuthRequestCodeUrl(){
+    public function getOAuthRequestCodeUrl($extra_params=null){
         $config = $this->getOpenIDConnectDiscoveryConfiguration();
         $authorization_endpoint = $config->authorization_endpoint;
 
@@ -108,6 +108,9 @@ class Keycloak {
         $url = $authorization_endpoint . '?response_type=code&client_id=' . urlencode($this->client_id)
             . '&redirect_uri=' . urlencode($this->callback_url)
             . '&scope=openid';
+        if ($extra_params != null) {
+            $url = $url . '&' . $extra_params;
+        }
         return $url;
     }
 

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/views/account/login.blade.php
----------------------------------------------------------------------
diff --git a/app/views/account/login.blade.php b/app/views/account/login.blade.php
index 1372f3e..5d79738 100755
--- a/app/views/account/login.blade.php
+++ b/app/views/account/login.blade.php
@@ -8,48 +8,15 @@
 
 <div class="col-md-offset-4 col-md-4">
 
-    <h3>
-        Login
-        <small>
-            <small> (Not registered? <a href="create">Create account</a>)</small>
-        </small>
-    </h3>
-
-
-    <form action="login" method="post" role="form">
-        @if( Session::has("invalid-credentials") )
-        {{ CommonUtilities::print_error_message('Invalid username or password. Please try again.') }}
-        @endif
-        @if( Session::has("update-password-required") )
-        <div class="alert alert-danger">
-            Your password has expired. Please <a href="{{URL::to('/') }}/forgot-password">reset your password</a>.
-        </div>
-        @endif
-        @if( Session::has("password-reset-success") )
-        <div class="alert alert-success">
-            {{{ Session::get("password-reset-success") }}}
-        </div>
+    @if (!empty($auth_password_option))
+        @include('partials/login-form', array("auth_name" => $auth_password_option["name"]))
+        @if (!empty($auth_code_options))
+            <h4>OR</h4>
         @endif
-        @if( Session::has("account-created-success") )
-        <div class="alert alert-success">
-            {{{ Session::get("account-created-success") }}}
-        </div>
-        @endif
-
-        <div class="form-group">
-            <label class="sr-only" for="username">Username</label>
-            <input type="text" class="form-control" name="username" placeholder="Username" autofocus required>
-        </div>
-        <div class="form-group">
-            <label class="sr-only" for="password">Password</label>
-            <input type="password" class="form-control" name="password" placeholder="Password" required>
-        </div>
-        <input name="Submit" type="submit" class="btn btn-primary btn-block" value="Sign in">
-    </form>
-
-    <small>
-        <small> (Forgot Password? Click <a href="{{URL::to('/') }}/forgot-password">here</a>)</small>
-    </small>
+    @endif
+    @foreach ($auth_code_options as $auth_code_option)
+        <a href="{{ $auth_code_option["auth_url"] }}" class="btn btn-primary">Sign in with {{{ $auth_code_option["name"] }}}</a>
+    @endforeach
 </div>
 
 @stop
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/airavata-php-gateway/blob/6882604f/app/views/partials/login-form.blade.php
----------------------------------------------------------------------
diff --git a/app/views/partials/login-form.blade.php b/app/views/partials/login-form.blade.php
new file mode 100644
index 0000000..304ffad
--- /dev/null
+++ b/app/views/partials/login-form.blade.php
@@ -0,0 +1,43 @@
+
+<h3>
+    Login with {{{ $auth_name }}}
+    <small>
+        <small> (Not registered? <a href="create">Create account</a>)</small>
+    </small>
+</h3>
+
+
+<form action="login" method="post" role="form">
+    @if( Session::has("invalid-credentials") )
+    {{ CommonUtilities::print_error_message('Invalid username or password. Please try again.') }}
+    @endif
+    @if( Session::has("update-password-required") )
+    <div class="alert alert-danger">
+        Your password has expired. Please <a href="{{URL::to('/') }}/forgot-password">reset your password</a>.
+    </div>
+    @endif
+    @if( Session::has("password-reset-success") )
+    <div class="alert alert-success">
+        {{{ Session::get("password-reset-success") }}}
+    </div>
+    @endif
+    @if( Session::has("account-created-success") )
+    <div class="alert alert-success">
+        {{{ Session::get("account-created-success") }}}
+    </div>
+    @endif
+
+    <div class="form-group">
+        <label class="sr-only" for="username">Username</label>
+        <input type="text" class="form-control" name="username" placeholder="Username" autofocus required>
+    </div>
+    <div class="form-group">
+        <label class="sr-only" for="password">Password</label>
+        <input type="password" class="form-control" name="password" placeholder="Password" required>
+    </div>
+    <input name="Submit" type="submit" class="btn btn-primary btn-block" value="Sign in with {{{ $auth_name }}}">
+</form>
+
+<small>
+    <small> (Forgot Password? Click <a href="{{URL::to('/') }}/forgot-password">here</a>)</small>
+</small>