omniauth-wechat-oauth2 0.2.2 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7957db81f8a3ca70305b81820dfad15f36eb1e4995ce4decb99515f9763539cf
4
- data.tar.gz: d48c9cef8cb649a4b4c941f5d16328ea54cb13c21f8d9ab883a539defac22f99
3
+ metadata.gz: 80313d7db1a1d6df69ed886099adead9279872a8fb49de1b8b961a8483fd6276
4
+ data.tar.gz: db075a26ae635ab40180b0b3f937bbad0484111c06dd54d3512067424e31c74b
5
5
  SHA512:
6
- metadata.gz: a57cab028371e48d8f4e0c307e7172133c5b1a6715de8c8faaf63dc15702301e870a5192941427ed11c15f7b208b27af51ed260170002df34fc24d3d04fd74d1
7
- data.tar.gz: 1a2af84613bf942a76a72d462e5196ab907378f7ef2ac6cf014ebf40eab41f7a22a743c3acff775e836bb5dc0dd7232b63157d6d98066d1e2ecf4a0dac2da205
6
+ metadata.gz: 65f903b8e65eedb5017d1763919b92679e0f798eb3dd3df22d66067ba28e3e9d4492ed9b755249ec0b0cd57e53f7fcb61d058930b892c65a931bf756c686bc70
7
+ data.tar.gz: 1a95f075d1f32e42feca3ade502f874ca455832a8da6fc466c298f470fa28530773e256de98260c345f9adb83053d73da935576a02a2eb8adf0bddd72d48602c
checksums.yaml.gz.sig ADDED
Binary file
data/README.md CHANGED
@@ -3,11 +3,11 @@ Omniauth-wechat-oauth2
3
3
 
