omniauth-multiprovider 0.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/LICENSE +21 -0
- data/README.md +57 -0
- data/lib/omniauth-multiprovider.rb +18 -0
- data/lib/omniauth/multiprovider.rb +2 -0
- data/lib/omniauth/multiprovider/controllers/callbacks_controller.rb +9 -0
- data/lib/omniauth/multiprovider/error.rb +6 -0
- data/lib/omniauth/multiprovider/helpers.rb +23 -0
- data/lib/omniauth/multiprovider/models/authentication.rb +46 -0
- data/lib/omniauth/multiprovider/models/concerns/omni_authenticable.rb +48 -0
- data/lib/omniauth/multiprovider/models/email_mockups.rb +26 -0
- data/lib/omniauth/multiprovider/version.rb +5 -0
- data/lib/omniauth/provider/abstract.rb +70 -0
- data/lib/omniauth/provider/facebook.rb +14 -0
- data/lib/omniauth/provider/generic.rb +21 -0
- data/lib/omniauth/provider/guests.rb +12 -0
- data/omniauth-multiprovider.gemspec +19 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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,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,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,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:
|