omniauth-multiprovider 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|