oauth2-client 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2U2ZjkyMjc5YjBhZWE1MjE3YTZjZDEzMjM4M2Y0MDZlYTA3MmU0YQ==
5
+ data.tar.gz: !binary |-
6
+ M2NhZDBhYjljNzVmY2ZkYTEwNjcxZGI4MmRjNTUxODhhOTNlMzYzMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MzJhY2RiOWQ4ZWFkZTZjNmI2YmRhYWYyOGUzZTBiM2YzNmJmZWY0ZTgyZTRj
10
+ M2IwYTkyOTgxM2MzZmQ1MzhlODYyOGM4YjEwZGJhZWZkNDg3ZDA4YzEyNWVk
11
+ NDQxNWM0N2QzYjRiZmM2Y2UwMzc4MzRlOTQ1OGQ2YjBjNTk5NTg=
12
+ data.tar.gz: !binary |-
13
+ ZGU0YmRiM2Y5YjRlNzUzMTdmNTA0ZWVjOGIzMzViNDliNzQxNjk0OWNiN2Zj
14
+ MDVjYjYxYzUxYTRiN2I0ZDJjYjQxZDc0YmEyZmI4ZWQ4YjFhNjMwYjVlMTcy
15
+ YzUwNGFjNDlmZDM4YjU1ODVlMDc1MGIzMDE5ZTViYmU3YTNjNjY=
data/.gitignore CHANGED
@@ -16,3 +16,13 @@ tmp
16
16
  .yardoc
17
17
  _yardoc
18
18
  doc/
19
+
20
+ # OS generated files #
21
+ .DS_Store
22
+ .DS_Store?
23
+ ._*
24
+ .Spotlight-V100
25
+ .Trashes
26
+ Icon?
27
+ ehthumbs.db
28
+ Thumbs.db
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - "1.8.7"
3
4
  - "1.9.2"
4
5
  - "1.9.3"
5
6
  # uncomment this line if your project needs to run something other than `rake`:
data/Gemfile CHANGED
@@ -1,17 +1,12 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'json'
4
-
5
- gem 'bcrypt-ruby', '~> 3.0.0'
6
-
7
- gem 'addressable'
8
-
9
3
  gem 'rake'
10
4
 
11
- gem 'rspec', '~>2.12'
12
-
13
- gem 'simplecov'
14
-
15
- gem 'activesupport', '~> 3.2.8'
5
+ group :test do
6
+ gem 'json', :platforms => :ruby_18
7
+ gem 'rspec', '>= 2.11'
8
+ gem 'simplecov', :require => false
9
+ gem 'webmock'
10
+ end
16
11
 
17
- # gem 'mocha', '>=0.12.1', :require => false
12
+ gemspec
@@ -1,13 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oauth2-client (1.1.0)
5
+ addressable
6
+ bcrypt-ruby (~> 3.0.0)
7
+ json
8
+
1
9
  GEM
2
10
  remote: https://rubygems.org/
3
11
  specs:
4
- activesupport (3.2.8)
5
- i18n (~> 0.6)
6
- multi_json (~> 1.0)
7
- addressable (2.3.2)
12
+ addressable (2.3.3)
8
13
  bcrypt-ruby (3.0.1)
14
+ crack (0.3.2)
9
15
  diff-lcs (1.1.3)
10
- i18n (0.6.1)
11
16
  json (1.7.5)
12
17
  multi_json (1.3.6)
13
18
  rake (0.9.2.2)
@@ -23,15 +28,18 @@ GEM
23
28
  multi_json (~> 1.0)
24
29
  simplecov-html (~> 0.7.1)
25
30
  simplecov-html (0.7.1)
31
+ webmock (1.10.1)
32
+ addressable (>= 2.2.7)
33
+ crack (>= 0.3.2)
26
34
 
27
35
  PLATFORMS
28
36
  ruby
29
37
 
30
38
  DEPENDENCIES
31
- activesupport (~> 3.2.8)
32
- addressable
33
- bcrypt-ruby (~> 3.0.0)
39
+ bundler (~> 1.0)
34
40
  json
41
+ oauth2-client!
35
42
  rake
36
- rspec (~> 2.12)
43
+ rspec (>= 2.11)
37
44
  simplecov
