Ruby google_drive gem oAuth2 saving

2019-02-07 11:13发布

So before the update there was a simple way to log into google drive and manipulate your google docs - with ruby.

Before you were able to log into your google drive with this.

require 'google_drive'
$session = GoogleDrive.login("email@gmail.com", "password")

But now you get the warning message:

WARNING: GoogleDrive.login is deprecated and will be removed in the next version. Use GoogleDrive.login_with_oauth instead.

So I went to the git hub page to see how google wants us to use their services with high level languages, and found out they want us to use oAuth2. Like so.

require 'google/api_client'
require 'google_drive'

client = Google::APIClient.new(
  :application_name => 'Example Ruby application',
  :application_version => '1.0.0'
)
auth = client.authorization
auth.client_id = "YOUR CLIENT ID"
auth.client_secret = "YOUR CLIENT SECRET"
auth.scope =
    "https://www.googleapis.com/auth/drive " +
    "https://spreadsheets.google.com/feeds/"
auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
print("1. Open this page:\n%s\n\n" % auth.authorization_uri)
print("2. Enter the authorization code shown in the page: ")
auth.code = $stdin.gets.chomp
auth.fetch_access_token!
access_token = auth.access_token

$session = GoogleDrive.login_with_oauth(access_token)

This is fine and all but I can't save the auth variable. I would like to hard code this in the script so I don't have to keep going to google to get a new access_token.

So I've tried to get the access_token and adding it to the script like so.

require 'google/api_client'
require 'google_drive'

client = Google::APIClient.new
access_token = "TokenFromGoogleHardCoded"

$session = GoogleDrive.login_with_oauth(access_token)

# $session doesn't connect

I'm not sure I'm attacking this problem in the correct manor. I would like to save the complete auth variable and hard code it in my scripts.

4条回答
放我归山
2楼-- · 2019-02-07 11:32

Although Duck1337's answer will work, you don't actually need to call auth.refresh! with google_drive 1.0.*.

All you need to do is save the refresh_token from when you provided the authorization code in the first instance and then always pass that before calling auth.fetch_access_token! and the tokens will automatically get refreshed.

Below is what I use to login. I use Environment variables rather that code constants, so I can add them to Heroku Config Vars and also to keep sensitive data out of the code.

client = Google::APIClient.new
    auth = client.authorization
    auth.client_id = ENV['GOOGLE_CLIENT_ID']
    auth.client_secret = ENV['GOOGLE_CLIENT_SECRET']
    auth.scope = [
        "https://www.googleapis.com/auth/drive",
        "https://spreadsheets.google.com/feeds/"
    ]
    auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"

    if ENV['GOOGLE_REFRESH_TOKEN'] == "0" # Always start with 0 in your .env file, e.g. GOOGLE_REFRESH_TOKEN = 0
      puts("1. Open this page:\n%s\n\n" % auth.authorization_uri)
      puts("2. Enter the authorization code shown in the page: ")
      auth.code = $stdin.gets.chomp
    end if

    auth.refresh_token = ENV['GOOGLE_REFRESH_TOKEN'] #this will be 0 the first time around, but that's OK
    auth.fetch_access_token!

    if ENV['GOOGLE_REFRESH_TOKEN'] == "0"   
      puts("3. Save this refresh token:\n%s\n\n" % auth.refresh_token) # you can now replace the 0 in your .env file with this token, so it'll be used permanently.  You can also add this to the Heroku Config Vars.
      ENV['GOOGLE_REFRESH_TOKEN'] = auth.refresh_token #we'll set it here, so it works without having to alter the .env file for this call
    end if

    GoogleDrive.login_with_oauth(auth.access_token)
查看更多
Deceive 欺骗
3楼-- · 2019-02-07 11:37

You might find it easier to use service accounts, as outlined here:

https://github.com/gimite/google-drive-ruby/issues/126#issuecomment-73542381

查看更多
淡お忘
4楼-- · 2019-02-07 11:41

Use capybara and navigate to the token page. Grab it from the page source and save to a variable. Plug the variable when needed. The token string expires so I grab a new one each time I need to access the spreadsheet.

查看更多
你好瞎i
5楼-- · 2019-02-07 11:50

I figured out this mess.

auth.scope =
    "https://www.googleapis.com/auth/drive " +
    "https://spreadsheets.google.com/feeds/"

The auth.scope is missing a url. REFERENCE from github

auth.scope =
    "https://docs.google.com/feeds/" +
    "https://www.googleapis.com/auth/drive " +
    "https://spreadsheets.google.com/feeds/"

You can reuse your access_token, but first you need to get it. WARNING: The auth.access_token is only good for an hour. If you need another one you need to call auth.refresh! This will issue you another access_token.

require 'google/api_client'
require 'google_drive'

client = Google::APIClient.new(
  :application_name => 'Example Ruby application',
  :application_version => '1.0.0'
)
auth = client.authorization
auth.client_id = "YOUR CLIENT ID"
auth.client_secret = "YOUR CLIENT SECRET"
auth.scope =
    "https://www.googleapis.com/auth/drive " +
    "https://spreadsheets.google.com/feeds/"
auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
print("1. Open this page:\n%s\n\n" % auth.authorization_uri)
print("2. Enter the authorization code shown in the page: ")
auth.code = $stdin.gets.chomp
auth.fetch_access_token!
access_token = auth.access_token

system'clear'
print "Save your access token\n\n"
print access_token  
print "\nSave your refresh token\n\n"
print auth.refresh_token 

This chunk of code should print out your access_token/refresh_token in your console. Now you can hard code your application.

require "google/api_client"
require "google_driver"
client = Google::APIClient.new(
  :application_name => 'Example Ruby application',
  :application_version => '1.0.0'
)
auth = client.authorization
auth.client_id = "Your Client ID"
auth.client_secret = "Your client secret"

access_token = "token you saved from the terminal"

session = GoogleDrive.login_with_oauth(access_token)

for file in session.files
   p file.title
end

And eventually your "access_token" will expire. At this point you need to "refresh" it. You can call to see if your access_token is expired by calling

auth.expires_at

You can get a new access token with this example.

require 'google/api_client'
require 'google_drive'


$client_id = "YOUR CLIENT ID"
$client_secret = "YOUR CLIENT SECRET"
$refresh_token = "SAVED REFRESH TOKEN"

 client = Google::APIClient.new(:application_name => 'Example Ruby application', :application_version => '1.0.0')
    auth = client.authorization
    auth.client_id = $client_id
    auth.client_secret = $client_secret
    auth.scope = "https://docs.google.com/feeds/" + "https://www.googleapis.com/auth/drive " + "https://spreadsheets.google.com/feeds/"
    auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
    auth.refresh_token = $refresh_token

    #here's the magic sauce 
    auth.refresh! 

    #as you can see above auth.access_token wasn't passed a value
    # but if you call it now you'll see you have a new access_token

    auth.access_token
    => new token from server 
查看更多
登录 后发表回答