omniauth-myheritage 1.0.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.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'jruby-openssl', :platform => :jruby
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # OmniAuth MyHeritage
2
+
3
+ MyHeritage OAuth2 Strategy for OmniAuth 1.0.
4
+
5
+ Supports the OAuth 2.0 server-side. Read the MyHeritage docs for more details: http://www.familygraph.com/documentation/authentication
6
+
7
+ ## Installing
8
+
9
+ Add to your `Gemfile`:
10
+
11
+ ```ruby
12
+ gem 'omniauth-myheritage'
13
+ ```
14
+
15
+ Then `bundle install`.
16
+
17
+ ## Usage
18
+
19
+ `OmniAuth::Strategies::MyHeritage` is simply a Rack middleware. Read the OmniAuth 1.0 docs for detailed instructions: https://github.com/intridea/omniauth.
20
+
21
+ Here's a quick example, adding the middleware to a Rails app in `config/initializers/omniauth.rb`:
22
+
23
+ ```ruby
24
+ Rails.application.config.middleware.use OmniAuth::Builder do
25
+ provider :myheritage, ENV['MY_HERITAGE_KEY'], ENV['MY_HERITAGE_SECRET']
26
+ end
27
+ ```
28
+
29
+ ## Configuring
30
+
31
+ You can configure several options, which you pass in to the `provider` method via a `Hash`:
32
+
33
+ * `scope`: A comma-separated list of permissions you want to request from the user. See the MyHeritage docs for a full list of available permissions. Default: `email`.
34
+
35
+ For example, to request `email` permission:
36
+
37
+ ```ruby
38
+ Rails.application.config.middleware.use OmniAuth::Builder do
39
+ provider :myheritage, ENV['MY_HERITAGE_KEY'], ENV['MY_HERITAGE_SECRET'], :scope => 'email'
40
+ end
41
+ ```
42
+
43
+ ## Authentication Hash
44
+
45
+ Here's an example *Authentication Hash* available in `request.env['omniauth.auth']`:
46
+
47
+ ```ruby
48
+ {
49
+ :provider => 'myheritage',
50
+ :uid => '123',
51
+ :info => {
52
+ :first_name => 'Alex',
53
+ :last_name => 'Thompson',
54
+ :email => 'alex@sample.com',
55
+ :name => 'Alex Thompson'
56
+ },
57
+ :credentials => {
58
+ :token => 'ABCDEF...', # OAuth 2.0 access_token
59
+ :expires_at => 1321747205 # when the access token expires
60
+ },
61
+ :extra => {
62
+ :profile => {
63
+ :id => '1234567',
64
+ :name => 'Alex Thompson',
65
+ :first_name => 'Alex',
66
+ :last_name => 'Thompson'
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ The precise information available may depend on the permissions which you request.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/example/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gem 'rack', '~> 1.3.6'
4
+
5
+ gem 'sinatra'
6
+ gem 'omniauth-myheritage', :path => '../'
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ omniauth-myheritage (1.0.0)
5
+ omniauth-oauth2 (~> 1.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ faraday (0.8.7)
11
+ multipart-post (~> 1.1)
12
+ hashie (2.0.5)
13
+ httpauth (0.2.0)
14
+ jwt (0.1.8)
15
+ multi_json (>= 1.5)
16
+ multi_json (1.7.3)
17
+ multipart-post (1.2.0)
18
+ oauth2 (0.8.1)
19
+ faraday (~> 0.8)
20
+ httpauth (~> 0.1)
21
+ jwt (~> 0.1.4)
22
+ multi_json (~> 1.0)
23
+ rack (~> 1.2)
24
+ omniauth (1.1.4)
25
+ hashie (>= 1.2, < 3)
26
+ rack
27
+ omniauth-oauth2 (1.0.3)
28
+ oauth2 (~> 0.8.0)
29
+ omniauth (~> 1.0)
30
+ rack (1.3.6)
31
+ rack-protection (1.2.0)
32
+ rack
33
+ sinatra (1.3.2)
34
+ rack (~> 1.3, >= 1.3.6)
35
+ rack-protection (~> 1.2)
36
+ tilt (~> 1.3, >= 1.3.3)
37
+ tilt (1.3.3)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ omniauth-myheritage!
44
+ rack (~> 1.3.6)
45
+ sinatra
data/example/config.ru ADDED
@@ -0,0 +1,31 @@
1
+ require 'bundler/setup'
2
+ require 'sinatra/base'
3
+ require 'omniauth-myheritage'
4
+
5
+ SCOPE = 'email'
6
+
7
+ class App < Sinatra::Base
8
+
9
+ get '/' do
10
+ redirect '/auth/myheritage'
11
+ end
12
+
13
+ get '/auth/:provider/callback' do
14
+ content_type 'application/json'
15
+ MultiJson.encode(request.env)
16
+ end
17
+
18
+ get '/auth/failure' do
19
+ content_type 'application/json'
20
+ MultiJson.encode(request.env)
21
+ end
22
+
23
+ end
24
+
25
+ use Rack::Session::Cookie
26
+
27
+ use OmniAuth::Builder do
28
+ provider :myheritage, ENV['APP_ID'], ENV['APP_SECRET'], :scope => SCOPE
29
+ end
30
+
31
+ run App.new
@@ -0,0 +1 @@
1
+ require 'omniauth/my_heritage'
@@ -0,0 +1,2 @@
1
+ require 'omniauth/my_heritage/version'
2
+ require 'omniauth/strategies/my_heritage'
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module MyHeritage
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,85 @@
1
+ require 'omniauth-oauth2'
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ class MyHeritage < OmniAuth::Strategies::OAuth2
6
+
7
+ option :client_options, {
8
+ :site => 'https://accounts.myheritage.com',
9
+ :authorize_url => '/oauth2/authorize',
10
+ :token_url => '/oauth2/token'
11
+ }
12
+
13
+ option :authorize_params, {
14
+
15
+ }
16
+
17
+ option :name, 'myheritage'
18
+
19
+ option :access_token_options, {
20
+ :header_format => 'Bearer %s',
21
+ :param_name => 'bearer_token'
22
+ }
23
+
24
+ option :authorize_options, [:scope]
25
+
26
+ def request_phase
27
+ super
28
+ end
29
+
30
+ def build_access_token
31
+ token_params = {
32
+ :code => request.params['code'],
33
+ :redirect_uri => callback_url,
34
+ :client_id => client.id,
35
+ :client_secret => client.secret,
36
+ :grant_type => 'authorization_code'
37
+ }
38
+ client.get_token(token_params)
39
+ end
40
+
41
+ uid { raw_info['id'] }
42
+
43
+ info do
44
+ prune!({
45
+ 'id' => raw_info['id'],
46
+ 'email' => raw_info['email'],
47
+ 'name' => raw_info['name'],
48
+ 'first_name' => raw_info['first_name'],
49
+ 'last_name' => raw_info['last_name'],
50
+ 'gender' => raw_info['gender'],
51
+ 'birthday' => raw_info['birth_date'],
52
+ 'link' => raw_info['link'],
53
+ 'locale' => raw_info['preferred_display_language']
54
+ })
55
+ end
56
+
57
+ extra do
58
+ { 'profile' => prune!(raw_info) }
59
+ end
60
+
61
+ def raw_info
62
+ @raw_info ||= access_token.get('https://familygraph.myheritage.com/me').parsed
63
+ end
64
+
65
+ def authorize_params
66
+ super.tap do |params|
67
+ params.merge!(:state => request.params['state']) if request.params['state']
68
+ params[:scope] ||= 'email'
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def prune!(hash)
75
+ hash.delete_if do |_, value|
76
+ prune!(value) if value.is_a?(Hash)
77
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+
85
+ OmniAuth.config.add_camelization 'myheritage', 'MyHeritage'
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'omniauth/my_heritage/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'omniauth-myheritage'
7
+ s.version = OmniAuth::MyHeritage::VERSION
8
+ s.authors = ['Michael Berkovich']
9
+ s.email = ['theiceberk@gmail.com']
10
+ s.summary = 'MyHeritage strategy for OmniAuth'
11
+ s.homepage = 'https://github.com/geni/omniauth-myheritage'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
16
+ s.require_paths = ['lib']
17
+
18
+ s.add_runtime_dependency 'omniauth-oauth2', '~> 1.0.0'
19
+
20
+ s.add_development_dependency 'rspec', '~> 2.7.0'
21
+ s.add_development_dependency 'rake'
22
+ end
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+ require 'omniauth-myheritage'
3
+
4
+ describe OmniAuth::Strategies::MyHeritage do
5
+ before :each do
6
+ @request = double('Request')
7
+ @request.stub(:params) { {} }
8
+ @request.stub(:cookies) { {} }
9
+
10
+ @client_id = 'abc'
11
+ @client_secret = 'def'
12
+ end
13
+
14
+ subject do
15
+ args = [@client_id, @client_secret, @options].compact
16
+ OmniAuth::Strategies::MyHeritage.new(nil, *args).tap do |strategy|
17
+ strategy.stub(:request) { @request }
18
+ end
19
+ end
20
+
21
+ it_should_behave_like 'an oauth2 strategy'
22
+
23
+ describe '#client' do
24
+ it 'has correct site' do
25
+ subject.client.site.should eq('https://accounts.myheritage.com')
26
+ end
27
+
28
+ it 'has correct authorize url' do
29
+ subject.client.options[:authorize_url].should eq('/oauth/authorize')
30
+ end
31
+
32
+ it 'has correct token url' do
33
+ subject.client.options[:token_url].should eq('/oauth/token')
34
+ end
35
+ end
36
+
37
+ describe '#authorize_params' do
38
+ it 'includes state parameter from request when present' do
39
+ @request.stub(:params) { { 'state' => 'some_state' } }
40
+ subject.authorize_params.should be_a(Hash)
41
+ subject.authorize_params[:state].should eq('some_state')
42
+ end
43
+ end
44
+
45
+ describe '#uid' do
46
+ before :each do
47
+ subject.stub(:raw_info) { { 'id' => '123' } }
48
+ end
49
+
50
+ it 'returns the id from raw_info' do
51
+ subject.uid.should eq('123')
52
+ end
53
+ end
54
+
55
+ describe '#info' do
56
+ before :each do
57
+ @raw_info ||= { 'first_name' => 'Alex' }
58
+ subject.stub(:raw_info) { @raw_info }
59
+ end
60
+
61
+ context 'when optional data is not present in raw info' do
62
+ it 'has no email key' do
63
+ subject.info.should_not have_key('email')
64
+ end
65
+
66
+ it 'has no last name key' do
67
+ subject.info.should_not have_key('last_name')
68
+ end
69
+ end
70
+
71
+ context 'when data is present in raw info' do
72
+ it 'returns first name' do
73
+ subject.info['first_name'].should eq('Alex')
74
+ end
75
+
76
+ it 'returns the email' do
77
+ @raw_info['email'] = 'fred@smith.com'
78
+ subject.info['email'].should eq('fred@smith.com')
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#raw_info' do
84
+ before :each do
85
+ @access_token = double('OAuth2::AccessToken')
86
+ subject.stub(:access_token) { @access_token }
87
+ end
88
+
89
+ it 'performs a GET to https://familygraph.myheritage.com/me' do
90
+ @access_token.stub(:get) { double('OAuth2::Response').as_null_object }
91
+ @access_token.should_receive(:get).with('/api/profile')
92
+ subject.raw_info
93
+ end
94
+
95
+ it 'returns a Hash' do
96
+ @access_token.stub(:get).with('/api/profile') do
97
+ raw_response = double('Faraday::Response')
98
+ raw_response.stub(:body) { '{ "ohai": "thar" }' }
99
+ raw_response.stub(:status) { 200 }
100
+ raw_response.stub(:headers) { { 'Content-Type' => 'application/json' } }
101
+ OAuth2::Response.new(raw_response)
102
+ end
103
+ subject.raw_info.should be_a(Hash)
104
+ subject.raw_info['ohai'].should eq('thar')
105
+ end
106
+ end
107
+
108
+ describe '#credentials' do
109
+ before :each do
110
+ @access_token = double('OAuth2::AccessToken')
111
+ @access_token.stub(:token)
112
+ @access_token.stub(:expires?)
113
+ @access_token.stub(:expires_at)
114
+ @access_token.stub(:refresh_token)
115
+ subject.stub(:access_token) { @access_token }
116
+ end
117
+
118
+ it 'returns a Hash' do
119
+ subject.credentials.should be_a(Hash)
120
+ end
121
+
122
+ it 'returns the token' do
123
+ @access_token.stub(:token) { '123' }
124
+ subject.credentials['token'].should eq('123')
125
+ end
126
+
127
+ it 'returns the expiry status' do
128
+ @access_token.stub(:expires?) { true }
129
+ subject.credentials['expires'].should eq(true)
130
+
131
+ @access_token.stub(:expires?) { false }
132
+ subject.credentials['expires'].should eq(false)
133
+ end
134
+
135
+ it 'returns the refresh token and expiry time when expiring' do
136
+ ten_mins_from_now = (Time.now + 600).to_i
137
+ @access_token.stub(:expires?) { true }
138
+ @access_token.stub(:refresh_token) { '321' }
139
+ @access_token.stub(:expires_at) { ten_mins_from_now }
140
+ subject.credentials['refresh_token'].should eq('321')
141
+ subject.credentials['expires_at'].should eq(ten_mins_from_now)
142
+ end
143
+
144
+ it 'does not return the refresh token when it is nil and expiring' do
145
+ @access_token.stub(:expires?) { true }
146
+ @access_token.stub(:refresh_token) { nil }
147
+ subject.credentials['refresh_token'].should be_nil
148
+ subject.credentials.should_not have_key('refresh_token')
149
+ end
150
+
151
+ it 'does not return the refresh token when not expiring' do
152
+ @access_token.stub(:expires?) { false }
153
+ @access_token.stub(:refresh_token) { 'XXX' }
154
+ subject.credentials['refresh_token'].should be_nil
155
+ subject.credentials.should_not have_key('refresh_token')
156
+ end
157
+ end
158
+
159
+ describe '#extra' do
160
+ before :each do
161
+ @raw_info = { 'name' => 'Fred Smith' }
162
+ subject.stub(:raw_info) { @raw_info }
163
+ end
164
+
165
+ it 'returns a Hash' do
166
+ subject.extra.should be_a(Hash)
167
+ end
168
+
169
+ it 'contains raw info' do
170
+ subject.extra.should eq({ 'profile' => @raw_info })
171
+ end
172
+ end
173
+
174
+ end
@@ -0,0 +1,6 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ Dir[File.expand_path('../support/**/*', __FILE__)].each { |f| require f }
4
+
5
+ RSpec.configure do |config|
6
+ end
@@ -0,0 +1,37 @@
1
+ # NOTE it would be useful if this lived in omniauth-oauth2 eventually
2
+ shared_examples 'an oauth2 strategy' do
3
+ describe '#client' do
4
+ it 'should be initialized with symbolized client_options' do
5
+ @options = { :client_options => { 'authorize_url' => 'https://example.com' } }
6
+ subject.client.options[:authorize_url].should == 'https://example.com'
7
+ end
8
+ end
9
+
10
+ describe '#authorize_params' do
11
+ it 'should include any authorize params passed in the :authorize_params option' do
12
+ @options = { :authorize_params => { :foo => 'bar', :baz => 'zip' } }
13
+ subject.authorize_params['foo'].should eq('bar')
14
+ subject.authorize_params['baz'].should eq('zip')
15
+ end
16
+
17
+ it 'should include top-level options that are marked as :authorize_options' do
18
+ @options = { :authorize_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' }
19
+ subject.authorize_params['scope'].should eq('bar')
20
+ subject.authorize_params['foo'].should eq('baz')
21
+ end
22
+ end
23
+
24
+ describe '#token_params' do
25
+ it 'should include any authorize params passed in the :authorize_params option' do
26
+ @options = { :token_params => { :foo => 'bar', :baz => 'zip' } }
27
+ subject.token_params['foo'].should eq('bar')
28
+ subject.token_params['baz'].should eq('zip')
29
+ end
30
+
31
+ it 'should include top-level options that are marked as :authorize_options' do
32
+ @options = { :token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' }
33
+ subject.token_params['scope'].should eq('bar')
34
+ subject.token_params['foo'].should eq('baz')
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-myheritage
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Berkovich
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omniauth-oauth2
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.7.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.7.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description:
63
+ email:
64
+ - theiceberk@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - Gemfile
70
+ - README.md
71
+ - Rakefile
72
+ - example/Gemfile
73
+ - example/Gemfile.lock
74
+ - example/config.ru
75
+ - lib/omniauth-myheritage.rb
76
+ - lib/omniauth/my_heritage.rb
77
+ - lib/omniauth/my_heritage/version.rb
78
+ - lib/omniauth/strategies/my_heritage.rb
79
+ - omniauth-myheritage.gemspec
80
+ - spec/omniauth/strategies/myheritage_spec.rb
81
+ - spec/spec_helper.rb
82
+ - spec/support/shared_examples.rb
83
+ homepage: https://github.com/geni/omniauth-myheritage
84
+ licenses: []
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 1.8.23
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: MyHeritage strategy for OmniAuth
107
+ test_files:
108
+ - spec/omniauth/strategies/myheritage_spec.rb
109
+ - spec/spec_helper.rb
110
+ - spec/support/shared_examples.rb