mirror of https://github.com/vitalif/grive2
Implement Google installed app loopback redirect OAuth flow
parent
6901fbb169
commit
8bfa97c709
16
README.md
16
README.md
|
@ -39,12 +39,12 @@ grive -a
|
|||
|
||||
A URL should be printed. Go to the link. You will need to login to your Google
|
||||
account if you haven't done so. After granting the permission to Grive, the
|
||||
browser will show you an authenication code. Copy-and-paste that to the
|
||||
standard input of Grive.
|
||||
authorization code will be forwarded to the Grive application and you will be
|
||||
redirected to a localhost web page confirming the authorization.
|
||||
|
||||
If everything works fine, Grive will create .grive and .grive_state files in your
|
||||
current directory. It will also start downloading files from your Google Drive to
|
||||
your current directory.
|
||||
If everything works fine, Grive will create .grive and .grive\_state files in
|
||||
your current directory. It will also start downloading files from your Google
|
||||
Drive to your current directory.
|
||||
|
||||
To resync the direcory, run `grive` in the folder.
|
||||
|
||||
|
@ -154,6 +154,7 @@ You need the following libraries:
|
|||
- libgcrypt
|
||||
- Boost (Boost filesystem, program_options, regex, unit_test_framework and system are required)
|
||||
- expat
|
||||
- libcpprest-dev
|
||||
|
||||
There are also some optional dependencies:
|
||||
- CppUnit (for unit tests)
|
||||
|
@ -165,16 +166,17 @@ these packages:
|
|||
|
||||
sudo apt-get install git cmake build-essential libgcrypt20-dev libyajl-dev \
|
||||
libboost-all-dev libcurl4-openssl-dev libexpat1-dev libcppunit-dev binutils-dev \
|
||||
debhelper zlib1g-dev dpkg-dev pkg-config
|
||||
debhelper zlib1g-dev dpkg-dev pkg-config libcpprest-dev
|
||||
|
||||
Fedora:
|
||||
|
||||
sudo dnf install git cmake libgcrypt-devel gcc-c++ libstdc++ yajl-devel boost-devel libcurl-devel expat-devel binutils zlib
|
||||
sudo dnf install git cmake libgcrypt-devel gcc-c++ libstdc++ yajl-devel boost-devel libcurl-devel expat-devel binutils zlib cpprest-devel
|
||||
|
||||
|
||||
FreeBSD:
|
||||
|
||||
pkg install git cmake boost-libs yajl libgcrypt pkgconf cppunit libbfd
|
||||
cpprestsdk
|
||||
|
||||
### Build Debian packages
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ Source: grive2
|
|||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Vitaliy Filippov <vitalif@mail.ru>
|
||||
Build-Depends: debhelper, cmake, pkg-config, zlib1g-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libboost-filesystem-dev, libboost-program-options-dev, libboost-test-dev, libboost-regex-dev, libexpat1-dev, libgcrypt-dev, libyajl-dev
|
||||
Build-Depends: debhelper, cmake, pkg-config, zlib1g-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libboost-filesystem-dev, libboost-program-options-dev, libboost-test-dev, libboost-regex-dev, libexpat1-dev, libgcrypt-dev, libyajl-dev, libcpprest-dev
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://yourcmc.ru/wiki/Grive2
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
project( grive )
|
||||
|
||||
find_package(Boost COMPONENTS program_options REQUIRED)
|
||||
find_package(cpprestsdk REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
include_directories(
|
||||
${grive_SOURCE_DIR}/../libgrive/src
|
||||
|
@ -18,6 +20,8 @@ add_executable( grive_executable
|
|||
|
||||
target_link_libraries( grive_executable
|
||||
grive
|
||||
OpenSSL::Crypto
|
||||
cpprestsdk::cpprest
|
||||
)
|
||||
|
||||
set(DEFAULT_APP_ID "615557989097-i93d4d1ojpen0m0dso18ldr6orjkidgf.apps.googleusercontent.com")
|
||||
|
|
|
@ -45,13 +45,21 @@
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <future>
|
||||
|
||||
#include <cpprest/http_listener.h>
|
||||
#include <cpprest/uri.h>
|
||||
|
||||
const std::string default_id = APP_ID ;
|
||||
const std::string default_secret = APP_SECRET ;
|
||||
const std::string default_redirect_uri = "http://localhost:9898" ;
|
||||
|
||||
using namespace gr ;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
using namespace web::http::experimental::listener;
|
||||
using namespace web::http;
|
||||
|
||||
// libgcrypt insist this to be done in application, not library
|
||||
void InitGCrypt()
|
||||
{
|
||||
|
@ -101,6 +109,63 @@ void InitLog( const po::variables_map& vm )
|
|||
LogBase::Inst( comp_log.release() ) ;
|
||||
}
|
||||
|
||||
// AuthCode reads an authorization code from the "code" query parameter passed
|
||||
// via client-side redirect to the redirect_uri specified in uri
|
||||
std::string AuthCode( std::string uri )
|
||||
{
|
||||
// Set up an HTTP listener that is waiting for Google
|
||||
// to hit the specified local URI with the authorization
|
||||
// code response
|
||||
http_listener listener(uri);
|
||||
listener.
|
||||
open().
|
||||
then([uri]() {
|
||||
std::cout
|
||||
<< "\n"
|
||||
<< "Listening on " << uri << " for an authorization code from Google"
|
||||
<< std::endl;
|
||||
}).
|
||||
wait();
|
||||
|
||||
// Set up a promise to read the authorization code from the
|
||||
// redirect
|
||||
std::promise<std::string> result;
|
||||
listener.support(methods::GET, [&result] (http_request req) {
|
||||
// Extract the "code" query parameter
|
||||
auto params = uri::split_query(req.request_uri().query());
|
||||
auto found_code = params.find("code");
|
||||
|
||||
// If auth code is missing, respond with basic web page
|
||||
// containing error message
|
||||
if (found_code == params.end()) {
|
||||
std::cout
|
||||
<< "request received without auth code: " << req.absolute_uri().to_string()
|
||||
<< std::endl;
|
||||
auto msg =
|
||||
"grive2 authorization code redirect missing 'code' query parameter.\n\n"
|
||||
"Try the auth flow again.";
|
||||
req.reply(status_codes::BadRequest, msg);
|
||||
}
|
||||
|
||||
// If found, respond with basic web page telling user to close
|
||||
// the window and pass the actual code back to the rest of the
|
||||
// application
|
||||
auto code = found_code->second;
|
||||
std::cout << "received authorization code" << std::endl;
|
||||
auto msg = "Received grive2 authorization code. You may now close this window.";
|
||||
req.reply(status_codes::OK, msg).wait();
|
||||
result.set_value(code);
|
||||
});
|
||||
|
||||
// Block until we receive an auth code
|
||||
std::string code = result.get_future().get();
|
||||
|
||||
// Having received the code, block until listener is shut down
|
||||
listener.close().wait();
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int Main( int argc, char **argv )
|
||||
{
|
||||
InitGCrypt() ;
|
||||
|
@ -115,6 +180,7 @@ int Main( int argc, char **argv )
|
|||
( "secret,e", po::value<std::string>(), "Authentication secret")
|
||||
( "print-url", "Only print url for request")
|
||||
( "path,p", po::value<std::string>(), "Path to working copy root")
|
||||
( "redirect-uri", po::value<std::string>(), "local URI on which to listen for auth redirect")
|
||||
( "dir,s", po::value<std::string>(), "Single subdirectory to sync")
|
||||
( "verbose,V", "Verbose mode. Enable more messages than normal.")
|
||||
( "log-http", po::value<std::string>(), "Log all HTTP responses in this file for debugging.")
|
||||
|
@ -183,6 +249,9 @@ int Main( int argc, char **argv )
|
|||
std::string secret = vm.count( "secret" ) > 0
|
||||
? vm["secret"].as<std::string>()
|
||||
: default_secret ;
|
||||
std::string uri = vm.count( "redirect-uri" ) > 0
|
||||
? vm["redirect-uri"].as<std::string>()
|
||||
: default_redirect_uri ;
|
||||
|
||||
OAuth2 token( http.get(), id, secret ) ;
|
||||
|
||||
|
@ -194,16 +263,11 @@ int Main( int argc, char **argv )
|
|||
|
||||
std::cout
|
||||
<< "-----------------------\n"
|
||||
<< "Please go to this URL and get an authentication code:\n\n"
|
||||
<< "Please go to this URL to authorize the app:\n\n"
|
||||
<< token.MakeAuthURL()
|
||||
<< std::endl ;
|
||||
|
||||
std::cout
|
||||
<< "\n-----------------------\n"
|
||||
<< "Please input the authentication code here: " << std::endl ;
|
||||
std::string code ;
|
||||
std::cin >> code ;
|
||||
|
||||
|
||||
std::string code = AuthCode(uri);
|
||||
token.Auth( code ) ;
|
||||
|
||||
// save to config
|
||||
|
|
|
@ -36,6 +36,7 @@ BuildRequires: expat-devel
|
|||
BuildRequires: openssl-devel
|
||||
BuildRequires: boost-devel
|
||||
BuildRequires: binutils-devel
|
||||
BuildRequires: cpprest-devel
|
||||
|
||||
%description
|
||||
The purpose of this project is to provide an independent implementation
|
||||
|
|
Loading…
Reference in New Issue