cbsorcery 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|