Net::Google::AuthSub login failed with new Google

2020-02-08 20:59发布

This code in Perl was working for years and now my Spreadsheets logins failed, when I logged into my account I noticed switch to a new Drive version. Probably some authentication methods deprecated?

my $auth = Net::Google::AuthSub->new;
my $response = $auth->login('LOGIN@gmail.com', 'PASS');
if ($response->is_success) {
     print "Hurrah! Logged in\n";
} else {
     die "Login failed: ".$response->error."\n";
}

The result is:

Login failed: 

And the code:

use Net::Google::Spreadsheets;
my $service = Net::Google::Spreadsheets->new(
 username => 'LOGIN@gmail.com',
 password => 'PASS'
);

The result is:

Net::Google::AuthSub login failed at /usr/local/share/perl/5.18.2/Net/Google/Spreadsheets.pm line 42.

As suggested somewhere I tried to skip SSL certificate checking with:

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

but this doesn't help too. What can I do to make it work? Thanks.

3条回答
贪生不怕死
2楼-- · 2020-02-08 21:43

That code above absolutely would not work for me. After looking around for several hours, reading the documentation and trying different things I finally ran across some code that worked. 90% of it is the same but it was the missing 10% and the accompanying explanations that made all the difference.

http://pastebin.com/8LeMyLW4

(Originally from this Stack Overflow post: Authenticating in a Google sheets application)

#!/usr/bin/perl

# Code to get a web-based token that can be stored 
# and used later to authorize our spreadsheet access. 

# Based on code from https://gist.github.com/hexaddikt/6738162

#-------------------------------------------------------------------

# To use this code:

# 1. Edit the lines below to put in your own
#    client_id and client_secret from Google. 
# 2. Run this script and follow the directions on 
#    the screen, which will give step you 
#    through the following steps:
# 3. Copy the URL printed out, and paste 
#    the URL in a browser to load the page. 
# 4. On the resulting page, click OK (possibly
#    after being asked to log in to your Google 
#    account). 
# 5. You will be redirected to a page that provides 
#    a code that you should copy and paste back into the 
#    terminal window, so this script can exchange it for
#    an access token from Google, and store the token.  
#    That will be the the token the other spreadsheet access
#    code can use. 


use Net::Google::DataAPI::Auth::OAuth2;
use Net::Google::Spreadsheets;
use Storable; #to save and restore token for future use
use Term::Prompt;

# Provide the filename in which we will store the access 
# token.  This file will also need to be readable by the 
# other script that accesses the spreadsheet and parses
# the contents. 

my $session_filename = "stored_google_access.session";


# Code for accessing your Google account.  The required client_id
# and client_secret can be found in your Google Developer's console 
# page, as described in the detailed instruction document.  This 
# block of code will also need to appear in the other script that
# accesses the spreadsheet. 

# Be sure to edit the lines below to fill in your correct client 
# id and client secret!
my $oauth2 = Net::Google::DataAPI::Auth::OAuth2->new(
    client_id => 'your_client_id.apps.googleusercontent.com',
    client_secret => 'your_client_secret',
    scope => ['http://spreadsheets.google.com/feeds/'],
    redirect_uri => 'https://developers.google.com/oauthplayground',
                             );
# We need to set these parameters this way in order to ensure 
# that we get not only an access token, but also a refresh token
# that can be used to update it as needed. 
my $url = $oauth2->authorize_url(access_type => 'offline',
                 approval_prompt => 'force');

# Give the user instructions on what to do:
print <<END

The following URL can be used to obtain an access token from
Google.  

1. Copy the URL and paste it into a browser.  

2.  You may be asked to log into your Google account if you 
were not logged in already in that browser.  If so, go 
ahead and log in to whatever account you want to have 
access to the Google doc. 

3. On the next page, click "Accept" when asked to grant access. 

4.  You will then be redirected to a page with a box in the 
left-hand column labeled  "Authorization code".  
Copy the code in that box and come back here. 

Here is the URL to paste in your browser to get the code:

$url

END
    ;

# Here is where we get the code from the user:
my $code = prompt('x', 'Paste the code obtained at the above URL here: ', '', ''); 

# Exchange the code for an access token:
my $token = $oauth2->get_access_token($code) or die;

# If we get to here, it worked!  Report success: 
print "nToken obtained successfully!n";
print "Here are the token contents (just FYI):nn";
print $token->to_string, "n";

# Save the token for future use:
my $session = $token->session_freeze;
store($session, $session_filename);

print <<END2

Token successfully stored in file $session_filename.

Use that filename in your spreadsheet-access script to 
load the token as needed for access to the spreadsheet data. 

END2
    ;

use Net::Google::Spreadsheets;
use Net::Google::DataAPI::Auth::OAuth2;
use Net::OAuth2::AccessToken;
use Storable;

# Authentication code based on example from gist at 
#  https://gist.github.com/hexaddikt/6738247

# Get the token that we saved previously in order to authenticate:
my $session_filename = "stored_google_access.session";


# Be sure to edit the lines below to fill in your correct client 
# id and client secret!
my $oauth2 = Net::Google::DataAPI::Auth::OAuth2->new(
    client_id => 'your_client_id.apps.googleusercontent.com',
    client_secret => 'your_client_secret',
    scope => ['http://spreadsheets.google.com/feeds/'],
    redirect_uri => 'https://developers.google.com/oauthplayground',
                             );

# Deserialize the file so we can thaw the session and reuse the refresh token
my $session = retrieve($sessionfile);

my $restored_token = Net::OAuth2::AccessToken->session_thaw($session,
                                auto_refresh => 1,
                                profile => $oauth2->oauth2_webserver,
                                );

$oauth2->access_token($restored_token);
# Now we can use this token to access the spreadsheets 
# in our account:
my $service = Net::Google::Spreadsheets->new(
                         auth => $oauth2);
查看更多
来,给爷笑一个
3楼-- · 2020-02-08 21:46

Thanks for this - very helpful. One addition is that the code in the original poster's answer will generate a token that expires in an hour. If you want to keep using it, you need to be sure to formulate the initial request so that it generates not only the access token, but also the refresh token. To get this, change the initial

my $url = $oauth2->authorize_url();

to

my $url = $oauth2->authorize_url(access_type => 'offline',
                                 approval_prompt => 'force');

Then the returned token will have the necessary refresh_token included.

查看更多
Deceive 欺骗
4楼-- · 2020-02-08 21:57

I have to answer my question as I was happy to find a solution. Google changed their authentication algorithm, so we have to use OAuth 2.0. You will need to create Credentials at: https://console.developers.google.com/

APIs & auth -> Credentials -> OAuth -> Client ID -> Installed application -> Other

and enable your API i.e.: APIs & auth -> APIs -> Google Apps APIs > Drive API

The following code works fine:

use Net::Google::DataAPI::Auth::OAuth2;
use Net::Google::Spreadsheets;
use Storable; #to save and restore token for future use

my $oauth2 = Net::Google::DataAPI::Auth::OAuth2->new(
    client_id => 'ID.apps.googleusercontent.com',
    client_secret => 'SECRET',
    scope => ['http://spreadsheets.google.com/feeds/'],
  );
#you can skip URL if you have your token saved and continue from RESTORE label

my $url = $oauth2->authorize_url();
#you will need to put code here and receive token
print "OAuth URL, get code: $url\n";
use Term::Prompt;
my $code = prompt('x', 'paste the code: ', '', ''); 
my $token = $oauth2->get_access_token($code) or die;

#save token for future use
my $session = $token->session_freeze;
store($session, 'google_spreadsheet.session');

RESTORE:
my $session = retrieve('google_spreadsheet.session');
my $restored_token = Net::OAuth2::AccessToken->session_thaw($session,
    auto_refresh => 1,
    profile => $oauth2->oauth2_webserver,
);
$oauth2->access_token($restored_token);

my $service = Net::Google::Spreadsheets->new(auth => $oauth2);
# and then as before..

Save and restore token session example found at https://gist.github.com/hexaddikt

查看更多
登录 后发表回答