Blob Blame History Raw
From 32aecffb5517dfc3b3674a8f7db418456bd877ed Mon Sep 17 00:00:00 2001
From: Giuseppe Castagno <giuseppe.castagno@acca-esse.eu>
Date: Sat, 30 Apr 2016 14:29:56 +0200
Subject: [PATCH 1/5] Add new Google Drive OAuth 2.0 login procedure.

The new Google login sequence uses two html pages: first page for user email
the second page for password.

The older sequence used only one page for both user email and user password.
---
 src/libcmis/oauth2-providers.cxx | 67 +++++++++++++++++++++++++++++++---------
 1 file changed, 52 insertions(+), 15 deletions(-)

diff --git a/src/libcmis/oauth2-providers.cxx b/src/libcmis/oauth2-providers.cxx
index 5e7f3bf..68a6aa5 100644
--- a/src/libcmis/oauth2-providers.cxx
+++ b/src/libcmis/oauth2-providers.cxx
@@ -37,11 +37,28 @@ using namespace std;
 string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUrl,
                                       const string& username, const string& password )
 {
+    /* This member function implements 'Google OAuth 2.0'
+     *
+     * The interaction is carried out by libcmis, with no web browser involved.
+     *
+     * Normal sequence (without 2FA) is:
+     * 1) a get to activate login page
+     *    receive first login page, html format
+     * 2) subsequent post to sent email
+     *    receive html page for password input
+     * 3) subsequent post to send password
+     *    receive html page for application consent
+     * 4) subsequent post to send a consent for the application
+     *    receive a single-use authorization code
+     *    this code is returned as a string
+     */
+
     static const string CONTENT_TYPE( "application/x-www-form-urlencoded" );
     // STEP 1: Log in
     string res;
     try
     {
+        // send the first get, receive the html login page
         res = session->httpGetRequest( authUrl )->getStream( )->str( );
     }
     catch ( const CurlException& e )
@@ -49,20 +66,39 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
         return string( );
     }
 
-    string loginPost, loginLink; 
-    if ( !parseResponse( res.c_str( ), loginPost, loginLink ) ) 
+    string loginEmailPost, loginEmailLink;
+    if ( !parseResponse( res.c_str( ), loginEmailPost, loginEmailLink ) )
         return string( );
-    
-    loginPost += "Email=";  
-    loginPost += string( username );
-    loginPost += "&Passwd=";
-    loginPost += string( password );
-    
-    istringstream loginIs( loginPost );
-    string loginRes;
-    try 
+
+    loginEmailPost += "Email=";
+    loginEmailPost += string( username );
+
+    istringstream loginEmailIs( loginEmailPost );
+    string loginEmailRes;
+    try
+    {
+        // send a post with user email, receive the html page for password input
+        loginEmailRes = session->httpPostRequest ( loginEmailLink, loginEmailIs, CONTENT_TYPE )
+                        ->getStream( )->str( );
+    }
+    catch ( const CurlException& e )
+    {
+        return string( );
+    }
+
+    string loginPasswdPost, loginPasswdLink;
+    if ( !parseResponse( loginEmailRes.c_str( ), loginPasswdPost, loginPasswdLink ) )
+        return string( );
+
+    loginPasswdPost += "Passwd=";
+    loginPasswdPost += string( password );
+
+    istringstream loginPasswdIs( loginPasswdPost );
+    string loginPasswdRes;
+    try
     {
-        loginRes = session->httpPostRequest ( loginLink, loginIs, CONTENT_TYPE )
+        // send a post with user password, receive the application consent page
+        loginPasswdRes = session->httpPostRequest ( loginPasswdLink, loginPasswdIs, CONTENT_TYPE )
                         ->getStream( )->str( );
     }
     catch ( const CurlException& e )
@@ -71,8 +107,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
     }
 
     // STEP 2: allow libcmis to access google drive
-    string approvalPost, approvalLink; 
-    if ( !parseResponse( loginRes. c_str( ), approvalPost, approvalLink) )
+    string approvalPost, approvalLink;
+    if ( !parseResponse( loginPasswdRes. c_str( ), approvalPost, approvalLink) )
         return string( );
     approvalPost += "submit_access=true";
 
@@ -80,7 +116,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
     string approvalRes;
     try
     {
-        approvalRes = session->httpPostRequest ( approvalLink, approvalIs, 
+        // send a post with application consent
+        approvalRes = session->httpPostRequest ( approvalLink, approvalIs,
                             CONTENT_TYPE) ->getStream( )->str( );
     }
     catch ( const CurlException& e )
-- 
2.7.4