45
+ webmock
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012, Kevin Mutyaba
1
+ Copyright (c) 2013, Kevin Mutyaba
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,24 +1,30 @@
1
1
  # OAuth2 Ruby Client
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/oauth2-client.png)][gem]
3
4
  [![Build Status](https://secure.travis-ci.org/tiabas/oauth2-client.png?branch=master)][travis]
4
5
 
6
+ [gem]: https://rubygems.org/gems/oauth2-client
5
7
  [travis]: http://travis-ci.org/tiabas/oauth2-client
6
8
 
7
- A Ruby wrapper for the OAuth 2.0 specification. It is designed with the philosophy that not
8
- every service that claims to support OAuth 2.0 actually implements it according to the
9
- [standard]( http://tools.ietf.org/html/rfc6749). This version therefore, affords
10
- the developer some degree of flexibility in generating the URLs and requests
11
- needed to authorize an OAuth 2.0 application.
9
+ A Ruby wrapper for the OAuth 2.0 specification. It is designed with the philosophy that
10
+ different service providers implement OAuth 2.0 differently and not exactly according to the
11
+ [RFC]( http://tools.ietf.org/html/rfc6749). This gem therefore, affords
12
+ the developer some degree of flexibility in creating a client that will work with different OAuth2
13
+ providers.
12
14
 
13
- For more about the standard, take a look at http://tools.ietf.org/html/rfc6749
15
+ For more about the standard checkout: http://tools.ietf.org/html/rfc6749
14
16
 
15
17
  ## Installation
16
- Download the library and include the its location in your Gemfile
18
+ ```sh
19
+ gem install oauth2-client
20
+ ```
17
21
 
18
22
  ## Resources
19
23
  * [View Source on GitHub][code]
20
24
  * [Report Issues on GitHub][issues]
25
+ * [Website][website]
21
26
 
27
+ [website]: http://tiabas.github.com/oauth2-client/
22
28
  [code]: https://github.com/tiabas/oauth2-client
23
29
  [issues]: https://github.com/tiabas/oauth2-client/issues
24
30
 
@@ -85,6 +91,52 @@ auth_url = client.device_code.authorization_path(:scope => 'abc xyz', :state =>
85
91
  token = client.device_code.get_token(device_auth_code)
86
92
  ```
87
93
 
94
+ # Using a custom Http wrapper
95
+ By default, oauth2-client uses a Net::HTTP wrapper called OAuth2::HttpConnection. However, if you wish to use a different HTTP library, you only
96
+ need to create a wrapper around your favorite library that will respond to the `send_request` method.
97
+
98
+ ```ruby
99
+ class TyphoeusHttpConnection
100
+
101
+ def initalize(site_url, connection_options={})
102
+ # set url and connection options
103
+ @site_url = site_url
104
+ @connection_options = connection_options
105
+ end
106
+
107
+ def base_url(path)
108
+ @site_url + path
109
+ end
110
+
111
+ def send_request(http_method, request_path, options={})
112
+ # options may contain optional arguments like http headers, request parameters etc
113
+ # send http request over the inter-webs
114
+
115
+ params = options[:params] || {}
116
+ headers = options[:headers]|| {}
117
+ method = method.to_sym
118
+ client = Typhoeus
119
+
120
+ case method
121
+ when :get, :delete
122
+ #pass
123
+ when :post, :put
124
+ options[:body] = options.delete(:params) if options[:params]
125
+ else
126
+ raise UnhandledHTTPMethodError.new("Unsupported HTTP method, #{method}")
127
+ end
128
+ response = client.send(http_method, base_url(request_path), params)
129
+ end
130
+ end
131
+
132
+ # now you can initialize the OAuth2 client with you custom client and expect that all requests
133
+ # will be sent using this client
134
+ oauth_client = OAuth2::Client.new('example.com', client_id, client_secret, {
135
+ :connection_client => TyphoeusHttpConnection,
136
+ :connection_options => {}
137
+ })
138
+ ```
139
+
88
140
  # Client Examples
89
141
  This library comes bundled with two sample implementations of Google and Yammer OAuth clients. These clients are
90
142
  meant to showcase the degree of flexibilty that you get when using this library to interact with other OAuth 2.0
@@ -94,21 +146,14 @@ providers.
94
146
 
95
147
  ```ruby
96
148
 
97
- google_client = GoogleClient.new(
98
- 'https://accounts.google.com',
99
- '827502413694.apps.googleusercontent.com',
100
- 'a2nQpcUm2Dgq1chWdAvbXGTk',
101
- {
102
- :token_path => '/o/oauth2/token',
103
- :authorize_path => '/o/oauth2/auth',
104
- :device_path => '/o/oauth2/device/code'
105
- }
106
- )
149
+ google_client = GoogleClient.new('https://accounts.google.com', '827502413694.apps.googleusercontent.com','a2nQpcUm2Dgq1chWdAvbXGTk')
107
150
 
108
151
  ```
109
152
 
110
153
  ### Client-side authorization URL(Implicit grant)
111
154
  ```ruby
155
+
156
+ # generate authorization url
112
157
  auth_url = google_client.webserver_authorization_url(
113
158
  :scope => 'https://www.googleapis.com/auth/userinfo.email',
114
159
  :state => '/profile',
@@ -119,6 +164,8 @@ auth_url = google_client.webserver_authorization_url(
119
164
 
120
165
  ### Server-side authorization URL(Authorization code grant)
121
166
  ```ruby
167
+
168
+ # generate authorization url
122
169
  auth_url = google_client.clientside_authorization_url(
123
170
  :scope => 'https://www.googleapis.com/auth/userinfo.email',
124
171
  :state => '/profile',
@@ -146,7 +193,50 @@ response.body
146
193
  }
147
194
  ```
148
195
 
196
+ ## Github Client
197
+
198
+ ```ruby
199
+
200
+ gihub_client = GithubClient.new('https://github.com', '82f971d013e8d637a7e1', '1a1d59e1f8b8afa5f73e9dc9f17e25f7876e64ac')
201
+
202
+ ```
203
+ ### Server-side authorization URL(Authorization code grant)
204
+
205
+ ```ruby
206
+
207
+ # generate authorization url
208
+ auth_url = gihub_client.webserver_authorization_url
209
+ # => https://github.com/login/oauth/authorize?client_id=82f971d013e8d637a7e1&response_type=code
210
+
211
+ # exchange authorization code for access token. we will get back a Net::HTTPResponse
212
+ response = gihub_client.exchange_auth_code_for_token({
213
+ :code => '11a0b0b64db56c30e2ef',
214
+ :redirect_uri => 'https://localhost/callback',
215
+ })
216
+
217
+ response.inspect
218
+ # => #<Net::HTTPOK:0x007ff8bc7c1200>
219
+
220
+ response.body
221
+ # => {
222
+ "access_token" : "e409f4272fe539166a77c42479de030e7660812a",
223
+ "token_type" : "bearer"
224
+ }"
225
+ ```
226
+
227
+ ## Supported Ruby Versions
228
+ This library aims to support and is [tested against][travis] the following Ruby
229
+ version:
230
+
231
+ * Ruby 1.8.7
232
+ * Ruby 1.9.2
233
+ * Ruby 1.9.3
234
+
235
+ This library may inadvertently work (or seem to work) on other Ruby
236
+ implementations, however support will only be provided for the versions listed
237
+ above.
238
+
149
239
  ## Copyright
150
- Copyright (c) 2012 Kevin Mutyaba
151
- See [LICENSE][] for details.
240
+ Copyright (c) 2013 Kevin Mutyaba
241
+ See [LICENSE][license] for details.
152
242
  [license]: https://github.com/tiabas/oauth2-client/blob/master/LICENSE
@@ -0,0 +1,42 @@
1
+ class GithubClient < OAuth2::Client
2
+
3
+ def initialize(*args)
4
+ super
5
+ @token_path = '/login/oauth/access_token'
6
+ @authorize_path = '/login/oauth/authorize'
7
+ end
8
+ # @see http://developer.github.com/v3/oauth/#redirect-users-to-request-github-access
9
+ #
10
+ # @params [Hash] parameters to include in the URL eg. scope, state, redirect_uri
11
+ #
12
+ # client.webserver_authorization_url({
13
+ # :scope => 'user, public_repo',
14
+ # :state => '2sw543v74sfD',
15
+ # :redirect_uri => 'https://localhost/callback',
16
+ # })
17
+ # #=>
18
+ def webserver_authorization_url(opts={})
19
+ opts[:scope] = normalize_scope(opts[:scope], ',') if opts[:scope]
20
+ authorization_code.authorization_url(opts)
21
+ end
22
+
23
+ #
24
+ # @see http://developer.github.com/v3/oauth/#github-redirects-back-to-your-site
25
+ #
26
+ # @params [Hash] parameters to include in the URL eg. code, redirect_uri
27
+ #
28
+ # client.exchange_auth_code_for_token(
29
+ # :params => {
30
+ # :code => '11a0b0b64db56c30e2ef',
31
+ # :redirect_uri => 'https://localhost/callback',
32
+ # })
33
+ # #=>
34
+ def exchange_auth_code_for_token(opts={})
35
+ unless (opts[:params] && opts[:params][:code])
36
+ raise "Authorization code expected but was nil"
37
+ end
38
+ opts[:authenticate] = :body
39
+ code = opts[:params].delete(:code)
40
+ authorization_code.get_token(code, opts)
41
+ end
42
+ end
@@ -1,11 +1,10 @@
1
1
  class GoogleClient < OAuth2::Client
2
2
 
3
- def normalize_scope(scope, sep=' ')
4
- unless (scope.is_a?(String) || scope.is_a?(Array))
5
- raise ArgumentError.new("Expected scope of type String or Array but was: #{scope.class.name}")
6
- end
7
- return scope if scope.is_a?(String)
8
- scope.join(sep)
3
+ def initialize(*args)
4
+ super
5
+ @token_path = '/o/oauth2/token'
6
+ @authorize_path = '/o/oauth2/auth'
7
+ @device_path = '/o/oauth2/device/code'
9
8
  end
10
9
 
11
10
  # Generates the Google URL that the user will be redirected to in order to
@@ -56,15 +55,6 @@ class GoogleClient < OAuth2::Client
56
55
  authorization_code.authorization_url(params)
57
56
  end
58
57
 
59
- # Generates the Google URL that allows a user to obtain an authorization
60
- # code for a given device
61
- #
62
- # @see https://developers.google.com/accounts/docs/OAuth2ForDevices
63
- # def device_authorization_url(params={})
64
- # params[:scope] = normalize_scope(params[:scope]) if params[:scope]
65
- # device.authorization_url(params)
66
- # end
67
-
68
58
  # Makes a request to google server that will swap your authorization code for an access
69
59
  # token
70
60
  #
@@ -87,6 +77,7 @@ class GoogleClient < OAuth2::Client
87
77
  unless (opts[:params] && opts[:params][:code])
88
78
  raise ArgumentError.new("You must include an authorization code as a parameter")
89
79
  end
80
+ opts[:authenticate] ||= :body
90
81
  code = opts[:params].delete(:code)
91
82
  authorization_code.get_token(code, opts)
92
83
  end
@@ -112,10 +103,21 @@ class GoogleClient < OAuth2::Client
112
103
  unless (opts[:params] && opts[:params][:refresh_token])
113
104
  raise ArgumentError.new("You must provide a refresh_token as a parameter")
114
105
  end
106
+ opts[:authenticate] = :body
115
107
  token = opts[:params].delete(:refresh_token)
116
108
  refresh_token.get_token(token, opts)
117
109
  end
118
110
 
111
+
112
+ # Generates the Google URL that allows a user to obtain an authorization
113
+ # code for a given device
114
+ #
115
+ # @see https://developers.google.com/accounts/docs/OAuth2ForDevices
116
+ def device_authorization_url(params={})
117
+ params[:scope] = normalize_scope(params[:scope]) if params[:scope]
118
+ device.authorization_url(params)
119
+ end
120
+
119
121
  # @see https://developers.google.com/accounts/docs/OAuth2ForDevices#obtainingacode
120
122
  #
121
123
  # @params [Hash] additional parameters to be include in URL eg. state
@@ -0,0 +1,96 @@
1
+ class YammerClient < OAuth2::Client
2
+
3
+ def initialize(*args)
4
+ super
5
+ @token_path = '/oauth2/token'
6
+ @authorize_path = '/dialog/oauth/authorize'
7
+ end
8
+ # Generates the Yammer URL that the user will be redirected to in order to
9
+ # authorize your application
10
+ #
11
+ # @see https://developer.yammer.com/api/oauth2.html#client-side
12
+ #
13
+ # @opts [Hash] additional parameters to be include in URL eg. scope, state, etc
14
+ #
15
+ # client = YammerClient.new(config)
16
+ # client.clientside_authorization_url({
17
+ # :redirect_uri => 'https://localhost/oauth/cb',
18
+ # })
19
+ # >> https://www.yammer.com/dialog/oauth/?client_id={client_id}&
20
+ # redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Fcb&response_type=token
21
+ #
22
+ def clientside_authorization_url(opts={})
23
+ implicit.token_url(opts)
24
+ end
25
+
26
+ # Generates the Yammer URL that the user will be redirected to in order to
27
+ # authorize your application
28
+ #
29
+ # @see https://developer.yammer.com/api/oauth2.html#server-side
30
+ #
31
+ # @opts [Hash] additional parameters to be include in URL eg. scope, state, etc
32
+ #
33
+ # >> client = YammerClient.new(config)
34
+ # >> client.webserver_authorization_url({
35
+ # :redirect_uri => 'https://localhost/oauth/cb',
36
+ # })
37
+ # >> https://www.yammer.com/dialog/oauth/?client_id={client_id}&
38
+ # redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Fcb&response_type=code
39
+ #
40
+ def webserver_authorization_url(opts={})
41
+ opts[:scope] = normalize_scope(opts[:scope]) if opts[:scope]
42
+ authorization_code.authorization_url(opts)
43
+ end
44
+
45
+ # Generates the Yammer URL that the user will be redirected to in order to
46
+ # authorize your application
47
+ #
48
+ # @see https://developer.yammer.com/api/oauth2.html#server-side
49
+ #
50
+ # @opts [Hash] additional parameters to be include in URL eg. scope, state, etc
51
+ #
52
+ # >> client = YammerClient.new(config)
53
+ # >> client.webserver_authorization_url({
54
+ # :client_secret => @client_secret
55
+ # :code => 'G3Y6jU3a',
56
+ # :redirect_uri => 'https://localhost/oauth/cb',
57
+ # })
58
+ # >> https://www.yammer.com/oauth2/access_token?client_id={client_id}&
59
+ # redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Fcb&client_secret={client_secret}&
60
+ # grant_type=authorization_code&code=aXW2c6bYz
61
+ #
62
+ def webserver_token_url(opts={})
63
+ opts[:scope] = normalize_scope(opts[:scope]) if opts[:scope]
64
+ opts[:client_secret] = @client_secret
65
+ authorization_code.token_path(opts)
66
+ end
67
+
68
+ # Makes a request to Yammer server that will swap your authorization code for an access
69
+ # token
70
+ #
71
+ # @see https://developer.yammer.com/api/oauth2.html#server-side
72
+ #
73
+ # @opts [Hash] must include authorization code and redirect uri in additon to others
74
+ #
75
+ # >> client = YammerClient.new(config)
76
+ # >> client.exchange_auth_code_for_token({
77
+ # :redirect_uri => 'https://localhost:3000/oauth/v2/callback',
78
+ # :code => 'G3Y6jU3a',
79
+ # })
80
+ #
81
+ # POST /oauth2/access_token HTTP/1.1
82
+ # Host: www.yammer.com
83
+ # Content-Type: application/x-www-form-urlencoded
84
+
85
+ # client_id={client_id}&code=G3Y6jU3a&grant_type=authorization_code&
86
+ # redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Fcb&client_secret={client_secret}
87
+
88
+ def exchange_auth_code_for_token(opts={})
89
+ unless (opts[:params] && opts[:params][:code])
90
+ raise ArgumentError.new("You must include an authorization code as a parameter")
91
+ end
92
+ opts[:authenticate] ||= :body
93
+ code = opts[:params].delete(:code)
94
+ authorization_code.get_token(code, opts)
95
+ end
96
+ end