4
4
  [![Gem Version](https://img.shields.io/gem/v/omniauth-wechat-oauth2.svg)][gem]
5
5
  [![Security Check](https://hakiri.io/github/NeverMin/omniauth-wechat-oauth2/master.svg)][security]
6
- [![Build Status](https://travis-ci.org/NeverMin/omniauth-wechat-oauth2.svg)][travis]
6
+ [![Build Status](https://app.travis-ci.com/Eric-Guo/omniauth-wechat-oauth2.svg?branch=master)][travis]
7
7
 
8
8
  [gem]: https://rubygems.org/gems/omniauth-wechat-oauth2
9
9
  [security]: https://hakiri.io/github/NeverMin/omniauth-wechat-oauth2/master
10
- [travis]: https://travis-ci.org/NeverMin/omniauth-wechat-oauth2
10
+ [travis]: https://app.travis-ci.com/github/Eric-Guo/omniauth-wechat-oauth2
11
11
 
12
12
 
13
13
  Wechat OAuth2 Strategy for OmniAuth 1.0.
@@ -93,6 +93,37 @@ Here's an example of an authentication hash available in the callback by accessi
93
93
 
94
94
  ## Wechat Qiye OAuth2
95
95
 
96
+ Both enterprise strategies (`qiye_web` and `wechat_qiye`) require a successful
97
+ WeCom API response (`errcode: 0`) and a nonempty member `userid`. A corporate
98
+ access token does not authenticate a user: the callback's authorization code
99
+ must also resolve to a member. Invalid codes, API errors, malformed responses,
100
+ and nonmember identities fail authentication without invoking the application
101
+ callback. TLS certificate verification is enabled by default.
102
+
103
+ ### WeCom web login
104
+
105
+ ```ruby
106
+ config.omniauth :qiye_web, ENV['WECOM_CORP_ID'], ENV['WECOM_CORP_SECRET'],
107
+ agentid: ENV['WECOM_AGENT_ID']
108
+ ```
109
+
110
+ Start login through OmniAuth's POST request phase with your application's CSRF
111
+ protection. Keep `provider_ignores_state` at its default (`false`): the callback
112
+ must return the generated state in the same browser session. State is consumed
113
+ when checked, so a completed callback cannot be replayed. If valid logins fail
114
+ with `csrf_detected`, check the session cookie, callback host, and proxy/HTTPS
115
+ configuration instead of disabling state validation.
116
+
117
+ When upgrading an existing deployment, publish or pin the fixed gem revision,
118
+ update the application's lockfile, and restart its processes. A Bundler local
119
+ override only changes the developer's checkout. This fix does not invalidate
120
+ previously issued application sessions or tokens; revoke those associated with
121
+ any confirmed unauthorized login separately. Applications should also reject
122
+ blank `auth.uid` values before looking up local accounts and avoid logging the
123
+ full authentication hash, which contains credentials.
124
+
125
+ ### Legacy enterprise OAuth2
126
+
96
127
  Wechat Qiey usage and configuration are the same with normal account above.
97
128
 
98
129
  ```ruby
@@ -0,0 +1,59 @@
1
+ require "omniauth-oauth2"
2
+ require "omniauth/strategies/wecom_validation"
3
+
4
+ module OmniAuth
5
+ module Strategies
6
+ class QiyeWeb < OmniAuth::Strategies::OAuth2
7
+ include WecomValidation
8
+
9
+ option :name, 'qiye_web'
10
+
11
+ option :client_options, { site: 'https://qyapi.weixin.qq.com',
12
+ authorize_url: 'https://login.work.weixin.qq.com/wwlogin/sso/login',
13
+ token_url: '/cgi-bin/gettoken',
14
+ token_method: :get }
15
+
16
+ option :authorize_options, %i[agentid state login_type]
17
+ option :token_params, { parse: :json }
18
+ option :agentid, nil
19
+
20
+ uid do
21
+ raw_info
22
+ end
23
+
24
+ info do
25
+ { userid: uid }
26
+ end
27
+
28
+ extra do
29
+ { raw_info: nil }
30
+ end
31
+
32
+ # Inherit OAuth2#callback_phase so state, provider errors, and failures are
33
+ # checked before an authentication hash can reach the application.
34
+ def request_phase
35
+ raise ArgumentError, 'agentid is required for QiyeWeb strategy' if options.agentid.to_i <= 0
36
+
37
+ ap = authorize_params
38
+ params = {
39
+ 'login_type' => ap[:login_type] || 'CorpApp',
40
+ 'appid' => client.id,
41
+ 'agentid' => options.agentid,
42
+ 'redirect_uri' => callback_url,
43
+ 'state' => ap[:state]
44
+ }
45
+
46
+ redirect client.authorize_url(params)
47
+ end
48
+
49
+ def raw_info
50
+ @uid ||= begin
51
+ access_token.options[:mode] = :query
52
+ response = access_token.get('/cgi-bin/auth/getuserinfo',
53
+ params: { 'code' => authorization_code }, parse: :json)
54
+ wecom_userid(wecom_response(response))
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -52,7 +52,7 @@ module OmniAuth
52
52
  @uid ||= access_token["openid"]
53
53
  @raw_info ||= begin
54
54
  access_token.options[:mode] = :query
55
- if access_token["scope"]&.include?("snsapi_login")
55
+ if ["snsapi_login", "snsapi_userinfo"].include?(access_token["scope"])
56
56
  access_token.get("/sns/userinfo", :params => { "openid" => @uid, "lang" => "zh_CN" }, parse: :json).parsed
57
57
  else
58
58
  { "openid" => @uid }
@@ -1,18 +1,18 @@
1
1
  require "omniauth-oauth2"
2
+ require "omniauth/strategies/wecom_validation"
2
3
 
3
4
  module OmniAuth
4
5
  module Strategies
5
6
  class WechatQiye < OmniAuth::Strategies::OAuth2
7
+ include WecomValidation
8
+
6
9
  option :name, "wechat_qiye"
7
10
 
8
11
  option :client_options, {
9
12
  :site => "https://qyapi.weixin.qq.com",
10
13
  authorize_url: "https://open.weixin.qq.com/connect/oauth2/authorize#wechat_redirect",
11
14
  token_url: "/cgi-bin/gettoken",
12
- token_method: :get,
13
- connection_opts: {
14
- ssl: { verify: false }
15
- }
15
+ token_method: :get
16
16
  }
17
17
 
18
18
  option :authorize_params, {scope: "snsapi_userinfo"}
@@ -46,35 +46,23 @@ module OmniAuth
46
46
  end
47
47
 
48
48
  def raw_info
49
- # step 2: get userid via code and access_token
50
- @code ||= access_token[:code]
51
-
52
- # step 3: get user info via userid
53
49
  @uid ||= begin
54
50
  access_token.options[:mode] = :query
55
- response = access_token.get('/cgi-bin/user/getuserinfo', :params => {'code' => @code}, parse: :json)
56
- response.parsed['UserId']
51
+ response = access_token.get('/cgi-bin/user/getuserinfo',
52
+ :params => {'code' => authorization_code}, parse: :json)
53
+ wecom_userid(wecom_response(response))
57
54
  end
58
55
 
59
56
  @raw_info ||= begin
60
57
  access_token.options[:mode] = :query
61
58
  response = access_token.get("/cgi-bin/user/get", :params => {"userid" => @uid}, parse: :json)
62
- response.parsed
59
+ data = wecom_response(response)
60
+ unless wecom_userid(data).casecmp(@uid).zero?
61
+ raise CallbackError.new(:invalid_uid, 'WeCom member profile does not match the authenticated userid')
62
+ end
63
+ data
63
64
  end
64
65
  end
65
-
66
- protected
67
- def build_access_token
68
- # step 0: wechat respond code
69
- code = request.params['code']
70
-
71
- # step 1: get access token
72
- params = {
73
- 'corpid' => client.id,
74
- 'corpsecret' => client.secret,
75
- }.merge(token_params.to_hash(symbolize_keys: true))
76
- client.get_token(params, deep_symbolize(options.auth_token_params.merge({code: code})))
77
- end
78
66
  end
79
67
  end
80
68
  end
@@ -0,0 +1,62 @@
1
+ module OmniAuth
2
+ module Strategies
3
+ # WeCom returns API failures as HTTP 200 responses. A corporate access token
4
+ # alone does not authenticate the user presenting the callback code.
5
+ module WecomValidation
6
+ protected
7
+
8
+ def secure_compare(left, right)
9
+ return false unless left.is_a?(String) && right.is_a?(String)
10
+
11
+ super
12
+ end
13
+
14
+ def authorization_code
15
+ code = request.params['code']
16
+ unless code.is_a?(String) && !code.strip.empty?
17
+ raise OAuth2::CallbackError.new(:invalid_code, 'Missing or invalid WeCom authorization code')
18
+ end
19
+
20
+ code
21
+ end
22
+
23
+ def build_access_token
24
+ authorization_code
25
+ params = {
26
+ 'corpid' => client.id,
27
+ 'corpsecret' => client.secret
28
+ }.merge(token_params.to_hash(symbolize_keys: true))
29
+
30
+ client.get_token(params, deep_symbolize(options.auth_token_params)).tap do |token|
31
+ unless token && token.token.is_a?(String) && !token.token.strip.empty?
32
+ raise OAuth2::CallbackError.new(:invalid_token, 'Missing WeCom access token')
33
+ end
34
+ validate_wecom_response(token.params)
35
+ end
36
+ end
37
+
38
+ def wecom_response(response)
39
+ validate_wecom_response(response.parsed)
40
+ end
41
+
42
+ def validate_wecom_response(data)
43
+ unless data.is_a?(Hash) && data['errcode'] == 0
44
+ raise OAuth2::CallbackError.new(:invalid_response, 'WeCom API did not return a successful response')
45
+ end
46
+
47
+ data
48
+ end
49
+
50
+ def wecom_userid(data)
51
+ # Support both the current API and the legacy UserId response. OAuth2's
52
+ # SnakyHash also accepts the original spelling of normalized keys.
53
+ userid = data['userid'] || data['UserId']
54
+ unless userid.is_a?(String) && !userid.strip.empty?
55
+ raise OAuth2::CallbackError.new(:invalid_uid, 'WeCom did not return a member userid')
56
+ end
57
+
58
+ userid
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,2 +1,3 @@
1
1
  require "omniauth/strategies/wechat"
2
2
  require "omniauth/strategies/wechat_qiye"
3
+ require "omniauth/strategies/qiye_web"
data.tar.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ ��d�;�I �;�߼"� v�؉d�E+����;�1� �栁|����;AD�d.�!�u�c�̜B�N����8���cCY�`��cv~�Y�v(q�����|���yw��F�ٙ�*���#"H�2����ö�;Xh���� ����X�ؙ�l��{��IB9��
2
+ �nGo�sp?��o �P�ݳ6�1!6�x�4��2����;������Waj�6�4%k���z-�v��4='!���E��8t1��I�����6F�K�B��.���*�>��l��٬ޡ;���s��PG�b���cvd�r
metadata CHANGED
@@ -1,59 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-wechat-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Hu
8
8
  - Never Min
9
9
  - Eric Guo
10
- autorequire:
11
10
  bindir: bin
12
- cert_chain: []
13
- date: 2020-06-12 00:00:00.000000000 Z
11
+ cert_chain:
12
+ - |
13
+ -----BEGIN CERTIFICATE-----
14
+ MIIEeDCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBBMRMwEQYDVQQDDAplcmlj
15
+ Lmd1b2N6MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
16
+ b20wHhcNMjYwNTIyMTUyNDI0WhcNMjcwNTIyMTUyNDI0WjBBMRMwEQYDVQQDDApl
17
+ cmljLmd1b2N6MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
18
+ FgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC49ueF2WFVqQye
19
+ d1kwtvBNyXx9AI8fLWwLHJqf+3ojjWEYwf8NtwYbBgptw7sMDfbpu+H0TjLSYW9e
20
+ R5IVlfP0v55JtDNjZLnQTtXxaiGLZ9aZgT1t5Rn42RSYqfjLKN2maKpRUCnw8Tw4
21
+ +G1tdxFnYIsHda7jiNvetZjqeVhaoN4enfPk2pTeHpmXvH/FzLuKRkPz0yQOFD6P
22
+ IFdE1a4sPs7Fk9QJa6zyPQ/7cL1Uu+IjNzibvTot+Go1GtWvc7bqdDueX6MSo9Ki
23
+ 7XBVH4Svk9BqGKKCJFibYjBRxMbzlwA8fik9JUKj9Q0gmXeRRf+tQUZWJHKF5Y/4
24
+ wzqyT6k4u5e3S/QnpD/ZNo1ESiu1Bxc6KvlIihKlOvA8+RSgSAmZtcHhk2en4DtP
25
+ aeBgCrJABFbkMVk9+OiRcq1kDAIJHnH9XxyrM/s4x5FYPgZWbqfbYltHp+Y9ByNw
26
+ uzG6YQkT6PkKRAdl8i6udI70iLQZIE8sI+4bwl3JnTfDrJsklhsCAwEAAaN7MHkw
27
+ CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFAAS4PVX34FrNYW9Iv16
28
+ R4Qyoj1CMB8GA1UdEQQYMBaBFGVyaWMuZ3VvY3pAZ21haWwuY29tMB8GA1UdEgQY
29
+ MBaBFGVyaWMuZ3VvY3pAZ21haWwuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQBFdbRh
30
+ Wh50P882h5BMysO8Ru/cnqUENIsHxUnZsssHuFcU3Gn3Sq43ixKzFhA4uOCDfY36
31
+ xvX7johxHhukDAdo4lD9h+f5Vck35Qns5Ln+b0o0iTyENOFou57CgeqpWeVkDIi4
32
+ vlwdgCunr64KKW7snC4E76AUXRnOYC0UhZL2VQRc54sN6eMIACogJ9ZHii3h5FmG
33
+ ep6LMfi1oKBrU7MLT5BidvCxG3ePEtdfACGznDE7GgimLVcsb3Ft+sNeP6fBtvrM
34
+ OljHZezOIi+Wbot4pvwdt8tCI4eCoAWAYuoCtyav5dDRUeqI7TPdQGgMPDcVckNE
35
+ e3iKcBAe/0pRYSZxORE63n3SOo9MPL2oGe9A21LR/tk/CJ8kZxDdeTh4zL+Ufw3R
36
+ G4TR+pkSPTTDPI2Ft/RAqHjqectqrcz4gZ4e/x1nBhoF8QKrBuEvHXNTR5EtMzcz
37
+ CU8I1U00X8GGbinHiVIfDJnOkCq7cBmbTamZpNwZLCrgQupqUNhEP2vcZVg=
38
+ -----END CERTIFICATE-----
39
+ date: 1980-01-02 00:00:00.000000000 Z
14
40
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: omniauth
17
- requirement: !ruby/object:Gem::Requirement
18
- requirements:
19
- - - ">="
20
- - !ruby/object:Gem::Version
21
- version: 1.3.2
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- version: 1.3.2
29
41
  - !ruby/object:Gem::Dependency
30
42
  name: omniauth-oauth2
31
43
  requirement: !ruby/object:Gem::Requirement
32
44
  requirements:
33
45
  - - ">="
34
46
  - !ruby/object:Gem::Version
35
- version: 1.1.1
47
+ version: 1.8.0
36
48
  type: :runtime
37
49
  prerelease: false
38
50
  version_requirements: !ruby/object:Gem::Requirement
39
51
  requirements:
40
52
  - - ">="
41
53
  - !ruby/object:Gem::Version
42
- version: 1.1.1
54
+ version: 1.8.0
43
55
  - !ruby/object:Gem::Dependency
44
56
  name: rspec
45
57
  requirement: !ruby/object:Gem::Requirement
46
58
  requirements:
47
59
  - - "~>"
48
60
  - !ruby/object:Gem::Version
49
- version: '2.99'
61
+ version: 3.13.1
50
62
  type: :development
51
63
  prerelease: false
52
64
  version_requirements: !ruby/object:Gem::Requirement
53
65
  requirements:
54
66
  - - "~>"
55
67
  - !ruby/object:Gem::Version
56
- version: '2.99'
68
+ version: 3.13.1
57
69
  description: Using OAuth2 to authenticate wechat user when web resources being viewed
58
70
  within wechat(weixin) client.
59
71
  email:
@@ -66,14 +78,15 @@ extra_rdoc_files: []
66
78
  files:
67
79
  - README.md
68
80
  - lib/omniauth-wechat-oauth2.rb
81
+ - lib/omniauth/strategies/qiye_web.rb
69
82
  - lib/omniauth/strategies/wechat.rb
70
83
  - lib/omniauth/strategies/wechat_qiye.rb
84
+ - lib/omniauth/strategies/wecom_validation.rb
71
85
  - lib/omniauth/wechat.rb
72
86
  homepage: https://github.com/nevermin/omniauth-wechat-oauth2
73
87
  licenses:
74
88
  - MIT
75
89
  metadata: {}
76
- post_install_message:
77
90
  rdoc_options: []
78
91
  require_paths:
79
92
  - lib
@@ -89,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
102
  version: '0'
90
103
  requirements:
91
104
  - none
92
- rubygems_version: 3.1.4
93
- signing_key:
105
+ rubygems_version: 4.0.22
94
106
  specification_version: 4
95
107
  summary: Omniauth strategy for wechat(weixin)
96
108
  test_files: []
metadata.gz.sig ADDED
Binary file