omniauth_china 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,15 @@
1
1
  # OmniAuth: Standardized Multi-Provider Authentication
2
2
 
3
- OmniAuth is a new Rack-based authentication system for multi-provider external authentcation. OmniAuth is built from the ground up on the philosophy that **authentication is not the same as identity**, and is based on two observations:
3
+ OmniAuth is a new Rack-based authentication system for multi-provider external authentcation. OmniAuth is built from the ground up on the philosophy that **authentication is not the same as identity**.
4
+
5
+ ## Apparently, oauth providers of China have already been merged into [intridea/omniauth](https://github.com/intridea/omniauth). Go take a look.
6
+
4
7
 
5
8
  # OmniAuthChina (omniauth_china)
6
9
 
7
- OmniAuth China is an extention of OmniAuth, it addes Open ID providers in China such as Douban, Sina, Sohu, 163, Tencent, Renren, etc.
10
+ OmniAuth China is an extention of OmniAuth, it addes Open ID providers in China such as Douban, Sina, Sohu, 163, Tencent, Renren, Qzone, etc.
11
+
12
+ ## Note
8
13
 
9
14
  ## Installation
10
15
 
@@ -22,11 +27,8 @@ OmniAuth currently supports the following external providers:
22
27
  * T163 (credit: [he9qi](http://github.com/he9qi))
23
28
  * Tsohu (credit: [he9qi](http://github.com/he9qi))
24
29
  * Tqq (credit: [he9qi](http://github.com/he9qi))
25
- * Renren (credit: [taweili](http://github.com/taweili), [rainux](http://github.com/rainux), [he9qi](http://github.com/he9qi))
26
-
27
- ## 人人([taweili](http://github.com/taweili), [rainux](http://github.com/rainux), [he9qi](http://github.com/he9qi))
28
-
29
- 人人 has been updated to Oauth 2.0; However, as of right now, 人人 still needs session key to get more user information other than just uid[see here](http://wiki.dev.renren.com/wiki/%E8%8E%B7%E5%8F%96%E4%BA%BA%E4%BA%BA%E7%BD%91%E8%B5%84%E6%BA%90), so we still need to request the session key by `https://graph.renren.com/renren_api/session_key?oauth_token='access_token'`. Hopefully this will change soon in the future.
30
+ * Renren (credit: [quake](http://github.com/quake))
31
+ * Qzone (credit: [quake](http://github.com/quake))
30
32
 
31
33
  ## Usage
32
34
 
@@ -8,5 +8,6 @@ module OmniAuth
8
8
  autoload :Tsohu, 'omniauth_china/strategies/tsohu'
9
9
  autoload :Tqq, 'omniauth_china/strategies/tqq'
10
10
  autoload :Renren, 'omniauth_china/strategies/renren'
11
+ autoload :Qzone, 'omniauth_china/strategies/qzone'
11
12
  end
12
13
  end
@@ -0,0 +1,69 @@
1
+ require 'omniauth/oauth'
2
+ require 'multi_json'
3
+
4
+ module OmniAuth
5
+ module Strategies
6
+ #
7
+ # Authenticate to qzone (QQ) via OAuth and retrieve basic
8
+ # user information.
9
+ #
10
+ # Usage:
11
+ #
12
+ # use OmniAuth::Strategies::Qzone, 'consumerkey', 'consumersecret'
13
+ #
14
+ class Qzone < OmniAuth::Strategies::OAuth
15
+ # Initialize the middleware
16
+ def initialize(app, consumer_key = nil, consumer_secret = nil, options = {}, &block)
17
+ client_options = {
18
+ :site => 'http://openapi.qzone.qq.com',
19
+ :request_token_path => '/oauth/qzoneoauth_request_token',
20
+ :access_token_path => '/oauth/qzoneoauth_access_token',
21
+ :authorize_path => '/oauth/qzoneoauth_authorize',
22
+ :scheme => :query_string,
23
+ :http_method => :get
24
+ }
25
+
26
+ options[:authorize_params] = {:oauth_consumer_key => consumer_key}
27
+ super(app, :qzone, consumer_key, consumer_secret, client_options, options)
28
+ end
29
+
30
+ #HACK qzone is using a none-standard parameter oauth_overicode
31
+ def consumer_options
32
+ @consumer_options[:access_token_path] = '/oauth/qzoneoauth_access_token?oauth_vericode=' + request['oauth_vericode'] if request['oauth_vericode']
33
+ @consumer_options
34
+ end
35
+
36
+ def callback_phase
37
+ session['oauth'][name.to_s]['callback_confirmed'] = true
38
+ super
39
+ end
40
+
41
+ def auth_hash
42
+ ui = user_info
43
+ OmniAuth::Utils.deep_merge(super, {
44
+ 'uid' => ui['uid'],
45
+ 'user_info' => ui,
46
+ 'extra' => {'user_hash' => user_hash}
47
+ })
48
+ end
49
+
50
+ def user_info
51
+ user_hash = self.user_hash
52
+ {
53
+ 'uid' => @access_token.params[:openid],
54
+ 'nickname' => user_hash['nickname'],
55
+ 'name' => user_hash['nickname'],
56
+ 'image' => user_hash['figureurl'],
57
+ 'urls' => {
58
+ 'figureurl_1' => user_hash['figureurl_1'],
59
+ 'figureurl_2' => user_hash['figureurl_2'],
60
+ }
61
+ }
62
+ end
63
+
64
+ def user_hash
65
+ @user_hash ||= MultiJson.decode(@access_token.get("/user/get_user_info?format=json&openid=#{@access_token.params[:openid]}").body)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,79 +1,87 @@
1
1
  require 'omniauth/oauth'
2
2
  require 'multi_json'
3
+ require 'digest/md5'
4
+ require 'net/http'
3
5
 
4
6
  module OmniAuth
5
7
  module Strategies
6
-
7
8
  # Authenticate to Renren utilizing OAuth 2.0 and retrieve
8
9
  # basic user information.
9
10
  #
10
11
  # @example Basic Usage
11
12
  # use OmniAuth::Strategies::Renren, 'client_id', 'client_secret'
12
13
  class Renren < OAuth2
13
- autoload :Session, 'omniauth_china/strategies/renren/session'
14
- autoload :Service, 'omniauth_china/strategies/renren/service'
15
-
16
- class << self
17
- def api_key; @@api_key; end
18
- def secret_key; @@secret_key; end
19
- end
20
-
21
14
  # @param [Rack Application] app standard middleware application parameter
22
- # @param [String] client_id the application id as [registered on Renren](http://www.renren.com/developers/)
15
+ # @param [String] client_id the application id as [registered on Renren](http://dev.renren.com/)
23
16
  # @param [String] client_secret the application secret as registered on Renren
24
- # @option options [String] :scope ('email') comma-separated extended permissions such as `email` and `manage_pages`
17
+ # @option options [String] :scope ('publish_feed,status_update') comma-separated extended permissions such as `publish_feed` and `status_update`
25
18
  def initialize(app, client_id = nil, client_secret = nil, options = {}, &block)
26
- @@api_key = client_id
27
- @@secret_key = client_secret
28
- super(app, :renren, client_id, client_secret, {:site => 'https://graph.renren.com/', :access_token_path => "/oauth/token"}, options, &block)
19
+ client_options = {
20
+ :site => "http://graph.renren.com/",
21
+ :authorize_url => "/oauth/authorize",
22
+ :access_token_url => "/oauth/token"
23
+ }
24
+
25
+ super(app, :renren, client_id, client_secret, client_options, options, &block)
26
+ end
27
+
28
+ def user_data
29
+ @data ||= MultiJson.decode(Net::HTTP.post_form(URI.parse('http://api.renren.com/restserver.do'), signed_params).body)[0]
30
+ end
31
+
32
+ def signed_params
33
+ params = {}
34
+ params[:api_key] = client.id
35
+ params[:method] = "users.getInfo"
36
+ params[:call_id] = Time.now.to_i
37
+ params[:format] = "json"
38
+ params[:v] = "1.0"
39
+ params[:uids] = session_key["user"]["id"]
40
+ params[:session_key] = session_key["renren_token"]["session_key"]
41
+ params[:sig] = Digest::MD5.hexdigest(params.map {|k,v| "#{k}=#{v}"}.sort.join("") + client.secret)
42
+ params
29
43
  end
30
-
31
- def user_hash
32
- @data ||= MultiJson.decode(@access_token.get('/renren_api/session_key', { :oauth_token => @access_token.token }, { "Accept-Language" => "zh;"}))
33
- @renren_session ||= Renren::Session.new(@data)
44
+
45
+ def session_key
46
+ @session_key ||= MultiJson.decode(@access_token.get('/renren_api/session_key'))
34
47
  end
35
-
48
+
36
49
  def request_phase
37
- options[:scope] ||= "email"
38
- options[:response_type] ||= "code"
50
+ options[:scope] ||= "publish_feed"
39
51
  super
40
52
  end
41
-
42
- # need to have :grant_type=>"authorization_code" for renren to work
43
- def callback_phase
44
- if request.params['error'] || request.params['error_reason']
45
- raise CallbackError.new(request.params['error'], request.params['error_description'] || request.params['error_reason'], request.params['error_uri'])
53
+
54
+ def build_access_token
55
+ if renren_session.nil? || renrensession.empty?
56
+ super
57
+ else
58
+ @access_token = ::OAuth2::AccessToken.new(client, renren_session['access_token'])
46
59
  end
47
- verifier = request.params['code']
48
- @access_token = client.web_server.get_access_token(verifier, {:redirect_uri => callback_url, :grant_type=>"authorization_code" })
49
- @env['omniauth.auth'] = auth_hash
50
- call_app!
51
- rescue ::OAuth2::HTTPError, ::OAuth2::AccessDenied, CallbackError => e
52
- fail!(:invalid_credentials, e)
53
60
  end
54
-
55
- def auth_hash
56
- OmniAuth::Utils.deep_merge(super, {
57
- 'uid' => user_hash.uid,
58
- 'user_info' => user_info,
59
- 'extra' => {
60
- 'user_hash' => user_hash.user
61
- }
62
- })
61
+
62
+ def renren_session
63
+ session_cookie = request.cookies["rrs_#{client.id}"]
64
+ if session_cookie
65
+ @renren_session ||= Rack::Utils.parse_query(request.cookies["rrs_#{client.id}"].gsub('"', ''))
66
+ else
67
+ nil
68
+ end
63
69
  end
64
-
70
+
65
71
  def user_info
66
- user_hash = self.user_hash.user
67
72
  {
68
- 'username' => user_hash['name'],
69
- 'name' => user_hash['name'],
70
- 'image' => user_hash['tinyurl'],
71
- 'vip' => user_hash['vip'],
72
- 'headurl' => user_hash['headurl']
73
+ 'name' => user_data["name"],
74
+ 'image' => user_data["tinyurl"]
73
75
  }
74
76
  end
75
-
77
+
78
+ def auth_hash
79
+ OmniAuth::Utils.deep_merge(super, {
80
+ 'uid' => user_data['uid'],
81
+ 'user_info' => user_info,
82
+ 'extra' => {'user_hash' => user_data}
83
+ })
84
+ end
76
85
  end
77
-
78
86
  end
79
87
  end
@@ -1,3 +1,3 @@
1
1
  module OmniauthChina
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,5 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe OmniAuth::Strategies::Qzone do
4
+ it_should_behave_like "an oauth strategy"
5
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Qi He
@@ -68,9 +68,8 @@ files:
68
68
  - lib/omniauth_china.rb
69
69
  - lib/omniauth_china/oauth_china.rb
70
70
  - lib/omniauth_china/strategies/douban.rb
71
+ - lib/omniauth_china/strategies/qzone.rb
71
72
  - lib/omniauth_china/strategies/renren.rb
72
- - lib/omniauth_china/strategies/renren/service.rb
73
- - lib/omniauth_china/strategies/renren/session.rb
74
73
  - lib/omniauth_china/strategies/t163.rb
75
74
  - lib/omniauth_china/strategies/tqq.rb
76
75
  - lib/omniauth_china/strategies/tsina.rb
@@ -78,6 +77,7 @@ files:
78
77
  - lib/omniauth_china/version.rb
79
78
  - omniauth_china.gemspec
80
79
  - spec/omniauth_china/strategies/douban_spec.rb
80
+ - spec/omniauth_china/strategies/qzone_spec.rb
81
81
  - spec/omniauth_china/strategies/renren_spec.rb
82
82
  - spec/omniauth_china/strategies/t163_spec.rb
83
83
  - spec/omniauth_china/strategies/tqq_spec.rb
@@ -160,6 +160,7 @@ specification_version: 3
160
160
  summary: "OmniAuth extension: omniauth for china"
161
161
  test_files:
162
162
  - spec/omniauth_china/strategies/douban_spec.rb
163
+ - spec/omniauth_china/strategies/qzone_spec.rb
163
164
  - spec/omniauth_china/strategies/renren_spec.rb
164
165
  - spec/omniauth_china/strategies/t163_spec.rb
165
166
  - spec/omniauth_china/strategies/tqq_spec.rb
@@ -1,22 +0,0 @@
1
- require 'net/http'
2
- require 'pp'
3
-
4
- module OmniAuth
5
- module Strategies
6
- class Renren
7
- class Service
8
- DEBUG = false
9
-
10
- def post(params)
11
- pp "### Posting Params: #{params.inspect}" if DEBUG
12
- Net::HTTP.post_form(url, params)
13
- end
14
-
15
- private
16
- def url
17
- URI.parse('http://api.renren.com/restserver.do')
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,78 +0,0 @@
1
- require 'digest/md5'
2
- require 'multi_json'
3
-
4
- module OmniAuth
5
- module Strategies
6
- class Renren
7
- class Session
8
- class IncorrectSignature < Exception; end
9
- class SessionExpired < Exception; end
10
- class OtherException < Exception; end
11
-
12
- attr_reader :session_key
13
- attr_reader :expires
14
- attr_reader :uid
15
-
16
- def initialize(user_hash)
17
- @expires = user_hash['renren_token']['expires_in'] ? user_hash['renren_token']['expires_in'].to_i : 0
18
- @session_key = user_hash['renren_token']['session_key']
19
- @uid = user_hash['user']['id']
20
- end
21
-
22
- def user
23
- @user ||= invoke_method('users.getInfo', :uids => @uid, :format => :json).first
24
- end
25
-
26
- def infinite?
27
- @expires == 0
28
- end
29
-
30
- def expired?
31
- @expires.nil? || (!infinite? && Time.at(@expires) <= Time.now)
32
- end
33
-
34
- def secured?
35
- !@session_key.nil? && !expired?
36
- end
37
-
38
- def invoke_method(method, params = {})
39
- xn_params = {
40
- :method => method,
41
- :api_key => Renren.api_key,
42
- :session_key => session_key,
43
- :call_id => Time.now.to_i,
44
- :v => '1.0',
45
- :format => :json
46
- }
47
- xn_params.merge!(params) if params
48
- xn_params.merge!(:sig => compute_sig(xn_params))
49
- MultiJson.decode(Service.new.post(xn_params).body)
50
- end
51
-
52
- class << self
53
- private
54
- def verify_signature(renren_sig_params, expected_signature)
55
- raise Renren::Session::IncorrectSignature if compute_sig(renren_sig_params) != expected_signature
56
- # raise Renren::Session::SignatureTooOld if renren_sig_params['time'] && Time.at(renren_sig_params['time'].to_f) < earliest_valid_session
57
- true
58
- end
59
-
60
- def compute_sig(params)
61
- raw_string = params.collect {|*args| args.join('=') }.sort.join
62
- actual_sig = Digest::MD5.hexdigest([raw_string, Renren.secret_key].join)
63
- end
64
- end
65
-
66
- private
67
-
68
- def verify_signature(renren_sig_params, expected_signature)
69
- self.class.send :verify_signature, renren_sig_params, expected_signature
70
- end
71
-
72
- def compute_sig(params)
73
- self.class.send :compute_sig, params
74
- end
75
- end
76
- end
77
- end
78
- end