├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── VERSION ├── lib ├── omniauth-wechat-oauth2.rb └── omniauth │ └── strategies │ └── wechat.rb └── omniauth-wechat-oauth2.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - gem update --system 2.1.11 3 | language: ruby 4 | rvm: 5 | - "1.9.3" 6 | - "2.0.0" 7 | - "2.1.0" -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rake", "~> 0.9.6" 4 | 5 | gemspec 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 YangShurui 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omniauth::Openweixin::Oauth2 2 | 3 | Omniauth Strategy for https://open.weixin.qq.com/ 4 | 5 | 微信开放平台的Omniauth Strategy 6 | 7 | ## Installation 8 | 9 | ```ruby 10 | gem "omniauth-wechat-oauth2", git: 'git@github.com:yangsr/omniauth-wechat-oauth2.git' 11 | ``` 12 | 13 | ## Usage 14 | 15 | Here's an example for adding the middleware to a Rails app in `config/initializers/omniauth.rb`: 16 | ```ruby 17 | Rails.application.config.middleware.use OmniAuth::Builder do 18 | provider :wechat, ENV["WECHAT_APP_ID"], ENV["WECHAT_APP_SECRET"] 19 | end 20 | ``` 21 | 22 | If you want to specify the callback url: 23 | ```ruby 24 | Rails.application.config.middleware.use OmniAuth::Builder do 25 | provider :wechat, ENV["WECHAT_APP_ID"], ENV["WECHAT_APP_SECRET"], 26 | :authorize_params => {:redirect_uri => "http://www.example.com/auth/wechat/callback"} 27 | end 28 | ``` 29 | You can now access the OmniAuth Wechat OAuth2 URL: `/auth/wechat` 30 | 31 | ## Credits 32 | 33 | Skinnyworm, If you want the Omniauth Strategy for http://mp.weixin.qq.com, Click [here](https://github.com/skinnyworm/omniauth-wechat-oauth2) 34 | 35 | ## Notice 36 | There is some difference between https://open.weixin.qq.com/ and http://mp.weixin.qq.com, plz choose the appropriate gem to use. 37 | 38 | 微信公众平台和微信开放平台的OAuth流程略有不同,请选择合适的gem使用。 39 | 40 | ## About Unionid 41 | 42 | UnionID机制,官方的解释是: 43 | 44 | > 通过获取用户基本信息接口,开发者可通过OpenID来获取用户基本信息,而如果开发者拥有多个公众号,可使用以下办法通过UnionID机制来在多公众号之间进行用户帐号互通。只要是同一个微信开放平台帐号下的公众号,用户的UnionID是唯一的。换句话说,同一用户,对同一个微信开放平台帐号下的不同应用,UnionID是相同的。 45 | 46 | 此前的OpenID机制,每个微信号对应每个公众号只有唯一的OpenID,所以不同微信公众号之间是不能共享用户的,现在有了UnionID就可以了。 47 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require File.join('bundler', 'gem_tasks') 3 | require File.join('rspec', 'core', 'rake_task') 4 | 5 | RSpec::Core::RakeTask.new(:spec) 6 | 7 | task :default => :spec -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.0 -------------------------------------------------------------------------------- /lib/omniauth-wechat-oauth2.rb: -------------------------------------------------------------------------------- 1 | require "omniauth/strategies/wechat" 2 | -------------------------------------------------------------------------------- /lib/omniauth/strategies/wechat.rb: -------------------------------------------------------------------------------- 1 | require "omniauth-oauth2" 2 | 3 | module OmniAuth 4 | module Strategies 5 | class Wechat < OmniAuth::Strategies::OAuth2 6 | # Give your strategy a name. 7 | option :name, "wechat" 8 | 9 | # This is where you pass the options you would pass when 10 | # initializing your consumer from the OAuth gem. 11 | option :client_options, { 12 | site: "https://api.weixin.qq.com", 13 | authorize_url: "https://open.weixin.qq.com/connect/qrconnect#wechat_redirect", 14 | token_url: "/sns/oauth2/access_token", 15 | token_method: :get 16 | } 17 | 18 | option :authorize_params, {scope: "snsapi_login"} 19 | 20 | option :token_params, {parse: :json} 21 | 22 | # These are called after authentication has succeeded. If 23 | # possible, you should try to set the UID without making 24 | # additional calls (if the user id is returned with the token 25 | # or as a URI parameter). This may not be possible with all 26 | # providers. 27 | uid { raw_info['openid'] } 28 | 29 | info do 30 | { 31 | nickname: raw_info['nickname'], 32 | sex: raw_info['sex'], 33 | province: raw_info['province'], 34 | city: raw_info['city'], 35 | country: raw_info['country'], 36 | headimgurl: raw_info['headimgurl'], 37 | unionid: raw_info['unionid'], 38 | } 39 | end 40 | 41 | extra do 42 | {raw_info: raw_info} 43 | end 44 | 45 | def request_phase 46 | params = client.auth_code.authorize_params.merge(redirect_uri: callback_url).merge(authorize_params) 47 | params["appid"] = params.delete("client_id") 48 | redirect client.authorize_url(params) 49 | end 50 | 51 | def raw_info 52 | @uid ||= access_token["openid"] 53 | @raw_info ||= begin 54 | access_token.options[:mode] = :query 55 | response = access_token.get("/sns/userinfo", :params => {"openid" => @uid}, parse: :text) 56 | @raw_info = JSON.parse(response.body.gsub(/[\u0000-\u001f]+/, '')) 57 | end 58 | end 59 | 60 | protected 61 | def build_access_token 62 | params = { 63 | 'appid' => client.id, 64 | 'secret' => client.secret, 65 | 'code' => request.params['code'], 66 | 'grant_type' => 'authorization_code' 67 | }.merge(token_params.to_hash(symbolize_keys: true)) 68 | client.get_token(params, deep_symbolize(options.auth_token_params)) 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /omniauth-wechat-oauth2.gemspec: -------------------------------------------------------------------------------- 1 | version = File.read(File.expand_path('../VERSION', __FILE__)).strip 2 | 3 | Gem::Specification.new do |s| 4 | s.platform = Gem::Platform::RUBY 5 | s.name = 'omniauth-wechat-oauth2' 6 | s.version = version 7 | s.summary = 'Omniauth strategy for open.weixin.qq.com' 8 | s.description = 'Using OAuth2 to authenticate wechat user when web resources being viewed within wechat(weixin) client.' 9 | 10 | s.files = Dir['README.md', 'lib/**/*'] 11 | s.require_path = 'lib' 12 | s.requirements << 'none' 13 | s.required_ruby_version = '>= 1.9.3' 14 | s.required_rubygems_version = '>= 1.8.23' 15 | 16 | s.author = 'Skinnyworm, yangsr' 17 | s.email = 'askinnyworm@gmail.com, ysr1023@foxmail.com' 18 | 19 | s.add_dependency 'omniauth', '~> 1.0' 20 | s.add_dependency 'omniauth-oauth2', '~> 1.0' 21 | s.add_development_dependency 'rspec', '~> 2.7' 22 | end 23 | --------------------------------------------------------------------------------