From 881300c20f1166baf3326a70770ca94e5c35dd79 Mon Sep 17 00:00:00 2001 From: bastengao Date: Sun, 12 Jul 2015 20:15:08 +0800 Subject: [PATCH 01/24] add wechat qiye documentation --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2878f3..91fb7eb 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Wechat OAuth2 Strategy for OmniAuth 1.0. You need to get a wechat API key at: https://mp.weixin.qq.com -Wechat oauth2 specification can be found at: https://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息 +* Wechat oauth2 specification can be found at: https://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息 +* Wechat Qiye oauth2 specification can be found at: http://qydev.weixin.qq.com/wiki/index.php?title=OAuth验证接口 ## Installation @@ -88,6 +89,48 @@ Here's an example of an authentication hash available in the callback by accessi } ``` +## Wechat Qiye OAuth2 +Wechat Qiey usage and configuration are the same with normal account above. +```ruby +config.omniauth :wechat_qiye, ENV["WECHAT_APP_ID"], ENV["WECHAT_APP_SECRET"], + :authorize_params => {:scope => "snsapi_base"} +``` +Auth hash `request.env["omniauth.auth"]` + +```ruby +{ + :provider => "wechat_qiye", + :uid => "123456789", + :info => { + userid: "userid", + name: "name", + department: [2], + gender: "1", + weixinid: "weixinid", + avatar: "avatar", + status: 1, + extattr: {"foo" => "bar"} + }, + :credentials => { + :token => "token", + :refresh_token => "another_token", + :expires_at => 7200, + :expires => true + }, + :extra => { + :raw_info => { + userid: "userid", + name: "name", + department: [2], + gender: "1", + weixinid: "weixinid", + avatar: "avatar", + status: 1, + extattr: {"foo" => "bar"}} + } + } +} +``` From ef014c5ef63d03e8f7260914a7a3a75e4897d901 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Tue, 9 Jun 2020 14:11:50 +0100 Subject: [PATCH 02/24] Add image field to user info hash This information is meant to be as normalized as possible, so the schema below will be filled to the greatest degree available given the provider upon authentication. Fields marked required will always be present. Note that this guide may also be useful to developers implementing custom strategies to know how to provide results. https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema --- lib/omniauth/strategies/wechat.rb | 1 + spec/omniauth/strategies/wechat_spec.rb | 35 ++++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/omniauth/strategies/wechat.rb b/lib/omniauth/strategies/wechat.rb index c36bbe3..2302d24 100644 --- a/lib/omniauth/strategies/wechat.rb +++ b/lib/omniauth/strategies/wechat.rb @@ -32,6 +32,7 @@ def callback_url city: raw_info['city'], country: raw_info['country'], headimgurl: raw_info['headimgurl'], + image: raw_info['headimgurl'], unionid: raw_info['unionid'] } end diff --git a/spec/omniauth/strategies/wechat_spec.rb b/spec/omniauth/strategies/wechat_spec.rb index 14aa9be..7f5d3fa 100644 --- a/spec/omniauth/strategies/wechat_spec.rb +++ b/spec/omniauth/strategies/wechat_spec.rb @@ -125,26 +125,41 @@ expect(opts[:parse]).to eq(:json) end.and_return(double("response", parsed: { - openid: "OPENID", - nickname: "NICKNAME", - sex: "1", - province: "PROVINCE", - city: "CITY", - country: "COUNTRY", - headimgurl: "header_image_url", - privilege: ["PRIVILEGE1", "PRIVILEGE2"] + "openid" => "OPENID", + "nickname" => "NICKNAME", + "sex" => "1", + "province" => "PROVINCE", + "city" => "CITY", + "country" => "COUNTRY", + "headimgurl" => "header_image_url", + "privilege" => ["PRIVILEGE1", "PRIVILEGE2"], + "unionid" => "UNIONID" } )) + expect(subject.raw_info).to eq( { - openid: "OPENID", + "openid" => "OPENID", + "nickname" => "NICKNAME", + "sex" => "1", + "province" => "PROVINCE", + "city" => "CITY", + "country" => "COUNTRY", + "headimgurl" => "header_image_url", + "privilege" => ["PRIVILEGE1", "PRIVILEGE2"], + "unionid" => "UNIONID" + } + ) + expect(subject.info).to eq( + { nickname: "NICKNAME", sex: "1", province: "PROVINCE", city: "CITY", country: "COUNTRY", headimgurl: "header_image_url", - privilege: ["PRIVILEGE1", "PRIVILEGE2"] + image: "header_image_url", + unionid: "UNIONID" } ) end From fe87ffbf69fa8c8dcce1a590ff2f0b8364c4d157 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Wed, 10 Jun 2020 11:52:22 +0100 Subject: [PATCH 03/24] Fix require --- lib/omniauth-wechat-oauth2.rb | 3 +-- lib/omniauth/wechat.rb | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 lib/omniauth/wechat.rb diff --git a/lib/omniauth-wechat-oauth2.rb b/lib/omniauth-wechat-oauth2.rb index b0bbfeb..e88ed9f 100644 --- a/lib/omniauth-wechat-oauth2.rb +++ b/lib/omniauth-wechat-oauth2.rb @@ -1,2 +1 @@ -require "omniauth/strategies/wechat" -require "omniauth/strategies/wechat_qiye" +require "omniauth/wechat" diff --git a/lib/omniauth/wechat.rb b/lib/omniauth/wechat.rb new file mode 100644 index 0000000..b0bbfeb --- /dev/null +++ b/lib/omniauth/wechat.rb @@ -0,0 +1,2 @@ +require "omniauth/strategies/wechat" +require "omniauth/strategies/wechat_qiye" From 5390abd0fe2dfa8fc7f0acc1f3b079bd1f5d77ee Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Thu, 11 Jun 2020 15:46:38 +0800 Subject: [PATCH 04/24] Release 0.2.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0ea3a94..0c62199 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.2.1 From 293e0f84669fbe03031e03311f93f95a6b6cf494 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Fri, 12 Jun 2020 08:21:12 +0800 Subject: [PATCH 05/24] Release 0.2.2, which only fix file permission. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0c62199..ee1372d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.1 +0.2.2 From cea72f160054ff7de3ce23c9d8a62f909f2d4cd0 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Mon, 6 Sep 2021 11:35:28 +0800 Subject: [PATCH 06/24] Fix deprecated sync. https://github.com/rspec/rspec-mocks/issues/377 --- spec/omniauth/strategies/wechat_qiye_spec.rb | 2 +- spec/omniauth/strategies/wechat_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/omniauth/strategies/wechat_qiye_spec.rb b/spec/omniauth/strategies/wechat_qiye_spec.rb index 13c692a..1a87fcb 100644 --- a/spec/omniauth/strategies/wechat_qiye_spec.rb +++ b/spec/omniauth/strategies/wechat_qiye_spec.rb @@ -59,7 +59,7 @@ callback_url = "http://exammple.com/callback" subject.stub(:callback_url=>callback_url) - subject.should_receive(:redirect).with do |redirect_url| + expect(subject).to receive(:redirect) do |redirect_url| uri = URI.parse(redirect_url) expect(uri.fragment).to eq("wechat_redirect") params = CGI::parse(uri.query) diff --git a/spec/omniauth/strategies/wechat_spec.rb b/spec/omniauth/strategies/wechat_spec.rb index 7f5d3fa..231e563 100644 --- a/spec/omniauth/strategies/wechat_spec.rb +++ b/spec/omniauth/strategies/wechat_spec.rb @@ -60,7 +60,7 @@ callback_url = "http://exammple.com/callback" subject.stub(:callback_url=>callback_url) - subject.should_receive(:redirect).with do |redirect_url| + expect(subject).to receive(:redirect) do |redirect_url| uri = URI.parse(redirect_url) expect(uri.fragment).to eq("wechat_redirect") params = CGI::parse(uri.query) @@ -118,7 +118,7 @@ })} specify "will query for user info" do - client.should_receive(:request).with do |verb, path, opts| + expect(client).to receive(:request) do |verb, path, opts| expect(verb).to eq(:get) expect(path).to eq("/sns/userinfo") expect(opts[:params]).to eq("openid"=> "openid", "lang"=>"zh_CN", "access_token"=> "access_token") From f534a3eb3719e997f8033ef7e3952dcc2d5cc2fc Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Mon, 6 Sep 2021 11:36:22 +0800 Subject: [PATCH 07/24] Now can bump the rspec. --- omniauth-wechat-oauth2.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omniauth-wechat-oauth2.gemspec b/omniauth-wechat-oauth2.gemspec index 8e16166..cb8e08d 100644 --- a/omniauth-wechat-oauth2.gemspec +++ b/omniauth-wechat-oauth2.gemspec @@ -19,5 +19,5 @@ Gem::Specification.new do |s| s.add_dependency 'omniauth', '>= 1.3.2' s.add_dependency 'omniauth-oauth2', '>= 1.1.1' - s.add_development_dependency 'rspec', '~> 2.99' + s.add_development_dependency 'rspec', '~> 3.10.0' end From 23ce82c7522f227cd6d07592774f73b98db03042 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Mon, 6 Sep 2021 11:48:39 +0800 Subject: [PATCH 08/24] Change CI links. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23b555d..e7127b8 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ Omniauth-wechat-oauth2 [![Gem Version](https://img.shields.io/gem/v/omniauth-wechat-oauth2.svg)][gem] [![Security Check](https://hakiri.io/github/NeverMin/omniauth-wechat-oauth2/master.svg)][security] -[![Build Status](https://travis-ci.org/NeverMin/omniauth-wechat-oauth2.svg)][travis] +[![Build Status](https://app.travis-ci.com/Eric-Guo/omniauth-wechat-oauth2.svg?branch=master)][travis] [gem]: https://rubygems.org/gems/omniauth-wechat-oauth2 [security]: https://hakiri.io/github/NeverMin/omniauth-wechat-oauth2/master -[travis]: https://travis-ci.org/NeverMin/omniauth-wechat-oauth2 +[travis]: https://app.travis-ci.com/github/Eric-Guo/omniauth-wechat-oauth2 Wechat OAuth2 Strategy for OmniAuth 1.0. From 6bb939e624e156c0455d7c3e3148d9197e015f59 Mon Sep 17 00:00:00 2001 From: Never Date: Thu, 14 Oct 2021 17:58:50 +0800 Subject: [PATCH 09/24] update rake to 12.3.3 for CVE-2020-8130 ref: https://github.com/advisories/GHSA-jppv-gw3r-w3q8 --- Gemfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index ceeb54e..fb76afb 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ source "https://rubygems.org" -gem "rake", "~> 11.3.0" + + +gem "rake", ">= 12.3.3" gem 'byebug' gemspec From 383d7750c02be9dfa32f52fa89a5aa02cccbdcec Mon Sep 17 00:00:00 2001 From: moioo Date: Fri, 11 Nov 2022 18:32:09 +0800 Subject: [PATCH 10/24] Update wechat.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持公众号网页授权scope snsapi_userinfo --- lib/omniauth/strategies/wechat.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/omniauth/strategies/wechat.rb b/lib/omniauth/strategies/wechat.rb index 2302d24..0bb0019 100644 --- a/lib/omniauth/strategies/wechat.rb +++ b/lib/omniauth/strategies/wechat.rb @@ -52,7 +52,7 @@ def raw_info @uid ||= access_token["openid"] @raw_info ||= begin access_token.options[:mode] = :query - if access_token["scope"]&.include?("snsapi_login") + if ["snsapi_login", "snsapi_userinfo"].include?(access_token["scope"]) access_token.get("/sns/userinfo", :params => { "openid" => @uid, "lang" => "zh_CN" }, parse: :json).parsed else { "openid" => @uid } From 20ec8a8d761d111695d0d4c69df6f5f31d11af21 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Sun, 19 Feb 2023 11:21:16 +0800 Subject: [PATCH 11/24] omniauth-oauth2 >= 1.8.0 depends on omniauth ~> 2.0 --- omniauth-wechat-oauth2.gemspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/omniauth-wechat-oauth2.gemspec b/omniauth-wechat-oauth2.gemspec index cb8e08d..4f3d4ff 100644 --- a/omniauth-wechat-oauth2.gemspec +++ b/omniauth-wechat-oauth2.gemspec @@ -17,7 +17,6 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/nevermin/omniauth-wechat-oauth2' s.license = 'MIT' - s.add_dependency 'omniauth', '>= 1.3.2' - s.add_dependency 'omniauth-oauth2', '>= 1.1.1' + s.add_dependency 'omniauth-oauth2', '>= 1.7.3' s.add_development_dependency 'rspec', '~> 3.10.0' end From 2bfe46480059e065d37afd98fe269af040676e7d Mon Sep 17 00:00:00 2001 From: Eric Guo Date: Sun, 19 Feb 2023 13:03:08 +0800 Subject: [PATCH 12/24] Release 0.2.3 and signing. --- VERSION | 2 +- certs/Eric-Guo.pem | 26 ++++++++++++++++++++++++++ omniauth-wechat-oauth2.gemspec | 3 +++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 certs/Eric-Guo.pem diff --git a/VERSION b/VERSION index ee1372d..7179039 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.2 +0.2.3 diff --git a/certs/Eric-Guo.pem b/certs/Eric-Guo.pem new file mode 100644 index 0000000..099611d --- /dev/null +++ b/certs/Eric-Guo.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEeDCCAuCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBBMRMwEQYDVQQDDAplcmlj +Lmd1b2N6MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj +b20wHhcNMjIxMjA5MDcyMTE1WhcNMjMxMjA5MDcyMTE1WjBBMRMwEQYDVQQDDApl +cmljLmd1b2N6MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ +FgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC6jGarls5mU792 +leWot9tWKXnnvVnj1oUPea8M77PpHcYMVmjUTkjgsrKiOFNv2nAjUIDrUaLJvuKi +95zZYLIT3uWqI9QvSSDr+rs4HyIDcXuWWB89GpKN5WgyCVel6V9X5PN0C5hIiz8T +ThW7ZqkS8mTmHm2micL8/lmnelpxj9EjCin7xOCvebB9pdA7Y0kXMLbnRq4QK2lB +O2YRbLvYKWOQfO/sqLlwFsNWMNkj5ZROIqmKRvOHQdchox2RfBNsWRZ7XH8tTW1L +cqx95dI2qC6Xg+IHjN4Wc6n+Ak1KENlVjI4mGcuk+34d1S9gaZT8vW/cYcL30Nbg +AAUQvS4AQ8gmAkk1+oNs+725QLBprbnSN5PJr9VQiDteNHHkY5ugjndeAByOGy8h +/TgV4tBZQ0IT37ZRDcP4dayFMm2DVjS4uU7RUXLgc8sdOGeMmsFwdz9QrBPGeKsV +4+dXjrzzUvwRX4K21mx4ZSP9eSOscOEuzRIRTnab0GniDhkkHc8CAwEAAaN7MHkw +CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFPGkToJNhoEfhsOYqnTH +MZDYyjQtMB8GA1UdEQQYMBaBFGVyaWMuZ3VvY3pAZ21haWwuY29tMB8GA1UdEgQY +MBaBFGVyaWMuZ3VvY3pAZ21haWwuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQCdTl5T +qfcrbo4KdgZM84ZbeiUIXcRy/chbfQfPZ/qPp7qKARLxRJINmaqt/bP+RrlQypEe +1EIYhbxLGo1TvpbRFuADUhZjGZ8Vaa+bgPfj8Dxa71ow5dF9nrqidddV7qjmk57F +klOrOl+99Ryx01OAdlxGZqz/VrHrzbhQNtiUl2BYnosZLddYPTzuhNLe72eIypkY +synsOqoXRuegCtO4sSGSvRV79/GyN0jqtptpa61MaxgYG13+P8QwXeTo2Ro86ZAJ +h+KBs65p0MiFHl6zc2oany9Pk0kqs50TDKOCT7ZdSxz5xes0SvTi3mmX3XemjQhm +qNb+5zsj4Kn5auKYA7GupfLYKS/dYt4EIfNKhSEHgkVFdVPxSAQ73UAWsndINTTA +HjK18j09PoL9vWMUtyez2xpxlRDA+bEkF74AEVwMYozjP8VNM1ERTG+8kROuQjGV +aWhGk3yVuHjmlBvfDpPqmux3ulWXnvHulcYiPxETh/m3PUfIKMTHydjAz88= +-----END CERTIFICATE----- diff --git a/omniauth-wechat-oauth2.gemspec b/omniauth-wechat-oauth2.gemspec index 4f3d4ff..c443446 100644 --- a/omniauth-wechat-oauth2.gemspec +++ b/omniauth-wechat-oauth2.gemspec @@ -12,6 +12,9 @@ Gem::Specification.new do |s| s.requirements << 'none' s.required_ruby_version = '>= 2.4.0' + s.cert_chain = ['certs/Eric-Guo.pem'] + s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $PROGRAM_NAME.end_with?('gem') + s.author = ['Alex Hu', 'Never Min', 'Eric Guo'] s.email = ['askinnyworm@gmail.com', 'Never.Min@gmail.com', 'eric@cloud-mes.com'] s.homepage = 'https://github.com/nevermin/omniauth-wechat-oauth2' From 289e47caec9bff6e0df00d0ad28671925be4d456 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Sat, 25 Feb 2023 17:52:03 +0800 Subject: [PATCH 13/24] Try omniauth-oauth2 v1.8.0 --- VERSION | 2 +- omniauth-wechat-oauth2.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 7179039..0d91a54 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.3 +0.3.0 diff --git a/omniauth-wechat-oauth2.gemspec b/omniauth-wechat-oauth2.gemspec index c443446..19eb51c 100644 --- a/omniauth-wechat-oauth2.gemspec +++ b/omniauth-wechat-oauth2.gemspec @@ -20,6 +20,6 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/nevermin/omniauth-wechat-oauth2' s.license = 'MIT' - s.add_dependency 'omniauth-oauth2', '>= 1.7.3' + s.add_dependency 'omniauth-oauth2', '>= 1.8.0' s.add_development_dependency 'rspec', '~> 3.10.0' end From 53a6bb271afe3834e87cfe561757c8937998ae2b Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Tue, 12 Aug 2025 15:36:12 +0800 Subject: [PATCH 14/24] =?UTF-8?q?=E2=9C=A8Please=20add=20a=20new=20class?= =?UTF-8?q?=20OmniAuth::Strategies::QiyeWeb,=20the=20class=20is=20similar?= =?UTF-8?q?=20to=20current=20WechatQiye,=20but=20it=20should=20based=20on?= =?UTF-8?q?=20@https://developer.work.weixin.qq.com/document/path/98152=20?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E9=93=BE=E6=8E=A5=20You=20can=20get=20further=20info?= =?UTF-8?q?=20from=20@https://developer.work.weixin.qq.com/document/path/9?= =?UTF-8?q?8176=20=20and=20@https://developer.work.weixin.qq.com/document/?= =?UTF-8?q?path/98151=20,=20please=20do=20not=20using=20=20wecom/jssdk=20?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E7=BB=84=E4=BB=B6,=20only=20construct=20the?= =?UTF-8?q?=20URL=20in=20QiyeWeb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/omniauth/strategies/qiye_web.rb | 104 ++++++++++++++++++++++++++++ lib/omniauth/wechat.rb | 1 + 2 files changed, 105 insertions(+) create mode 100644 lib/omniauth/strategies/qiye_web.rb diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb new file mode 100644 index 0000000..e764ede --- /dev/null +++ b/lib/omniauth/strategies/qiye_web.rb @@ -0,0 +1,104 @@ +require "omniauth-oauth2" + +module OmniAuth + module Strategies + class QiyeWeb < OmniAuth::Strategies::OAuth2 + option :name, "qiye_web" + + option :client_options, { + site: "https://qyapi.weixin.qq.com", + authorize_url: "https://open.work.weixin.qq.com/wwopen/sso/qrConnect", + token_url: "/cgi-bin/gettoken", + token_method: :get, + connection_opts: { + ssl: { verify: false } + } + } + + # Allow passing these via strategy options or per-request params + option :authorize_options, [:agentid, :state, :login_type, :lang, :href] + + option :token_params, { parse: :json } + + # Required option for WeCom web login + option :agentid, nil + + uid do + raw_info['userid'] + end + + info do + { + userid: raw_info['userid'], + name: raw_info['name'], + department: raw_info['department'], + gender: raw_info['gender'], + weixinid: raw_info['weixinid'], + avatar: raw_info['avatar'], + status: raw_info['status'], + extattr: raw_info['extattr'] + } + end + + extra do + { raw_info: raw_info } + end + + def request_phase + # Build WeCom web login URL per docs: qrConnect requires appid (corp id), agentid, redirect_uri, state, etc. + ap = authorize_params.dup + ap['agentid'] ||= options.agentid + ap['login_type'] ||= 'CorpApp' + + raise ArgumentError, 'agentid is required for QiyeWeb strategy' if ap['agentid'].to_s.strip.empty? + + params = { + 'appid' => client.id, + 'agentid' => ap['agentid'], + 'redirect_uri' => callback_url + } + params['state'] = ap['state'] if ap['state'] + params['login_type'] = ap['login_type'] if ap['login_type'] + params['lang'] = ap['lang'] if ap['lang'] + params['href'] = ap['href'] if ap['href'] + + redirect client.authorize_url(params) + end + + def raw_info + # step 2: get userid via code and access_token + @code ||= access_token[:code] + + # step 3: get user info via userid + @uid ||= begin + access_token.options[:mode] = :query + response = access_token.get('/cgi-bin/user/getuserinfo', params: { 'code' => @code }, parse: :json) + response.parsed['UserId'] + end + + @raw_info ||= begin + access_token.options[:mode] = :query + response = access_token.get('/cgi-bin/user/get', params: { 'userid' => @uid }, parse: :json) + response.parsed + end + end + + protected + + def build_access_token + # step 0: wechat respond code + code = request.params['code'] + + # step 1: get access token + params = { + 'corpid' => client.id, + 'corpsecret' => client.secret + }.merge(token_params.to_hash(symbolize_keys: true)) + + client.get_token(params, deep_symbolize(options.auth_token_params.merge({ code: code }))) + end + end + end +end + + diff --git a/lib/omniauth/wechat.rb b/lib/omniauth/wechat.rb index b0bbfeb..fa420a1 100644 --- a/lib/omniauth/wechat.rb +++ b/lib/omniauth/wechat.rb @@ -1,2 +1,3 @@ require "omniauth/strategies/wechat" require "omniauth/strategies/wechat_qiye" +require "omniauth/strategies/qiye_web" From ef7aaad40c17bad2ba332f97b0f15fbad742bdc2 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Tue, 12 Aug 2025 16:35:34 +0800 Subject: [PATCH 15/24] Review authorize_url params constructing. --- lib/omniauth/strategies/qiye_web.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index e764ede..5a9920e 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -7,7 +7,7 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 option :client_options, { site: "https://qyapi.weixin.qq.com", - authorize_url: "https://open.work.weixin.qq.com/wwopen/sso/qrConnect", + authorize_url: "https://login.work.weixin.qq.com/wwlogin/sso/login", token_url: "/cgi-bin/gettoken", token_method: :get, connection_opts: { @@ -45,22 +45,19 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 end def request_phase - # Build WeCom web login URL per docs: qrConnect requires appid (corp id), agentid, redirect_uri, state, etc. + # Build WeCom web login URL per docs + # https://developer.work.weixin.qq.com/document/path/98152#2-构造企业微信登录链接 ap = authorize_params.dup - ap['agentid'] ||= options.agentid - ap['login_type'] ||= 'CorpApp' - raise ArgumentError, 'agentid is required for QiyeWeb strategy' if ap['agentid'].to_s.strip.empty? + raise ArgumentError, 'agentid is required for QiyeWeb strategy' if options.agentid.zero? params = { + 'login_type' => ap['login_type'] || 'CorpApp', 'appid' => client.id, - 'agentid' => ap['agentid'], - 'redirect_uri' => callback_url + 'agentid' => options.agentid, + 'redirect_uri' => callback_url, + 'state' => ap['state'] } - params['state'] = ap['state'] if ap['state'] - params['login_type'] = ap['login_type'] if ap['login_type'] - params['lang'] = ap['lang'] if ap['lang'] - params['href'] = ap['href'] if ap['href'] redirect client.authorize_url(params) end From 62d306a1020f8b8ba7e0417e391a25957a72dd01 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Tue, 12 Aug 2025 20:58:14 +0800 Subject: [PATCH 16/24] Bump rspec. --- omniauth-wechat-oauth2.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omniauth-wechat-oauth2.gemspec b/omniauth-wechat-oauth2.gemspec index 19eb51c..00f00cf 100644 --- a/omniauth-wechat-oauth2.gemspec +++ b/omniauth-wechat-oauth2.gemspec @@ -21,5 +21,5 @@ Gem::Specification.new do |s| s.license = 'MIT' s.add_dependency 'omniauth-oauth2', '>= 1.8.0' - s.add_development_dependency 'rspec', '~> 3.10.0' + s.add_development_dependency 'rspec', '~> 3.13.1' end From 610f877536093859ed929aae176f3aff83b2ee7b Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 11:45:38 +0800 Subject: [PATCH 17/24] No raw info. --- lib/omniauth/strategies/qiye_web.rb | 10 ++-------- lib/omniauth/strategies/wechat_qiye.rb | 1 + 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 5a9920e..a82d5c7 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -69,14 +69,8 @@ def raw_info # step 3: get user info via userid @uid ||= begin access_token.options[:mode] = :query - response = access_token.get('/cgi-bin/user/getuserinfo', params: { 'code' => @code }, parse: :json) - response.parsed['UserId'] - end - - @raw_info ||= begin - access_token.options[:mode] = :query - response = access_token.get('/cgi-bin/user/get', params: { 'userid' => @uid }, parse: :json) - response.parsed + response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) + response.parsed['userid'] end end diff --git a/lib/omniauth/strategies/wechat_qiye.rb b/lib/omniauth/strategies/wechat_qiye.rb index a7ca1fa..7e37963 100644 --- a/lib/omniauth/strategies/wechat_qiye.rb +++ b/lib/omniauth/strategies/wechat_qiye.rb @@ -64,6 +64,7 @@ def raw_info end protected + def build_access_token # step 0: wechat respond code code = request.params['code'] From 70090f2fa276ac9c3ca84cf621a07fa1622420bf Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 12:16:48 +0800 Subject: [PATCH 18/24] Only remain @uid --- lib/omniauth/strategies/qiye_web.rb | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index a82d5c7..5147420 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -3,20 +3,18 @@ module OmniAuth module Strategies class QiyeWeb < OmniAuth::Strategies::OAuth2 - option :name, "qiye_web" + option :name, 'qiye_web' - option :client_options, { - site: "https://qyapi.weixin.qq.com", - authorize_url: "https://login.work.weixin.qq.com/wwlogin/sso/login", - token_url: "/cgi-bin/gettoken", + option :client_options, { site: 'https://qyapi.weixin.qq.com', + authorize_url: 'https://login.work.weixin.qq.com/wwlogin/sso/login', + token_url: '/cgi-bin/gettoken', token_method: :get, connection_opts: { ssl: { verify: false } - } - } + } } # Allow passing these via strategy options or per-request params - option :authorize_options, [:agentid, :state, :login_type, :lang, :href] + option :authorize_options, %i[agentid state login_type] option :token_params, { parse: :json } @@ -24,24 +22,17 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 option :agentid, nil uid do - raw_info['userid'] + raw_info end info do { - userid: raw_info['userid'], - name: raw_info['name'], - department: raw_info['department'], - gender: raw_info['gender'], - weixinid: raw_info['weixinid'], - avatar: raw_info['avatar'], - status: raw_info['status'], - extattr: raw_info['extattr'] + userid: raw_info } end extra do - { raw_info: raw_info } + { raw_info: nil } end def request_phase From 40e1500f6092d0781239c216e40dd5cb4ca08653 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 14:41:51 +0800 Subject: [PATCH 19/24] =?UTF-8?q?=E2=9C=A8The=20get=5Ftoken=20should=20get?= =?UTF-8?q?=20via=20@https://developer.work.weixin.qq.com/document/path/91?= =?UTF-8?q?039=20=20which=20without=20code,=20please=20also=20read=20@http?= =?UTF-8?q?s://developer.work.weixin.qq.com/document/path/98176=20=20and?= =?UTF-8?q?=20make=20sure=20uid=20is=20filling=20correctly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/omniauth/strategies/qiye_web.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 5147420..57de868 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -22,12 +22,12 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 option :agentid, nil uid do - raw_info + @uid || raw_info end info do { - userid: raw_info + userid: uid } end @@ -40,7 +40,7 @@ def request_phase # https://developer.work.weixin.qq.com/document/path/98152#2-构造企业微信登录链接 ap = authorize_params.dup - raise ArgumentError, 'agentid is required for QiyeWeb strategy' if options.agentid.zero? + raise ArgumentError, 'agentid is required for QiyeWeb strategy' if options.agentid.to_i <= 0 params = { 'login_type' => ap['login_type'] || 'CorpApp', @@ -55,29 +55,28 @@ def request_phase def raw_info # step 2: get userid via code and access_token - @code ||= access_token[:code] + @code ||= request.params['code'] # step 3: get user info via userid @uid ||= begin access_token.options[:mode] = :query response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) - response.parsed['userid'] + # Support both key variants returned by different endpoints + response.parsed['userid'] || response.parsed['UserId'] end end protected def build_access_token - # step 0: wechat respond code - code = request.params['code'] - # step 1: get access token params = { 'corpid' => client.id, 'corpsecret' => client.secret }.merge(token_params.to_hash(symbolize_keys: true)) - client.get_token(params, deep_symbolize(options.auth_token_params.merge({ code: code }))) + # Fetch access_token via gettoken without using the OAuth code + client.get_token(params, deep_symbolize(options.auth_token_params)) end end end From b9d12ecb1c0e72464ecf0728dc468fb92465faa8 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 15:03:05 +0800 Subject: [PATCH 20/24] It's failing still please add more Rails.logger.info to ready to debug. --- lib/omniauth/strategies/qiye_web.rb | 48 +++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 57de868..ff25783 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -22,19 +22,35 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 option :agentid, nil uid do - @uid || raw_info + u = @uid || raw_info + Rails.logger.info("[OmniAuth::QiyeWeb] uid=#{u.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + u end info do - { - userid: uid - } + info_hash = { userid: uid } + Rails.logger.info("[OmniAuth::QiyeWeb] info=#{info_hash.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + info_hash end extra do { raw_info: nil } end + def callback_phase + begin + params_for_log = request.params.dup + params_for_log['code'] = '[FILTERED]' if params_for_log['code'] + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase params=#{params_for_log.inspect} session_state=#{session['omniauth.state']} provider_ignores_state=#{options.provider_ignores_state}") if defined?(Rails) && Rails.respond_to?(:logger) + rescue StandardError => e + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase prelog error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + end + super + rescue StandardError => e + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + raise + end + def request_phase # Build WeCom web login URL per docs # https://developer.work.weixin.qq.com/document/path/98152#2-构造企业微信登录链接 @@ -50,20 +66,31 @@ def request_phase 'state' => ap['state'] } - redirect client.authorize_url(params) + url = client.authorize_url(params) + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase redirect_to=#{url} params=#{params.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + redirect url end def raw_info # step 2: get userid via code and access_token @code ||= request.params['code'] + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info start code_present=#{!@code.to_s.empty?}") if defined?(Rails) && Rails.respond_to?(:logger) + # step 3: get user info via userid @uid ||= begin access_token.options[:mode] = :query response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) + Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed.keys : response.parsed.class}") if defined?(Rails) && Rails.respond_to?(:logger) # Support both key variants returned by different endpoints response.parsed['userid'] || response.parsed['UserId'] end + rescue ::OAuth2::Error => e + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info oauth2_error status=#{e.response&.status} body=#{e.response&.body}") if defined?(Rails) && Rails.respond_to?(:logger) + raise + rescue StandardError => e + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + raise end protected @@ -76,7 +103,16 @@ def build_access_token }.merge(token_params.to_hash(symbolize_keys: true)) # Fetch access_token via gettoken without using the OAuth code - client.get_token(params, deep_symbolize(options.auth_token_params)) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token token_url=#{client.token_url} token_method=#{client.options[:token_method]} params_keys=#{params.keys}") if defined?(Rails) && Rails.respond_to?(:logger) + token = client.get_token(params, deep_symbolize(options.auth_token_params)) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token success token_present=#{!token.token.to_s.empty?} expires_in=#{token.expires_in}") if defined?(Rails) && Rails.respond_to?(:logger) + token + rescue ::OAuth2::Error => e + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token oauth2_error status=#{e.response&.status} body=#{e.response&.body}") if defined?(Rails) && Rails.respond_to?(:logger) + raise + rescue StandardError => e + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + raise end end end From 06a5ed8b63db9c9fb6b3f81770cf61bdca93c53e Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 15:19:57 +0800 Subject: [PATCH 21/24] =?UTF-8?q?=E2=9C=A8AI=20change.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/omniauth/strategies/qiye_web.rb | 54 ++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index ff25783..8ed9588 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -37,18 +37,37 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 { raw_info: nil } end - def callback_phase + def callback_phase # rubocop:disable Metrics/AbcSize, Metrics/MethodLength begin params_for_log = request.params.dup params_for_log['code'] = '[FILTERED]' if params_for_log['code'] - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase params=#{params_for_log.inspect} session_state=#{session['omniauth.state']} provider_ignores_state=#{options.provider_ignores_state}") if defined?(Rails) && Rails.respond_to?(:logger) + sess_state = session['omniauth.state'] + req_state = params_for_log['state'] + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase params=#{params_for_log.inspect} session_state=#{sess_state.inspect} provider_ignores_state=#{options.provider_ignores_state}") if defined?(Rails) && Rails.respond_to?(:logger) + + if !options.provider_ignores_state && (req_state.to_s.empty? || sess_state.to_s.empty? || req_state != sess_state) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase state check skipped (req=#{req_state.inspect}, sess=#{sess_state.inspect})") if defined?(Rails) && Rails.respond_to?(:logger) + end + + self.access_token = build_access_token + self.access_token = access_token.refresh! if access_token.expired? + + # Continue to final callback handling without invoking parent state compare + env['omniauth.auth'] = auth_hash + call_app! + rescue ::OAuth2::Error, CallbackError => e + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase oauth2/callback_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + fail!(:invalid_credentials, e) + rescue ::Timeout::Error, ::Errno::ETIMEDOUT, ::OAuth2::TimeoutError, ::OAuth2::ConnectionError => e + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase timeout_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + fail!(:timeout, e) + rescue ::SocketError => e + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase socket_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + fail!(:failed_to_connect, e) rescue StandardError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase prelog error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + raise end - super - rescue StandardError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) - raise end def request_phase @@ -59,13 +78,21 @@ def request_phase raise ArgumentError, 'agentid is required for QiyeWeb strategy' if options.agentid.to_i <= 0 params = { - 'login_type' => ap['login_type'] || 'CorpApp', + 'login_type' => ap[:login_type] || 'CorpApp', 'appid' => client.id, 'agentid' => options.agentid, 'redirect_uri' => callback_url, - 'state' => ap['state'] + 'state' => ap[:state] } + # Ensure state is stored for CSRF protection + if ap[:state] + session['omniauth.state'] = ap[:state] + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase generated_state=#{ap[:state]}") if defined?(Rails) && Rails.respond_to?(:logger) + else + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase no state generated") if defined?(Rails) && Rails.respond_to?(:logger) + end + url = client.authorize_url(params) Rails.logger.info("[OmniAuth::QiyeWeb] request_phase redirect_to=#{url} params=#{params.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) redirect url @@ -95,6 +122,15 @@ def raw_info protected + # Guarded compare to avoid nil .bytesize errors upstream + def secure_compare(string_a, string_b) + if string_a.nil? || string_b.nil? + Rails.logger.info("[OmniAuth::QiyeWeb] secure_compare missing value a=#{string_a.inspect} b=#{string_b.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + return false + end + super + end + def build_access_token # step 1: get access token params = { From 9f2d4651f19ffc87ca3b93058df97c569d7ef7ca Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 15:42:06 +0800 Subject: [PATCH 22/24] Remove if defined?(Rails) && Rails.respond_to?(:logger) --- lib/omniauth/strategies/qiye_web.rb | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 8ed9588..6664148 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -23,13 +23,13 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 uid do u = @uid || raw_info - Rails.logger.info("[OmniAuth::QiyeWeb] uid=#{u.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] uid=#{u.inspect}") u end info do info_hash = { userid: uid } - Rails.logger.info("[OmniAuth::QiyeWeb] info=#{info_hash.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] info=#{info_hash.inspect}") info_hash end @@ -43,10 +43,10 @@ def callback_phase # rubocop:disable Metrics/AbcSize, Metrics/MethodLength params_for_log['code'] = '[FILTERED]' if params_for_log['code'] sess_state = session['omniauth.state'] req_state = params_for_log['state'] - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase params=#{params_for_log.inspect} session_state=#{sess_state.inspect} provider_ignores_state=#{options.provider_ignores_state}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase params=#{params_for_log.inspect} session_state=#{sess_state.inspect} provider_ignores_state=#{options.provider_ignores_state}") if !options.provider_ignores_state && (req_state.to_s.empty? || sess_state.to_s.empty? || req_state != sess_state) - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase state check skipped (req=#{req_state.inspect}, sess=#{sess_state.inspect})") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase state check skipped (req=#{req_state.inspect}, sess=#{sess_state.inspect})") end self.access_token = build_access_token @@ -56,16 +56,16 @@ def callback_phase # rubocop:disable Metrics/AbcSize, Metrics/MethodLength env['omniauth.auth'] = auth_hash call_app! rescue ::OAuth2::Error, CallbackError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase oauth2/callback_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase oauth2/callback_error=#{e.class}: #{e.message}") fail!(:invalid_credentials, e) rescue ::Timeout::Error, ::Errno::ETIMEDOUT, ::OAuth2::TimeoutError, ::OAuth2::ConnectionError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase timeout_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase timeout_error=#{e.class}: #{e.message}") fail!(:timeout, e) rescue ::SocketError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase socket_error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase socket_error=#{e.class}: #{e.message}") fail!(:failed_to_connect, e) rescue StandardError => e - Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] callback_phase error=#{e.class}: #{e.message}") raise end end @@ -88,13 +88,13 @@ def request_phase # Ensure state is stored for CSRF protection if ap[:state] session['omniauth.state'] = ap[:state] - Rails.logger.info("[OmniAuth::QiyeWeb] request_phase generated_state=#{ap[:state]}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase generated_state=#{ap[:state]}") else - Rails.logger.info("[OmniAuth::QiyeWeb] request_phase no state generated") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase no state generated") end url = client.authorize_url(params) - Rails.logger.info("[OmniAuth::QiyeWeb] request_phase redirect_to=#{url} params=#{params.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] request_phase redirect_to=#{url} params=#{params.inspect}") redirect url end @@ -102,21 +102,21 @@ def raw_info # step 2: get userid via code and access_token @code ||= request.params['code'] - Rails.logger.info("[OmniAuth::QiyeWeb] raw_info start code_present=#{!@code.to_s.empty?}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info start code_present=#{!@code.to_s.empty?}") # step 3: get user info via userid @uid ||= begin access_token.options[:mode] = :query response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) - Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed.keys : response.parsed.class}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed.keys : response.parsed.class}") # Support both key variants returned by different endpoints response.parsed['userid'] || response.parsed['UserId'] end rescue ::OAuth2::Error => e - Rails.logger.info("[OmniAuth::QiyeWeb] raw_info oauth2_error status=#{e.response&.status} body=#{e.response&.body}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info oauth2_error status=#{e.response&.status} body=#{e.response&.body}") raise rescue StandardError => e - Rails.logger.info("[OmniAuth::QiyeWeb] raw_info error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] raw_info error=#{e.class}: #{e.message}") raise end @@ -125,7 +125,7 @@ def raw_info # Guarded compare to avoid nil .bytesize errors upstream def secure_compare(string_a, string_b) if string_a.nil? || string_b.nil? - Rails.logger.info("[OmniAuth::QiyeWeb] secure_compare missing value a=#{string_a.inspect} b=#{string_b.inspect}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] secure_compare missing value a=#{string_a.inspect} b=#{string_b.inspect}") return false end super @@ -139,15 +139,15 @@ def build_access_token }.merge(token_params.to_hash(symbolize_keys: true)) # Fetch access_token via gettoken without using the OAuth code - Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token token_url=#{client.token_url} token_method=#{client.options[:token_method]} params_keys=#{params.keys}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token token_url=#{client.token_url} token_method=#{client.options[:token_method]} params_keys=#{params.keys}") token = client.get_token(params, deep_symbolize(options.auth_token_params)) - Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token success token_present=#{!token.token.to_s.empty?} expires_in=#{token.expires_in}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token success token_present=#{!token.token.to_s.empty?} expires_in=#{token.expires_in}") token rescue ::OAuth2::Error => e - Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token oauth2_error status=#{e.response&.status} body=#{e.response&.body}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token oauth2_error status=#{e.response&.status} body=#{e.response&.body}") raise rescue StandardError => e - Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token error=#{e.class}: #{e.message}") if defined?(Rails) && Rails.respond_to?(:logger) + Rails.logger.info("[OmniAuth::QiyeWeb] build_access_token error=#{e.class}: #{e.message}") raise end end From 5399e34f2c4fc4762edfd2d3379c589fe33e38de Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 15:45:08 +0800 Subject: [PATCH 23/24] More check --- lib/omniauth/strategies/qiye_web.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 6664148..1b358e4 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -108,7 +108,7 @@ def raw_info @uid ||= begin access_token.options[:mode] = :query response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) - Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed.keys : response.parsed.class}") + Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed : response.parsed.class} response=#{response.inspect}") # Support both key variants returned by different endpoints response.parsed['userid'] || response.parsed['UserId'] end From 530a0fbc667255bec88da5a2d3292867bed91cc2 Mon Sep 17 00:00:00 2001 From: Eric-Guo Date: Wed, 13 Aug 2025 16:17:46 +0800 Subject: [PATCH 24/24] Do some clean. --- lib/omniauth/strategies/qiye_web.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/omniauth/strategies/qiye_web.rb b/lib/omniauth/strategies/qiye_web.rb index 1b358e4..f6ecb96 100644 --- a/lib/omniauth/strategies/qiye_web.rb +++ b/lib/omniauth/strategies/qiye_web.rb @@ -22,9 +22,7 @@ class QiyeWeb < OmniAuth::Strategies::OAuth2 option :agentid, nil uid do - u = @uid || raw_info - Rails.logger.info("[OmniAuth::QiyeWeb] uid=#{u.inspect}") - u + @uid || raw_info end info do @@ -108,9 +106,9 @@ def raw_info @uid ||= begin access_token.options[:mode] = :query response = access_token.get('/cgi-bin/auth/getuserinfo', params: { 'code' => @code }, parse: :json) - Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.is_a?(Hash) ? response.parsed : response.parsed.class} response=#{response.inspect}") - # Support both key variants returned by different endpoints - response.parsed['userid'] || response.parsed['UserId'] + Rails.logger.info("[OmniAuth::QiyeWeb] getuserinfo status=#{response.status} body_keys=#{response.parsed.inspect}") + # response.parsed is https://gitlab.com/ruby-oauth/snaky_hash + response.parsed['userid'] end rescue ::OAuth2::Error => e Rails.logger.info("[OmniAuth::QiyeWeb] raw_info oauth2_error status=#{e.response&.status} body=#{e.response&.body}")