Bypass login page if no user input is required.
authorCindy Cicalese <cicalese@mitre.org>
Mon, 26 Sep 2016 19:35:22 +0000 (15:35 -0400)
committerCicalese <cicalese@mitre.org>
Tue, 22 Nov 2016 14:10:20 +0000 (14:10 +0000)
Bug: T141474
Bug: T110464
Change-Id: I9588a2b87a423f614fc5d2e771ad1ac7279ebd0b

includes/auth/AuthenticationRequest.php
includes/auth/RememberMeAuthenticationRequest.php
includes/specialpage/LoginSignupSpecialPage.php

index ff4569b..7fc362a 100644 (file)
@@ -108,6 +108,10 @@ abstract class AuthenticationRequest {
         *  - optional: (bool) If set and truthy, the field may be left empty
         *  - sensitive: (bool) If set and truthy, the field is considered sensitive. Code using the
         *      request should avoid exposing the value of the field.
+        *  - skippable: (bool) If set and truthy, the client is free to hide this
+        *      field from the user to streamline the workflow. If all fields are
+        *      skippable (except possibly a single button), no user interaction is
+        *      required at all.
         *
         * All AuthenticationRequests are populated from the same data, so most of the time you'll
         * want to prefix fields names with something unique to the extension/provider (although
index d487e31..06060b1 100644 (file)
@@ -58,6 +58,7 @@ class RememberMeAuthenticationRequest extends AuthenticationRequest {
                                'label' => wfMessage( 'userlogin-remembermypassword' )->numParams( $expirationDays ),
                                'help' => wfMessage( 'authmanager-userlogin-remembermypassword-help' ),
                                'optional' => true,
+                               'skippable' => true,
                        ]
                ];
        }
index bf83e7b..d3cd577 100644 (file)
@@ -294,6 +294,14 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                        return;
                }
 
+               if ( $this->canBypassForm( $button_name ) ) {
+                       $this->setRequest( [], true );
+                       $this->getRequest()->setVal( $this->getTokenName(), $this->getToken() );
+                       if ( $button_name ) {
+                               $this->getRequest()->setVal( $button_name, true );
+                       }
+               }
+
                $status = $this->trySubmit();
 
                if ( !$status || !$status->isGood() ) {
@@ -366,6 +374,46 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                }
        }
 
+       /**
+        * Determine if the login form can be bypassed. This will be the case when no more than one
+        * button is present and no other user input fields that are not marked as 'skippable' are
+        * present. If the login form were not bypassed, the user would be presented with a
+        * superfluous page on which they must press the single button to proceed with login.
+        * Not only does this cause an additional mouse click and page load, it confuses users,
+        * especially since there are a help link and forgotten password link that are
+        * provided on the login page that do not apply to this situation.
+        *
+        * @param string|null &$button_name if the form has a single button, returns
+        *   the name of the button; otherwise, returns null
+        * @return bool
+        */
+       private function canBypassForm( &$button_name ) {
+               $button_name = null;
+               if ( $this->isContinued() ) {
+                       return false;
+               }
+               $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
+               foreach ( $fields as $fieldname => $field ) {
+                       if ( !isset( $field['type'] ) ) {
+                               return false;
+                       }
+                       if ( !empty( $field['skippable'] ) ) {
+                               continue;
+                       }
+                       if ( $field['type'] === 'button' ) {
+                               if ( $button_name !== null ) {
+                                       $button_name = null;
+                                       return false;
+                               } else {
+                                       $button_name = $fieldname;
+                               }
+                       } elseif ( $field['type'] !== 'null' ) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
        /**
         * Show the success page.
         *