omniauth_china 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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