oauth2-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +70 -0
  3. data/bin/oauth2-cli +144 -0
  4. metadata +89 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 76187c5b942695b8ee0626735c7a762f76dba841
4
+ data.tar.gz: bf31d9f78aee657bfd091d96c40b81bf8bfa72a0
5
+ SHA512:
6
+ metadata.gz: 0dcb7367f6597f3311c5e07982e8655f234fc3100a7160193af810cc0e71c050d4b71de2589a14e2935d69fd2035e33115e9d8b6383b8db2c9ba27079603309c
7
+ data.tar.gz: e7bbd220f94a2e494eada6131b22481d8cef9db51ff7ff7311c229813c3686c8eb73533535a289cfa995fab884f097a4c7091a4ef6acb27311be4ac14746ef68
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ ## oauth2-cli
2
+
3
+ Command line utility to get an OAuth access token for three-legged flows where you authorise an application to access your account. Inspired by [oauth2-cli](https://github.com/dcarley/oauth2-cli) written in Go.
4
+
5
+ The reason for rewriting this in Ruby was the difficulty to debug the OAuth2 flow when things don't go as expected. Go's OAuth2 library is pretty opaque and trying to figure out why for some services the client_id is not passed when sending the the token request after obtaining the authorisation code has been fruitless - even though sending the request via curl using the produced authorisation code proved successful.
6
+
7
+ The purpose for this tool is to obtain access and refresh tokens for applications which run as services (i.e daemons) where doing the OAuth2 flow is a bit difficult.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ gem install oauth2-cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ For services which validate the callback URL, you must use `http://127.0.0.1:8000/oauth/callback` in your OAuth2 application. Bear in mind that `8000` is the default port which may be changed via CLI argument. Adapt as necessary.
18
+
19
+ The `oauth2-cli` script has a built in help:
20
+
21
+ ```bash
22
+ oauth2-cli -h
23
+ Usage: oauth2-cli --auth AUTHORISATION_URL --token TOKEN_URL --id CLIENT_ID --secret CLIENT_SECRET
24
+
25
+ -a, --auth AUTHORISATION_URL Authorisation URL (required)
26
+ -t, --token TOKEN_URL Token URL (required)
27
+ -i, --id CLIENT_ID Client ID (required)
28
+ -s, --secret CLIENT_SECRET Client secret (required)
29
+ -o, --scope SCOPE1,SCOPE2,etc OAuth2 scope to authorise (not used if not specified)
30
+ -e, --separator OAuth2 scope separator character (defaults to space) n.b the scope arg is always passed as array and joined with the separator char for the request
31
+ -p, --port 8000 Callback port (defaults to 8000)
32
+ -d, --debug Turn on OAuth2 library debug and WEBrick log
33
+ ```
34
+
35
+ The scope separator character has been implemented for services which interpret the OAuth2 spec a tad different - for example Facebook is using comma separated values for scope.
36
+
37
+ ## Examples
38
+
39
+ ```bash
40
+ # request tokens for accessing Netatmo Weather station
41
+ oauth2-cli -a https://api.netatmo.com/oauth2/authorize -t https://api.netatmo.com/oauth2/token -i CLIENT_ID -s CLIENT_SECRET -o read_station
42
+
43
+ Go to URL: https://api.netatmo.com/oauth2/authorize?access_type=offline&client_id=CLIENT_ID&redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Foauth%2Fcallback&response_type=code&scope=read_station&state=ewcxkqpsfrinhgvyamzbouljtd
44
+
45
+ Starting server - use Ctrl+C to stop
46
+
47
+ {"scope"=>["read_station"],
48
+ "expire_in"=>10800,
49
+ :access_token=>"ACCESS_TOKEN",
50
+ :refresh_token=>"REFRESH_TOKEN",
51
+ :expires_at=>TIMESTAMP}
52
+
53
+ ^C
54
+
55
+ # request tokens for accessing Awair air-quality monitor
56
+ oauth2-cli -a https://oauth-login.awair.is -t https://oauth2.awair.is/v2/token -i CLIENT_ID -s CLIENT_SECRET
57
+
58
+ Go to URL: https://oauth-login.awair.is?access_type=offline&client_id=CLIENT_ID&redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Foauth%2Fcallback&response_type=code&state=jtiznuypwqfhbvmradlgkeoxcs
59
+
60
+ Starting server - use Ctrl+C to stop
61
+
62
+ {"token_type"=>"Bearer",
63
+ :access_token=>"ACCESS_TOKEN",
64
+ :refresh_token=>"REFRESH_TOKEN",
65
+ :expires_at=>nil}
66
+
67
+ ^C
68
+ ```
69
+
70
+ The output hash from the token request may be used by Ruby's [OAuth2](https://github.com/oauth-xx/oauth2) library to recreate an `AccessToken` object using the `from_hash` class method. You have to implement your own token refresh capabilities when the access token expires for the OAuth2 library doesn't provide such functionality.
data/bin/oauth2-cli ADDED
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pp'
4
+ require 'oauth2'
5
+ require 'webrick'
6
+ require 'optparse'
7
+
8
+ options = {}
9
+ required = []
10
+
11
+ src = File.basename($PROGRAM_NAME)
12
+ state = ('a'..'z').to_a.sample(32).join
13
+ path = '/oauth/callback'
14
+
15
+ optp = OptionParser.new do |opts|
16
+ opts.banner = "Usage: #{src} --auth AUTHORISATION_URL --token TOKEN_URL "\
17
+ "--id CLIENT_ID --secret CLIENT_SECRET\n\n"
18
+
19
+ required << :auth
20
+ desc_auth = 'Authorisation URL (required)'
21
+ opts.on('-a', '--auth AUTHORISATION_URL', desc_auth) do |opt|
22
+ options[:auth] = opt
23
+ end
24
+
25
+ required << :token
26
+ opts.on('-t', '--token TOKEN_URL', 'Token URL (required)') do |opt|
27
+ options[:token] = opt
28
+ end
29
+
30
+ required << :id
31
+ opts.on('-i', '--id CLIENT_ID', 'Client ID (required)') do |opt|
32
+ options[:id] = opt
33
+ end
34
+
35
+ required << :secret
36
+ opts.on('-s', '--secret CLIENT_SECRET', 'Client secret (required)') do |opt|
37
+ options[:secret] = opt
38
+ end
39
+
40
+ options[:scope] = []
41
+ desc_scope = 'OAuth2 scope to authorise (not used if not specified)'
42
+ opts.on('-o', '--scope SCOPE1,SCOPE2,etc', Array, desc_scope) do |opt|
43
+ options[:scope] = opt
44
+ end
45
+
46
+ options[:separator] = ' '
47
+ desc_separator = 'OAuth2 scope separator character (defaults to space) n.b '\
48
+ 'the scope arg is always passed as array and joined with the separator '\
49
+ 'char for the request'
50
+ opts.on('-e', '--separator', desc_separator) do |opt|
51
+ options[:separator] = opt
52
+ end
53
+
54
+ options[:port] = 8000
55
+ desc_port = 'Callback port (defaults to 8000)'
56
+ opts.on('-p', '--port 8000', Integer, desc_port) do |opt|
57
+ options[:port] = opt
58
+ end
59
+
60
+ options[:debug] = false
61
+ opts.on('-d', '--debug', 'Turn on OAuth2 library debug and WEBrick log') do
62
+ ENV['OAUTH_DEBUG'] = 'true'
63
+ options[:debug] = true
64
+ end
65
+ end
66
+
67
+ optp.parse!
68
+
69
+ required.each do |arg|
70
+ next unless options[arg].nil?
71
+
72
+ STDERR.puts "Error: missing required argument #{arg}. "\
73
+ "See #{src} -h for help."
74
+ exit 1
75
+ end
76
+
77
+ redirect_uri = "http://127.0.0.1:#{options[:port]}#{path}"
78
+ client = OAuth2::Client.new(
79
+ options[:id],
80
+ options[:secret],
81
+ authorize_url: options[:auth],
82
+ token_url: options[:token]
83
+ )
84
+
85
+ code_args = {
86
+ access_type: 'offline',
87
+ redirect_uri: redirect_uri,
88
+ state: state
89
+ }
90
+
91
+ unless options[:scope].empty?
92
+ code_args[:scope] = options[:scope].join(options[:separator])
93
+ end
94
+
95
+ url = client.auth_code.authorize_url(code_args)
96
+
97
+ puts ''
98
+ puts "Go to URL: #{url}"
99
+ puts ''
100
+
101
+ puts 'Starting server - use Ctrl+C to stop'
102
+ puts ''
103
+
104
+ server_options = {
105
+ Port: options[:port]
106
+ }
107
+
108
+ unless options[:debug]
109
+ server_options[:Logger] = WEBrick::Log.new(File.open(File::NULL, 'w'))
110
+ server_options[:AccessLog] = []
111
+ end
112
+
113
+ server = WEBrick::HTTPServer.new(server_options)
114
+
115
+ server.mount_proc('/') do |req, res|
116
+ unless req.path == path
117
+ res.status = 403
118
+ res.body = "Invalid callback path - expecting #{path}"
119
+ next
120
+ end
121
+
122
+ unless req.query['state'] == state
123
+ res.status = 400
124
+ res.body = 'Invalid state in callback'
125
+ next
126
+ end
127
+
128
+ token = client.auth_code.get_token(
129
+ req.query['code'],
130
+ redirect_uri: redirect_uri
131
+ )
132
+
133
+ pp token.to_hash
134
+ puts ''
135
+
136
+ res.status = 200
137
+ res.body = 'You may now close this tab'
138
+ end
139
+
140
+ trap('INT') do
141
+ server.shutdown
142
+ end
143
+
144
+ server.start
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oauth2-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ștefan Rusu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oauth2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jeweler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.62'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.62'
55
+ description: CLI utility to get OAuth token for three-leggged flows
56
+ email: saltwaterc@gmail.com
57
+ executables:
58
+ - oauth2-cli
59
+ extensions: []
60
+ extra_rdoc_files:
61
+ - README.md
62
+ files:
63
+ - README.md
64
+ - bin/oauth2-cli
65
+ homepage: https://github.com/SaltwaterC/oauth2-cli
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.6.14
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: CLI utility to get OAuth token
89
+ test_files: []