google-oauth-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee18c4c8bf054e4a04d18b104b22c72e0360355864e2090361f1f520c1bf95f6
4
+ data.tar.gz: 6ee8403f8a338e57c7dc199fbc50580577b711b100b651f2f3e0027dd9b07c91
5
+ SHA512:
6
+ metadata.gz: 2ecfed6455a9a51e70ff931ae78c9e0d1ad20fe65d0d87774b0cd37690b6cefb6b140f495215eb88d5994aea157cf6846b7c12193f33d3c3899528f196194a37
7
+ data.tar.gz: d2693bb74664c645a7ef5ea7d421847a95ab51f6ccd51076278191c07a8d7ebee231843db0ec7571b24504138ca2ccfe386d468feac0177f6b963fc653ecfddd
data/.rubocop.yml ADDED
@@ -0,0 +1,24 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.6
4
+
5
+ Style/StringLiterals:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Style/StringLiteralsInInterpolation:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Style/Documentation:
14
+ Enabled: false
15
+
16
+ Layout/LineLength:
17
+ Max: 120
18
+
19
+ Metrics/MethodLength:
20
+ Max: 30
21
+
22
+ Naming/FileName:
23
+ Exclude:
24
+ - 'lib/google-oauth-cli.rb'
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-04-06
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in google-oauth-cli.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rubocop", "~> 1.21"
data/Gemfile.lock ADDED
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ google-oauth-cli (0.1.0)
5
+ googleauth (~> 1.5)
6
+ launchy (~> 2.5)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.8.3)
12
+ public_suffix (>= 2.0.2, < 6.0)
13
+ ast (2.4.2)
14
+ faraday (2.7.4)
15
+ faraday-net_http (>= 2.0, < 3.1)
16
+ ruby2_keywords (>= 0.0.4)
17
+ faraday-net_http (3.0.2)
18
+ googleauth (1.5.0)
19
+ faraday (>= 0.17.3, < 3.a)
20
+ jwt (>= 1.4, < 3.0)
21
+ memoist (~> 0.16)
22
+ multi_json (~> 1.11)
23
+ os (>= 0.9, < 2.0)
24
+ signet (>= 0.16, < 2.a)
25
+ json (2.6.3)
26
+ jwt (2.7.0)
27
+ launchy (2.5.2)
28
+ addressable (~> 2.8)
29
+ memoist (0.16.2)
30
+ multi_json (1.15.0)
31
+ os (1.1.4)
32
+ parallel (1.22.1)
33
+ parser (3.2.2.0)
34
+ ast (~> 2.4.1)
35
+ public_suffix (5.0.1)
36
+ rainbow (3.1.1)
37
+ rake (13.0.6)
38
+ regexp_parser (2.7.0)
39
+ rexml (3.2.5)
40
+ rubocop (1.49.0)
41
+ json (~> 2.3)
42
+ parallel (~> 1.10)
43
+ parser (>= 3.2.0.0)
44
+ rainbow (>= 2.2.2, < 4.0)
45
+ regexp_parser (>= 1.8, < 3.0)
46
+ rexml (>= 3.2.5, < 4.0)
47
+ rubocop-ast (>= 1.28.0, < 2.0)
48
+ ruby-progressbar (~> 1.7)
49
+ unicode-display_width (>= 2.4.0, < 3.0)
50
+ rubocop-ast (1.28.0)
51
+ parser (>= 3.2.1.0)
52
+ ruby-progressbar (1.13.0)
53
+ ruby2_keywords (0.0.5)
54
+ signet (0.17.0)
55
+ addressable (~> 2.8)
56
+ faraday (>= 0.17.5, < 3.a)
57
+ jwt (>= 1.5, < 3.0)
58
+ multi_json (~> 1.10)
59
+ unicode-display_width (2.4.2)
60
+
61
+ PLATFORMS
62
+ arm64-darwin-22
63
+
64
+ DEPENDENCIES
65
+ google-oauth-cli!
66
+ rake (~> 13.0)
67
+ rubocop (~> 1.21)
68
+
69
+ BUNDLED WITH
70
+ 2.4.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Yusuke Fujiki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # google-oauth-cli
2
+
3
+ google-oauth-cli is a RubyGems library that allows you to perform OAuth authentication with Google from the command-line interface (CLI).
4
+
5
+ ## Features
6
+
7
+ - Authenticates with Google using OAuth from CLI.
8
+ - Spins up a simple web server to receive the authorization code.
9
+ - Supports passing a file path as an optional argument to persist the refresh token, making it easier to handle token refreshing in subsequent requests.
10
+
11
+ ## Motivation
12
+
13
+ Google deprecates to the OOB flow by Google in February 2022.
14
+
15
+ ## Usage
16
+
17
+ ```rb
18
+ auth = GoogleOAuthCli.new(
19
+ client_id: ENV["client_id"],
20
+ client_secret: ENV["client_secret"],
21
+ scope: ["https://www.googleapis.com/auth/drive", "https://spreadsheets.google.com/feeds"],
22
+ credentials_file: "~/.config/google-test.json"
23
+ )
24
+
25
+ # Starts authentication flow and returns Google::Auth::UserRefreshCredentials
26
+ credentials = auth.login
27
+
28
+ drive = Google::Apis::DriveV3::DriveService.new
29
+ drive.authorization = credentials
30
+ ```
31
+
32
+ ## Development
33
+
34
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+
36
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## License
39
+
40
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/google-oauth-cli/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "google-oauth-cli"
7
+ spec.version = GoogleOAuthCli::VERSION
8
+ spec.authors = ["Yusuke Fujiki"]
9
+ spec.email = ["yusuke@fujikkys.com"]
10
+
11
+ spec.summary = "Library for Google OAuth authentication from CLI"
12
+ spec.description = <<~DESC
13
+ Perform Google OAuth authentication from the CLI using redirect flows.
14
+ Authentication information is saved in a file and can be used for the next authentication.
15
+ DESC
16
+ spec.homepage = "https://github.com/fujikky/google-oauth-cli"
17
+ spec.license = "MIT"
18
+ spec.required_ruby_version = ">= 2.6.0"
19
+
20
+ spec.metadata["rubygems_mfa_required"] = "true"
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = "https://github.com/fujikky/google-oauth-cli"
23
+ spec.metadata["changelog_uri"] = "https://github.com/fujikky/google-oauth-cli/tree/main/CHANGELOG"
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(__dir__) do
28
+ `git ls-files -z`.split("\x0").reject do |f|
29
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
30
+ end
31
+ end
32
+ spec.bindir = "exe"
33
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
34
+ spec.require_paths = ["lib"]
35
+
36
+ # Uncomment to register a new dependency of your gem
37
+ spec.add_dependency "googleauth", "~> 1.5"
38
+ spec.add_dependency "launchy", "~> 2.5"
39
+
40
+ # For more information and examples about making a new gem, check out our
41
+ # guide at: https://bundler.io/guides/creating_gem.html
42
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GoogleOAuthCli
4
+ class Server
5
+ def initialize(port:, state:)
6
+ @server = TCPServer.new port
7
+ @state = state
8
+ end
9
+
10
+ def start
11
+ loop do
12
+ connection = server.accept
13
+ request = connection.gets
14
+ data = handle_request(request)
15
+ connection.write <<~DOC
16
+ HTTP/1.1 200 OK
17
+ Content-Type: text/plain; charset=UTF-8
18
+
19
+ OAuth request received. You can close this window now.
20
+ DOC
21
+ connection.close
22
+ if data
23
+ server.close
24
+ return data
25
+ end
26
+ end
27
+ server.close
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :server, :state
33
+
34
+ def handle_request(request)
35
+ _, full_path = request.split
36
+ return if URI(full_path).path != "/authorize"
37
+
38
+ params = CGI.parse(URI.parse(full_path).query)
39
+ raise(Error, "Invalid oauth request received") if @state != params["state"][0]
40
+
41
+ params["code"][0]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GoogleOAuthCli
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "googleauth"
4
+ require "launchy"
5
+ require_relative "google-oauth-cli/version"
6
+ require_relative "google-oauth-cli/server"
7
+
8
+ class GoogleOAuthCli
9
+ class Error < StandardError; end
10
+
11
+ def initialize(client_id:, client_secret:, scope:, credentials_file: nil, port: 9876)
12
+ @credentials = Google::Auth::UserRefreshCredentials.new(
13
+ client_id: client_id,
14
+ client_secret: client_secret,
15
+ scope: scope,
16
+ redirect_uri: "http://localhost:#{port}/authorize",
17
+ additional_parameters: { access_type: "offline" }
18
+ )
19
+ if credentials_file
20
+ @credentials_file = Pathname.new(File.expand_path(credentials_file))
21
+ @credentials_file
22
+ end
23
+ @port = port
24
+ end
25
+
26
+ def login
27
+ authorize_from_credentials || authorize_from_authorization_code_flow
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :credentials, :credentials_file, :port
33
+
34
+ def authorize_from_credentials
35
+ return nil unless credentials_file&.exist?
36
+
37
+ token = JSON.parse(credentials_file.read)["refresh_token"]
38
+ return nil if token.nil?
39
+
40
+ credentials.refresh_token = token
41
+ fetch_and_save_token!
42
+
43
+ credentials
44
+ end
45
+
46
+ def authorize_from_authorization_code_flow
47
+ state = SecureRandom.base64(16)
48
+ credentials.state = state
49
+
50
+ uri = credentials.authorization_uri
51
+ Launchy.open(uri) do |exception|
52
+ raise(Error, "Attempted to open #{uri} and failed because #{exception}")
53
+ end
54
+
55
+ credentials.code = start_server_and_receive_code(state)
56
+ fetch_and_save_token!
57
+
58
+ credentials
59
+ end
60
+
61
+ def fetch_and_save_token!
62
+ credentials.fetch_access_token!
63
+ credentials_file&.write({ refresh_token: credentials.refresh_token }.to_json)
64
+ end
65
+
66
+ def start_server_and_receive_code(state)
67
+ server = Thread.new do
68
+ Thread.current.report_on_exception = false
69
+ Server.new(port: port, state: state).start
70
+ end
71
+ server.join
72
+ server.value
73
+ end
74
+ end
@@ -0,0 +1,7 @@
1
+ class GoogleOAuthCli
2
+ VERSION: String
3
+
4
+ def initialize(client_id: String, client_secret: String, scope: String | Array[String], credentials_file: String?, port: Integer?) -> void
5
+
6
+ def login -> Google::Auth::UserRefreshCredentials
7
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google-oauth-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yusuke Fujiki
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: googleauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: launchy
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.5'
41
+ description: |
42
+ Perform Google OAuth authentication from the CLI using redirect flows.
43
+ Authentication information is saved in a file and can be used for the next authentication.
44
+ email:
45
+ - yusuke@fujikkys.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".rubocop.yml"
51
+ - CHANGELOG.md
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - google-oauth-cli.gemspec
58
+ - lib/google-oauth-cli.rb
59
+ - lib/google-oauth-cli/server.rb
60
+ - lib/google-oauth-cli/version.rb
61
+ - sig/google-oauth-cli.rbs
62
+ homepage: https://github.com/fujikky/google-oauth-cli
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ rubygems_mfa_required: 'true'
67
+ homepage_uri: https://github.com/fujikky/google-oauth-cli
68
+ source_code_uri: https://github.com/fujikky/google-oauth-cli
69
+ changelog_uri: https://github.com/fujikky/google-oauth-cli/tree/main/CHANGELOG
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 2.6.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubygems_version: 3.4.1
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Library for Google OAuth authentication from CLI
89
+ test_files: []