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.
- data/README.markdown +9 -7
- data/lib/omniauth_china/oauth_china.rb +1 -0
- data/lib/omniauth_china/strategies/qzone.rb +69 -0
- data/lib/omniauth_china/strategies/renren.rb +58 -50
- data/lib/omniauth_china/version.rb +1 -1
- data/spec/omniauth_china/strategies/qzone_spec.rb +5 -0
- metadata +5 -4
- data/lib/omniauth_china/strategies/renren/service.rb +0 -22
- data/lib/omniauth_china/strategies/renren/session.rb +0 -78
data/README.markdown
CHANGED
@@ -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
|
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: [
|
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
|
|
@@ -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://
|
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 ('
|
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
|
-
|
27
|
-
|
28
|
-
|
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
|
32
|
-
@
|
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] ||= "
|
38
|
-
options[:response_type] ||= "code"
|
50
|
+
options[:scope] ||= "publish_feed"
|
39
51
|
super
|
40
52
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
56
|
-
|
57
|
-
|
58
|
-
'
|
59
|
-
|
60
|
-
|
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
|
-
'
|
69
|
-
'
|
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
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
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
|