omniauth-multiprovider 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f91a138b2a60e02e2c38acc950045cae88281922
4
+ data.tar.gz: b4743f78480676b0de284cd11e212009ead3258e
5
+ SHA512:
6
+ metadata.gz: 3035045753961d2bb672c5ab90b0593a1845ea92f4572b610df5b4858fde5bb5825ae644ea083b2a2737b12999a2e3a7442275c21a5db5fe104a0895c08fece3
7
+ data.tar.gz: f752d7732163ab562d2020120c2c190dfb7cdfb2f6b77361b85537431fbc6924ef2a7256254c99b75586322c2a583d3a0de82f3649ee4e76e711428c8e209137
@@ -0,0 +1,19 @@
1
+ *.rbc
2
+ *.sassc
3
+ .sass-cache
4
+ capybara-*.html
5
+ .rspec
6
+ .rvmrc
7
+ /.bundle
8
+ /vendor/bundle
9
+ /log/*
10
+ /tmp/*
11
+ /db/*.sqlite3
12
+ /public/system/*
13
+ /coverage/
14
+ /spec/tmp/*
15
+ **.orig
16
+ rerun.txt
17
+ pickle-email-*.html
18
+ .project
19
+ config/initializers/secret_token.rb
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 1uptalent
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,57 @@
1
+ omniauth-multiprovider
2
+ ======================
3
+
4
+ An easy way to authenticate users through many oauth providers (i.e. facebook, twitter, github and custom providers)
5
+
6
+ No more OmniauthCallbacksController, no more complex method to relate users with tokens
7
+
8
+ ## Disclaimer
9
+
10
+ This is a work in progress. Expect serious refactors, breaking changes.
11
+
12
+ I am almose sure that this gem will not work outside an Rails project. Sorry Sinatra lovers... I will try to remove any DHH opinion ;)
13
+
14
+ ## How to use
15
+
16
+ In your devise resource model (aka mapping), usually `User` add:
17
+
18
+ include OmniAuth::MultiProvider::OmniAuthenticable
19
+
20
+ Don't forget to configure devise to use Facebook (or any other provider):
21
+
22
+ devise :omniauthable, omniauth_providers: [:facebook]
23
+
24
+ In your `routes.rb`
25
+
26
+ devise_for :users, controllers: { omniauth_callbacks: 'omni_auth/multi_provider/callbacks' }
27
+
28
+ Create a migration to add the `Authentication` model with:
29
+
30
+ rails g migration create_authentications
31
+
32
+ The change method should contain something like:
33
+
34
+ create_table :authentications do |t|
35
+ t.references :{devise_mapping_name}
36
+ t.string :uid, null: false
37
+ t.string :provider, null: false
38
+ t.string :access_token
39
+ t.string :permissions
40
+ t.timestamps
41
+ end
42
+
43
+ add_index :authentications, [:provider, :uid], unique: true
44
+
45
+ **devise_mapping_name** is probably `user`
46
+
47
+ ## Testing
48
+
49
+ I am porting this gem from an existing project, the testing is currently embebed in the project. I will extract those test and cover this project.
50
+
51
+ ##Contributors
52
+
53
+ [German DZ](https://twitter.com/GermanDZ)
54
+
55
+ ## License
56
+
57
+ MIT License.
@@ -0,0 +1,18 @@
1
+ require 'omniauth/multiprovider'
2
+
3
+ autoload :Authentication, 'omniauth/multiprovider/models/authentication'
4
+ module OmniAuth
5
+ module MultiProvider
6
+ autoload :CallbacksController, 'omniauth/multiprovider/controllers/callbacks_controller'
7
+ autoload :OmniAuthenticable, 'omniauth/multiprovider/models/concerns/omni_authenticable'
8
+ autoload :EmailMockups, 'omniauth/multiprovider/models/email_mockups'
9
+ autoload :Error, 'omniauth/multiprovider/error'
10
+ end
11
+ module Provider
12
+ autoload :Abstract, 'omniauth/provider/abstract'
13
+ autoload :Generic, 'omniauth/provider/generic'
14
+ autoload :Facebook, 'omniauth/provider/facebook'
15
+ autoload :Guests, 'omniauth/provider/guests'
16
+ end
17
+ end
18
+
@@ -0,0 +1,2 @@
1
+ require 'omniauth/multiprovider/helpers'
2
+ require 'omniauth/multiprovider/version'
@@ -0,0 +1,9 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+ class CallbacksController < Devise::OmniauthCallbacksController
4
+ def self.add_callback(provider, &block)
5
+ self.send :define_method, provider, &block
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+ class Error < RuntimeError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,23 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+ def self.authentication_klass
4
+ Authentication
5
+ end
6
+
7
+ def self.resource_klass
8
+ User
9
+ end
10
+
11
+ def self.resource_mapping
12
+ :user
13
+ end
14
+
15
+ def self.current_resource
16
+ "current_#{resource_mapping}".to_sym
17
+ end
18
+
19
+ def self.authentication_relationship_name
20
+ :authentications
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ require 'hashugar'
2
+
3
+ class Authentication < ActiveRecord::Base
4
+ belongs_to OmniAuth::MultiProvider::resource_mapping
5
+ validates :provider, :uid, presence: true
6
+
7
+ def self.from(omniauth_data, resource)
8
+ auth = normalize(omniauth_data)
9
+ authentication = self.find_or_create(auth)
10
+ authentication.access_token = auth.credentials.token
11
+ authentication.resource = resource
12
+ authentication.save
13
+ authentication
14
+ end
15
+
16
+ def self.normalize(omniauth_data)
17
+ return omniauth_data if omniauth_data.is_a? Hashugar
18
+ normalized = omniauth_data.to_hashugar
19
+ normalized.delete(:extra)
20
+ normalized.credentials ||= {}
21
+ normalized.info ||= {}
22
+ normalized.info.delete(:description)
23
+ normalized
24
+ end
25
+
26
+ def resource
27
+ send OmniAuth::MultiProvider::resource_mapping
28
+ end
29
+
30
+ def resource=(resource)
31
+ send("#{OmniAuth::MultiProvider::resource_mapping}=", resource)
32
+ end
33
+
34
+ private
35
+
36
+ def self.find_or_create(auth)
37
+ self.find_by(
38
+ provider: auth.provider,
39
+ uid: auth.uid) ||
40
+ self.new(
41
+ provider: auth.provider,
42
+ uid: auth.uid,
43
+ access_token: auth.credentials.token)
44
+ end
45
+
46
+ end
@@ -0,0 +1,48 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+
4
+ module OmniAuthenticable
5
+ extend ActiveSupport::Concern
6
+
7
+ def self.authenticate_from_params(params)
8
+ resource = nil
9
+ if params[:username].present? && params[:password].present?
10
+ resource = MultiProvider::resource_klass.find_for_database_authentication(email: params[:username])
11
+ resource = nil if resource.nil? || !resource.valid_password?(params[:password])
12
+ end
13
+ if params[:provider].present?
14
+ omniauth_data = {
15
+ provider: params[:provider],
16
+ uid: params[:user_id],
17
+ credentials: {
18
+ token: params[:access_token]
19
+ }
20
+ }
21
+ provider_class = "OmniAuth::Provider::#{params[:provider].camelize}".constantize
22
+ resource = provider_class.authenticate_from_oauth(params[:provider], omniauth_data)
23
+ end
24
+ resource
25
+ end
26
+
27
+ included do
28
+ include MultiProvider::EmailMockups
29
+
30
+ has_many MultiProvider::authentication_relationship_name, dependent: :destroy, inverse_of: MultiProvider::resource_mapping, autosave: true, class_name: MultiProvider::authentication_klass.name do
31
+ def [](provider)
32
+ find_by(provider: provider)
33
+ end
34
+ end
35
+
36
+ omniauth_providers.each do |provider_name|
37
+ begin
38
+ klass = "OmniAuth::Provider::#{provider_name.to_s.camelize}".constantize
39
+ rescue NameError
40
+ klass = OmniAuth::Provider::Generic
41
+ end
42
+ klass.init(provider_name)
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+
4
+ module EmailMockups
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ def mocked_email?
11
+ email.match /.*@from\-.*\.com$/
12
+ end
13
+
14
+ def current_email
15
+ mocked_email? ? '' : email
16
+ end
17
+
18
+ module ClassMethods
19
+ def mock_email(provider, nickname)
20
+ "#{nickname}@from-#{provider}.example.com"
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module MultiProvider
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,70 @@
1
+ module OmniAuth
2
+ module Provider
3
+ class Abstract
4
+
5
+ def self.init
6
+ end
7
+
8
+ OmniAuth::MultiProvider::resource_klass.send(:include, OmniAuth::MultiProvider::EmailMockups)
9
+
10
+ def self.find_from_oauth(provider_name, omniauth_data, signed_in_resource=nil)
11
+ auth = MultiProvider::authentication_klass.normalize(omniauth_data)
12
+ access_token = auth.credentials.token
13
+ authentication = MultiProvider.authentication_klass.find_by(provider: provider_name, uid: auth.uid)
14
+
15
+ if authentication
16
+ if signed_in_resource
17
+ if authentication.resource == signed_in_resource
18
+ raise MultiProvider::Error.new 'already connected'
19
+ else
20
+ raise MultiProvider::Error.new 'already connected with other user'
21
+ end
22
+ end
23
+ authentication.resource
24
+ else
25
+ if auth.info[:email].blank?
26
+ auth.info[:email] = MultiProvider::resource_klass.mock_email(provider_name, auth.uid)
27
+ end
28
+ email = auth.info[:email]
29
+
30
+ raise MultiProvider::Error.new 'email_already_registered' if MultiProvider::resource_klass.find_by(email: email)
31
+
32
+ resource = signed_in_resource || MultiProvider::resource_klass.create(
33
+ email: email,
34
+ password: Devise.friendly_token[0,20]
35
+ )
36
+
37
+ MultiProvider.authentication_klass.from(auth, resource)
38
+
39
+ resource
40
+ end
41
+ end
42
+
43
+ def self.authenticate_from_oauth(provider_name, omniauth_data)
44
+ auth = MultiProvider::authentication_klass.normalize(omniauth_data)
45
+ access_token = auth.credentials.token
46
+ authentication = MultiProvider.authentication_klass.find_by(provider: provider_name, uid: auth.uid)
47
+
48
+ if authentication
49
+ authenticate(authentication.send(MultiProvider::resource_mapping), authentication, auth)
50
+ else
51
+ if auth.info[:email].blank?
52
+ auth.info[:email] = MultiProvider::resource_klass.mock_email(provider_name, auth.uid)
53
+ end
54
+ email = auth.info[:email]
55
+
56
+ raise MultiProvider::Error.new 'email_already_registered' if MultiProvider::resource_klass.find_by(email: email)
57
+
58
+ resource = MultiProvider::resource_klass.create(
59
+ email: email,
60
+ password: Devise.friendly_token[0,20]
61
+ )
62
+
63
+ MultiProvider.authentication_klass.from(auth, resource)
64
+
65
+ resource
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,14 @@
1
+ module OmniAuth
2
+ module Provider
3
+ class Facebook < Generic
4
+
5
+ def self.authenticate(resource, authentication, omniauth_data)
6
+ access_token = omniauth_data.credentials.token
7
+ fb_user = FbGraph::User.me(access_token).fetch
8
+ return nil unless fb_user.identifier == omniauth_data.uid
9
+ authentication.update!(access_token: access_token)
10
+ resource
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module OmniAuth
2
+ module Provider
3
+ class Generic < Abstract
4
+
5
+ def self.init(provider_name)
6
+ klass = self
7
+ OmniAuth::MultiProvider::CallbacksController.add_callback(provider_name) do
8
+ resource = klass.find_from_oauth(provider_name, request.env['omniauth.auth'], send(OmniAuth::MultiProvider::current_resource))
9
+ if resource.persisted?
10
+ sign_in_and_redirect resource, event: :authentication #this will throw if resource is not activated
11
+ set_flash_message(:notice, :success, kind: provider_name.to_s.camelize) if is_navigational_format?
12
+ else
13
+ session["devise.#{provider_name}_data"] = auth
14
+ redirect_to send("new_#{OmniAuth::MultiProvider::resource_mapping}_registration_url")
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module OmniAuth
2
+ module Provider
3
+ class Guests < Abstract
4
+
5
+ def self.authenticate(resource, authentication, omniauth_data)
6
+ return nil unless authentication.access_token == omniauth_data.credentials.token
7
+ resource
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'omniauth/multiprovider/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'omniauth-multiprovider'
6
+ s.version = OmniAuth::MultiProvider::VERSION
7
+ s.summary = "Authenticate devise users with multiple OAuth providers"
8
+ s.description = "Provides a simple approach to support many oauth providers to devise"
9
+ s.authors = ["German Del Zotto"]
10
+ s.email = 'germ@ndz.com.ar'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.require_paths = ['lib']
13
+ s.homepage = 'https://github.com/1uptalent/omniauth-multiprovider'
14
+ s.license = 'MIT'
15
+
16
+ s.add_dependency('devise', '~> 3.2')
17
+ s.add_dependency('omniauth-oauth2', '~> 1.1')
18
+ s.add_dependency('hashugar', '~> 0.0.6')
19
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-multiprovider
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - German Del Zotto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: devise
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: omniauth-oauth2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashugar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.6
55
+ description: Provides a simple approach to support many oauth providers to devise
56
+ email: germ@ndz.com.ar
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - LICENSE
63
+ - README.md
64
+ - lib/omniauth-multiprovider.rb
65
+ - lib/omniauth/multiprovider.rb
66
+ - lib/omniauth/multiprovider/controllers/callbacks_controller.rb
67
+ - lib/omniauth/multiprovider/error.rb
68
+ - lib/omniauth/multiprovider/helpers.rb
69
+ - lib/omniauth/multiprovider/models/authentication.rb
70
+ - lib/omniauth/multiprovider/models/concerns/omni_authenticable.rb
71
+ - lib/omniauth/multiprovider/models/email_mockups.rb
72
+ - lib/omniauth/multiprovider/version.rb
73
+ - lib/omniauth/provider/abstract.rb
74
+ - lib/omniauth/provider/facebook.rb
75
+ - lib/omniauth/provider/generic.rb
76
+ - lib/omniauth/provider/guests.rb
77
+ - omniauth-multiprovider.gemspec
78
+ homepage: https://github.com/1uptalent/omniauth-multiprovider
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.2.0
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Authenticate devise users with multiple OAuth providers
102
+ test_files: []
103
+ has_rdoc: