cbsorcery 0.8.6
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/.document +5 -0
- data/.gitignore +56 -0
- data/.rspec +1 -0
- data/.travis.yml +40 -0
- data/CHANGELOG.md +263 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +360 -0
- data/Rakefile +6 -0
- data/gemfiles/active_record-rails40.gemfile +7 -0
- data/gemfiles/active_record-rails41.gemfile +7 -0
- data/lib/generators/sorcery/USAGE +22 -0
- data/lib/generators/sorcery/helpers.rb +40 -0
- data/lib/generators/sorcery/install_generator.rb +95 -0
- data/lib/generators/sorcery/templates/initializer.rb +451 -0
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +10 -0
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +9 -0
- data/lib/generators/sorcery/templates/migration/core.rb +13 -0
- data/lib/generators/sorcery/templates/migration/external.rb +12 -0
- data/lib/generators/sorcery/templates/migration/remember_me.rb +8 -0
- data/lib/generators/sorcery/templates/migration/reset_password.rb +9 -0
- data/lib/generators/sorcery/templates/migration/user_activation.rb +9 -0
- data/lib/sorcery.rb +85 -0
- data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
- data/lib/sorcery/adapters/base_adapter.rb +30 -0
- data/lib/sorcery/controller.rb +157 -0
- data/lib/sorcery/controller/config.rb +65 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +82 -0
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +38 -0
- data/lib/sorcery/controller/submodules/external.rb +199 -0
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +74 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +81 -0
- data/lib/sorcery/controller/submodules/session_timeout.rb +56 -0
- data/lib/sorcery/crypto_providers/aes256.rb +51 -0
- data/lib/sorcery/crypto_providers/bcrypt.rb +97 -0
- data/lib/sorcery/crypto_providers/common.rb +35 -0
- data/lib/sorcery/crypto_providers/md5.rb +19 -0
- data/lib/sorcery/crypto_providers/sha1.rb +28 -0
- data/lib/sorcery/crypto_providers/sha256.rb +36 -0
- data/lib/sorcery/crypto_providers/sha512.rb +36 -0
- data/lib/sorcery/engine.rb +21 -0
- data/lib/sorcery/model.rb +183 -0
- data/lib/sorcery/model/config.rb +96 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +70 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +125 -0
- data/lib/sorcery/model/submodules/external.rb +100 -0
- data/lib/sorcery/model/submodules/remember_me.rb +62 -0
- data/lib/sorcery/model/submodules/reset_password.rb +131 -0
- data/lib/sorcery/model/submodules/user_activation.rb +149 -0
- data/lib/sorcery/model/temporary_token.rb +30 -0
- data/lib/sorcery/protocols/certs/ca-bundle.crt +5182 -0
- data/lib/sorcery/protocols/oauth.rb +42 -0
- data/lib/sorcery/protocols/oauth2.rb +47 -0
- data/lib/sorcery/providers/base.rb +27 -0
- data/lib/sorcery/providers/facebook.rb +63 -0
- data/lib/sorcery/providers/github.rb +51 -0
- data/lib/sorcery/providers/google.rb +51 -0
- data/lib/sorcery/providers/jira.rb +77 -0
- data/lib/sorcery/providers/linkedin.rb +66 -0
- data/lib/sorcery/providers/liveid.rb +53 -0
- data/lib/sorcery/providers/twitter.rb +59 -0
- data/lib/sorcery/providers/vk.rb +63 -0
- data/lib/sorcery/providers/xing.rb +64 -0
- data/lib/sorcery/railties/tasks.rake +6 -0
- data/lib/sorcery/test_helpers/internal.rb +78 -0
- data/lib/sorcery/test_helpers/internal/rails.rb +68 -0
- data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
- data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
- data/lib/sorcery/version.rb +3 -0
- data/sorcery.gemspec +34 -0
- data/spec/active_record/user_activation_spec.rb +18 -0
- data/spec/active_record/user_activity_logging_spec.rb +17 -0
- data/spec/active_record/user_brute_force_protection_spec.rb +16 -0
- data/spec/active_record/user_oauth_spec.rb +16 -0
- data/spec/active_record/user_remember_me_spec.rb +16 -0
- data/spec/active_record/user_reset_password_spec.rb +16 -0
- data/spec/active_record/user_spec.rb +37 -0
- data/spec/controllers/controller_activity_logging_spec.rb +124 -0
- data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
- data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
- data/spec/controllers/controller_oauth2_spec.rb +407 -0
- data/spec/controllers/controller_oauth_spec.rb +240 -0
- data/spec/controllers/controller_remember_me_spec.rb +117 -0
- data/spec/controllers/controller_session_timeout_spec.rb +80 -0
- data/spec/controllers/controller_spec.rb +215 -0
- data/spec/orm/active_record.rb +21 -0
- data/spec/rails_app/app/active_record/authentication.rb +3 -0
- data/spec/rails_app/app/active_record/user.rb +5 -0
- data/spec/rails_app/app/active_record/user_provider.rb +3 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +265 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +32 -0
- data/spec/rails_app/app/views/application/index.html.erb +17 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.text.erb +9 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
- data/spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +56 -0
- data/spec/rails_app/config/boot.rb +4 -0
- data/spec/rails_app/config/database.yml +22 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/test.rb +37 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_app/config/initializers/session_store.rb +12 -0
- data/spec/rails_app/config/locales/en.yml +5 -0
- data/spec/rails_app/config/routes.rb +48 -0
- data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +19 -0
- data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +13 -0
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +16 -0
- data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +22 -0
- data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
- data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/rails_app/db/schema.rb +23 -0
- data/spec/rails_app/db/seeds.rb +7 -0
- data/spec/shared_examples/user_activation_shared_examples.rb +242 -0
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +97 -0
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +156 -0
- data/spec/shared_examples/user_oauth_shared_examples.rb +36 -0
- data/spec/shared_examples/user_remember_me_shared_examples.rb +57 -0
- data/spec/shared_examples/user_reset_password_shared_examples.rb +263 -0
- data/spec/shared_examples/user_shared_examples.rb +467 -0
- data/spec/sorcery_crypto_providers_spec.rb +198 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +41 -0
- metadata +350 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'oauth'
|
|
2
|
+
|
|
3
|
+
module Sorcery
|
|
4
|
+
module Protocols
|
|
5
|
+
module Oauth
|
|
6
|
+
|
|
7
|
+
def oauth_version
|
|
8
|
+
'1.0'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_request_token(token=nil,secret=nil)
|
|
12
|
+
return ::OAuth::RequestToken.new(get_consumer, token, secret) if token && secret
|
|
13
|
+
get_consumer.get_request_token(oauth_callback: @callback_url)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def authorize_url(args)
|
|
17
|
+
get_request_token(
|
|
18
|
+
args[:request_token],
|
|
19
|
+
args[:request_token_secret]
|
|
20
|
+
).authorize_url({
|
|
21
|
+
oauth_callback: @callback_url
|
|
22
|
+
})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_access_token(args)
|
|
26
|
+
get_request_token(
|
|
27
|
+
args[:request_token],
|
|
28
|
+
args[:request_token_secret]
|
|
29
|
+
).get_access_token({
|
|
30
|
+
oauth_verifier: args[:oauth_verifier]
|
|
31
|
+
})
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def get_consumer
|
|
37
|
+
::OAuth::Consumer.new(@key, @secret, site: @site)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'oauth2'
|
|
2
|
+
|
|
3
|
+
module Sorcery
|
|
4
|
+
module Protocols
|
|
5
|
+
module Oauth2
|
|
6
|
+
|
|
7
|
+
def oauth_version
|
|
8
|
+
'2.0'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def authorize_url(options = {})
|
|
12
|
+
client = build_client(options)
|
|
13
|
+
client.auth_code.authorize_url(
|
|
14
|
+
redirect_uri: @callback_url,
|
|
15
|
+
scope: @scope,
|
|
16
|
+
display: @display,
|
|
17
|
+
state: @state
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get_access_token(args, options = {})
|
|
22
|
+
client = build_client(options)
|
|
23
|
+
client.auth_code.get_token(
|
|
24
|
+
args[:code],
|
|
25
|
+
{
|
|
26
|
+
redirect_uri: @callback_url,
|
|
27
|
+
parse: options.delete(:parse)
|
|
28
|
+
},
|
|
29
|
+
options
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_client(options = {})
|
|
34
|
+
defaults = {
|
|
35
|
+
site: @site,
|
|
36
|
+
ssl: { ca_file: Sorcery::Controller::Config.ca_file }
|
|
37
|
+
}
|
|
38
|
+
::OAuth2::Client.new(
|
|
39
|
+
@key,
|
|
40
|
+
@secret,
|
|
41
|
+
defaults.merge!(options)
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
class Base
|
|
4
|
+
|
|
5
|
+
attr_reader :access_token
|
|
6
|
+
|
|
7
|
+
attr_accessor :callback_url, :key, :original_callback_url, :secret,
|
|
8
|
+
:site, :state, :user_info_mapping
|
|
9
|
+
|
|
10
|
+
def has_callback?; true; end
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@user_info_mapping = {}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.name
|
|
17
|
+
super.gsub(/Sorcery::Providers::/, '').downcase
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Ensure that all descendant classes are loaded before run this
|
|
21
|
+
def self.descendants
|
|
22
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with facebook.com.
|
|
4
|
+
#
|
|
5
|
+
# config.facebook.key = <key>
|
|
6
|
+
# config.facebook.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Facebook < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth2
|
|
12
|
+
|
|
13
|
+
attr_reader :mode, :param_name, :parse
|
|
14
|
+
attr_accessor :access_permissions, :display, :scope, :token_url,
|
|
15
|
+
:user_info_path
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
@site = 'https://graph.facebook.com'
|
|
21
|
+
@user_info_path = '/me'
|
|
22
|
+
@scope = 'email,offline_access'
|
|
23
|
+
@display = 'page'
|
|
24
|
+
@token_url = 'oauth/access_token'
|
|
25
|
+
@mode = :query
|
|
26
|
+
@parse = :query
|
|
27
|
+
@param_name = 'access_token'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def get_user_hash(access_token)
|
|
31
|
+
response = access_token.get(user_info_path)
|
|
32
|
+
|
|
33
|
+
{}.tap do |h|
|
|
34
|
+
h[:user_info] = JSON.parse(response.body)
|
|
35
|
+
h[:uid] = h[:user_info]['id']
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# calculates and returns the url to which the user should be redirected,
|
|
40
|
+
# to get authenticated at the external provider's site.
|
|
41
|
+
def login_url(params, session)
|
|
42
|
+
authorize_url
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# overrides oauth2#authorize_url to allow customized scope.
|
|
46
|
+
def authorize_url
|
|
47
|
+
@scope = access_permissions.present? ? access_permissions.join(',') : scope
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# tries to login the user from access token
|
|
52
|
+
def process_callback(params, session)
|
|
53
|
+
args = {}.tap do |a|
|
|
54
|
+
a[:code] = params[:code] if params[:code]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
get_access_token(args, token_url: token_url, mode: mode,
|
|
58
|
+
param_name: param_name, parse: parse)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with github.com.
|
|
4
|
+
#
|
|
5
|
+
# config.github.key = <key>
|
|
6
|
+
# config.github.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Github < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth2
|
|
12
|
+
|
|
13
|
+
attr_accessor :auth_path, :scope, :token_url, :user_info_path
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
super
|
|
17
|
+
|
|
18
|
+
@scope = nil
|
|
19
|
+
@site = 'https://github.com/'
|
|
20
|
+
@user_info_path = 'https://api.github.com/user'
|
|
21
|
+
@auth_path = '/login/oauth/authorize'
|
|
22
|
+
@token_url = '/login/oauth/access_token'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_user_hash(access_token)
|
|
26
|
+
response = access_token.get(user_info_path)
|
|
27
|
+
|
|
28
|
+
{}.tap do |h|
|
|
29
|
+
h[:user_info] = JSON.parse(response.body)
|
|
30
|
+
h[:uid] = h[:user_info]['id']
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# calculates and returns the url to which the user should be redirected,
|
|
35
|
+
# to get authenticated at the external provider's site.
|
|
36
|
+
def login_url(params, session)
|
|
37
|
+
authorize_url({ authorize_url: auth_path })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# tries to login the user from access token
|
|
41
|
+
def process_callback(params, session)
|
|
42
|
+
args = {}.tap do |a|
|
|
43
|
+
a[:code] = params[:code] if params[:code]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
get_access_token(args, token_url: token_url, token_method: :post)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with google.com.
|
|
4
|
+
#
|
|
5
|
+
# config.google.key = <key>
|
|
6
|
+
# config.google.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Google < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth2
|
|
12
|
+
|
|
13
|
+
attr_accessor :auth_url, :scope, :token_url, :user_info_url
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
super
|
|
17
|
+
|
|
18
|
+
@site = 'https://accounts.google.com'
|
|
19
|
+
@auth_url = '/o/oauth2/auth'
|
|
20
|
+
@token_url = '/o/oauth2/token'
|
|
21
|
+
@user_info_url = 'https://www.googleapis.com/oauth2/v1/userinfo'
|
|
22
|
+
@scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_user_hash(access_token)
|
|
26
|
+
response = access_token.get(user_info_url)
|
|
27
|
+
|
|
28
|
+
{}.tap do |h|
|
|
29
|
+
h[:user_info] = JSON.parse(response.body)
|
|
30
|
+
h[:uid] = h[:user_info]['id']
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# calculates and returns the url to which the user should be redirected,
|
|
35
|
+
# to get authenticated at the external provider's site.
|
|
36
|
+
def login_url(params, session)
|
|
37
|
+
authorize_url({ authorize_url: auth_url })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# tries to login the user from access token
|
|
41
|
+
def process_callback(params, session)
|
|
42
|
+
args = {}.tap do |a|
|
|
43
|
+
a[:code] = params[:code] if params[:code]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
get_access_token(args, token_url: token_url, token_method: :post)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with Jira
|
|
4
|
+
#
|
|
5
|
+
# config.jira.key = <key>
|
|
6
|
+
# config.jira.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Jira < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth
|
|
12
|
+
|
|
13
|
+
attr_accessor :access_token_path, :authorize_path, :request_token_path,
|
|
14
|
+
:user_info_path, :site, :signature_method, :private_key_file, :callback_url
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@configuration = {
|
|
19
|
+
authorize_path: '/authorize',
|
|
20
|
+
request_token_path: '/request-token',
|
|
21
|
+
access_token_path: '/access-token'
|
|
22
|
+
}
|
|
23
|
+
@user_info_path = '/users/me'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Override included get_consumer method to provide authorize_path
|
|
27
|
+
#read extra configurations
|
|
28
|
+
def get_consumer
|
|
29
|
+
@configuration = @configuration.merge({
|
|
30
|
+
site: site,
|
|
31
|
+
signature_method: signature_method,
|
|
32
|
+
consumer_key: key,
|
|
33
|
+
private_key_file: private_key_file
|
|
34
|
+
})
|
|
35
|
+
::OAuth::Consumer.new(@key, @secret, @configuration)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def get_user_hash(access_token)
|
|
39
|
+
response = access_token.get(user_info_path)
|
|
40
|
+
|
|
41
|
+
{}.tap do |h|
|
|
42
|
+
h[:user_info] = JSON.parse(response.body)['users'].first
|
|
43
|
+
h[:uid] = user_hash[:user_info]['id'].to_s
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# calculates and returns the url to which the user should be redirected,
|
|
48
|
+
# to get authenticated at the external provider's site.
|
|
49
|
+
def login_url(params, session)
|
|
50
|
+
req_token = get_request_token
|
|
51
|
+
session[:request_token] = req_token.token
|
|
52
|
+
session[:request_token_secret] = req_token.secret
|
|
53
|
+
|
|
54
|
+
#it was like that -> redirect_to authorize_url({ request_token: req_token.token, request_token_secret: req_token.secret })
|
|
55
|
+
#for some reason Jira does not need these parameters
|
|
56
|
+
|
|
57
|
+
get_request_token(
|
|
58
|
+
session[:request_token],
|
|
59
|
+
session[:request_token_secret]
|
|
60
|
+
).authorize_url
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# tries to login the user from access token
|
|
64
|
+
def process_callback(params, session)
|
|
65
|
+
args = {
|
|
66
|
+
oauth_verifier: params[:oauth_verifier],
|
|
67
|
+
request_token: session[:request_token],
|
|
68
|
+
request_token_secret: session[:request_token_secret]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
args.merge!({ code: params[:code] }) if params[:code]
|
|
72
|
+
get_access_token(args)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with Linkedin.com.
|
|
4
|
+
#
|
|
5
|
+
# config.linkedin.key = <key>
|
|
6
|
+
# config.linkedin.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Linkedin < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth
|
|
12
|
+
|
|
13
|
+
attr_accessor :authorize_path, :access_permissions, :access_token_path,
|
|
14
|
+
:request_token_path, :user_info_fields, :user_info_path
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
@configuration = {
|
|
18
|
+
site: 'https://api.linkedin.com',
|
|
19
|
+
authorize_path: '/uas/oauth/authenticate',
|
|
20
|
+
request_token_path: '/uas/oauth/requestToken',
|
|
21
|
+
access_token_path: '/uas/oauth/accessToken'
|
|
22
|
+
}
|
|
23
|
+
@user_info_path = '/v1/people/~'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Override included get_consumer method to provide authorize_path
|
|
27
|
+
def get_consumer
|
|
28
|
+
# Add access permissions to request token path
|
|
29
|
+
@configuration[:request_token_path] += '?scope=' + access_permissions.join('+') unless access_permissions.blank? or @configuration[:request_token_path].include? '?scope='
|
|
30
|
+
::OAuth::Consumer.new(@key, @secret, @configuration)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def get_user_hash(access_token)
|
|
34
|
+
fields = self.user_info_fields.join(',')
|
|
35
|
+
response = access_token.get("#{@user_info_path}:(#{fields})", 'x-li-format' => 'json')
|
|
36
|
+
|
|
37
|
+
{}.tap do |h|
|
|
38
|
+
h[:user_info] = JSON.parse(response.body)
|
|
39
|
+
h[:uid] = h[:user_info]['id'].to_s
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# calculates and returns the url to which the user should be redirected,
|
|
44
|
+
# to get authenticated at the external provider's site.
|
|
45
|
+
def login_url(params, session)
|
|
46
|
+
req_token = get_request_token
|
|
47
|
+
session[:request_token] = req_token.token
|
|
48
|
+
session[:request_token_secret] = req_token.secret
|
|
49
|
+
authorize_url({ request_token: req_token.token, request_token_secret: req_token.secret })
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# tries to login the user from access token
|
|
53
|
+
def process_callback(params, session)
|
|
54
|
+
args = {
|
|
55
|
+
oauth_verifier: params[:oauth_verifier],
|
|
56
|
+
request_token: session[:request_token],
|
|
57
|
+
request_token_secret: session[:request_token_secret]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
args.merge!({ code: params[:code] }) if params[:code]
|
|
61
|
+
get_access_token(args)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Sorcery
|
|
2
|
+
module Providers
|
|
3
|
+
# This class adds support for OAuth with microsoft liveid.
|
|
4
|
+
#
|
|
5
|
+
# config.liveid.key = <key>
|
|
6
|
+
# config.liveid.secret = <secret>
|
|
7
|
+
# ...
|
|
8
|
+
#
|
|
9
|
+
class Liveid < Base
|
|
10
|
+
|
|
11
|
+
include Protocols::Oauth2
|
|
12
|
+
|
|
13
|
+
attr_accessor :auth_url, :token_path, :user_info_url, :scope
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
super
|
|
17
|
+
|
|
18
|
+
@site = 'https://oauth.live.com/'
|
|
19
|
+
@auth_url = '/authorize'
|
|
20
|
+
@token_path = '/token'
|
|
21
|
+
@user_info_url = 'https://apis.live.net/v5.0/me'
|
|
22
|
+
@scope = 'wl.basic wl.emails wl.offline_access'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_user_hash(access_token)
|
|
26
|
+
access_token.token_param = 'access_token'
|
|
27
|
+
response = access_token.get(user_info_url)
|
|
28
|
+
|
|
29
|
+
{}.tap do |h|
|
|
30
|
+
h[:user_info] = JSON.parse(response.body)
|
|
31
|
+
h[:uid] = h[:user_info]['id']
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# calculates and returns the url to which the user should be redirected,
|
|
36
|
+
# to get authenticated at the external provider's site.
|
|
37
|
+
def login_url(params, session)
|
|
38
|
+
self.authorize_url({ authorize_url: auth_url })
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# tries to login the user from access token
|
|
42
|
+
def process_callback(params, session)
|
|
43
|
+
args = {}.tap do |a|
|
|
44
|
+
a[:code] = params[:code] if params[:code]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
get_access_token(args, access_token_path: token_path,
|
|
48
|
+
access_token_method: :post)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|