sorcery 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sorcery might be problematic. Click here for more details.

Files changed (33) hide show
  1. data/Gemfile.lock +2 -2
  2. data/README.rdoc +1 -1
  3. data/VERSION +1 -1
  4. data/lib/generators/sorcery/install_generator.rb +5 -3
  5. data/lib/generators/sorcery/templates/initializer.rb +25 -4
  6. data/lib/sorcery.rb +2 -0
  7. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +17 -18
  8. data/lib/sorcery/controller/submodules/external/providers/github.rb +11 -3
  9. data/lib/sorcery/controller/submodules/external/providers/google.rb +89 -0
  10. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +90 -0
  11. data/lib/sorcery/model.rb +17 -4
  12. data/lib/sorcery/model/adapters/active_record.rb +6 -1
  13. data/lib/sorcery/model/adapters/mongo_mapper.rb +6 -1
  14. data/lib/sorcery/model/adapters/mongoid.rb +6 -1
  15. data/lib/sorcery/model/submodules/activity_logging.rb +4 -4
  16. data/lib/sorcery/model/submodules/brute_force_protection.rb +5 -5
  17. data/lib/sorcery/model/submodules/reset_password.rb +4 -5
  18. data/lib/sorcery/model/submodules/user_activation.rb +1 -2
  19. data/sorcery.gemspec +4 -2
  20. data/spec/Gemfile.lock +3 -3
  21. data/spec/rails3/Gemfile +1 -2
  22. data/spec/rails3/Gemfile.lock +13 -14
  23. data/spec/rails3/app/controllers/application_controller.rb +26 -2
  24. data/spec/rails3/spec/controller_oauth2_spec.rb +111 -11
  25. data/spec/rails3/spec/controller_spec.rb +30 -2
  26. data/spec/rails3_mongo_mapper/Gemfile.lock +11 -11
  27. data/spec/rails3_mongo_mapper/spec/controller_spec.rb +34 -1
  28. data/spec/rails3_mongoid/Gemfile.lock +8 -8
  29. data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +3 -3
  30. data/spec/rails3_mongoid/spec/controller_spec.rb +34 -1
  31. data/spec/shared_examples/user_reset_password_shared_examples.rb +9 -1
  32. data/spec/sorcery_crypto_providers_spec.rb +5 -1
  33. metadata +4 -2
data/Gemfile.lock CHANGED
@@ -61,7 +61,7 @@ GEM
61
61
  oauth2 (0.4.1)
62
62
  faraday (~> 0.6.1)
63
63
  multi_json (>= 0.0.5)
64
- polyglot (0.3.2)
64
+ polyglot (0.3.3)
65
65
  rack (1.3.5)
66
66
  rack-cache (1.1)
67
67
  rack (>= 0.4)
@@ -129,7 +129,7 @@ GEM
129
129
  treetop (1.4.10)
130
130
  polyglot
131
131
  polyglot (>= 0.3.1)
132
- tzinfo (0.3.30)
132
+ tzinfo (0.3.31)
133
133
  yard (0.6.8)
134
134
 
135
135
  PLATFORMS
data/README.rdoc CHANGED
@@ -28,7 +28,7 @@ Railscast: http://railscasts.com/episodes/283-authentication-with-sorcery
28
28
 
29
29
  Example Rails 3 app using sorcery: https://github.com/NoamB/sorcery-example-app
30
30
 
31
- Documentation: http://rubydoc.info/gems/sorcery/0.7.4/frames
31
+ Documentation: http://rubydoc.info/gems/sorcery/0.7.5/frames
32
32
 
33
33
  Check out the tutorials in the github wiki!
34
34
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.4
1
+ 0.7.5
@@ -39,6 +39,9 @@ module Sorcery
39
39
 
40
40
  # Copy the migrations files to db/migrate folder
41
41
  def copy_migration_files
42
+ # Copy core migration file in all cases except when you pass --migrations.
43
+ migration_template "migration/core.rb", "db/migrate/sorcery_core.rb" unless options[:migrations]
44
+
42
45
  if submodules
43
46
  submodules.each do |submodule|
44
47
  unless submodule == "http_basic_auth" || submodule == "session_timeout"
@@ -47,8 +50,7 @@ module Sorcery
47
50
  end
48
51
  end
49
52
 
50
- # Copy core migration file in all cases except when you pass --migrations.
51
- migration_template "migration/core.rb", "db/migrate/sorcery_core.rb" unless options[:migrations]
53
+
52
54
  end
53
55
 
54
56
  # Define the next_migration_number method (necessary for the migration_template method to work)
@@ -69,4 +71,4 @@ module Sorcery
69
71
  end
70
72
  end
71
73
  end
72
- end
74
+ end
@@ -29,19 +29,22 @@ Rails.application.config.sorcery.configure do |config|
29
29
  # -- http_basic_auth --
30
30
  # config.controller_to_realm_map = {"application" => "Application"} # What realm to display for which controller name.
31
31
  # For example {"My App" => "Application"}
32
-
32
+
33
33
  # -- activity logging --
34
34
  # config.register_login_time = true # will register the time of last user login, every login.
35
35
  # config.register_logout_time = true # will register the time of last user logout, every logout.
36
36
  # config.register_last_activity_time = true # will register the time of last user action, every action.
37
-
37
+
38
38
  # -- external --
39
39
  # config.external_providers = [] # What providers are supported by this app,
40
- # i.e. [:twitter, :facebook, :github] .
40
+ # i.e. [:twitter, :facebook, :github, :google, :liveid] .
41
41
  # config.ca_file = 'path/to/ca_file' # Path to ca_file. By default use a internal ca-bundle.crt.
42
42
  # You can change it by your local ca_file.
43
43
  # i.e. '/etc/pki/tls/certs/ca-bundle.crt'
44
44
 
45
+ # Twitter wil not accept any requests nor redirect uri containing localhost,
46
+ # make sure you use 0.0.0.0:3000 to access your app in development
47
+ #
45
48
  # config.twitter.key = "eYVNBjBDi33aa9GkA3w"
46
49
  # config.twitter.secret = "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8"
47
50
  # config.twitter.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=twitter"
@@ -56,6 +59,20 @@ Rails.application.config.sorcery.configure do |config|
56
59
  # config.github.secret = ""
57
60
  # config.github.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=github"
58
61
  # config.github.user_info_mapping = {:email => "name"}
62
+ #
63
+ # config.google.key = "491253340633.apps.googleusercontent.com"
64
+ # config.google.secret = "4oE6kXqbL_LN-VGcGcg7qgdL"
65
+ # config.google.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=google"
66
+ # config.google.user_info_mapping = {:email => "email", :username => "name"}
67
+ #
68
+ # To use liveid in development mode you have to replace mydomain.com with
69
+ # a valid domain even in development. To use a valid domain in development
70
+ # simply add your domain in your /etc/hosts file in front of 127.0.0.1
71
+ #
72
+ # config.liveid.key = ""
73
+ # config.liveid.secret = ""
74
+ # config.liveid.callback_url = "http://mydomain.com:3000/oauth/callback?provider=liveid"
75
+ # config.liveid.user_info_mapping = {:username => "name"}
59
76
 
60
77
  # --- user config ---
61
78
  config.user_config do |user|
@@ -69,6 +86,10 @@ Rails.application.config.sorcery.configure do |config|
69
86
  # until an encrypted one is
70
87
  # generated.
71
88
 
89
+ # user.downcase_username_before_authenticating = false # downcase the username before
90
+ # trying to authenticate, default
91
+ # is false
92
+
72
93
  # user.email_attribute_name = :email # change default email attribute.
73
94
 
74
95
  # user.crypted_password_attribute_name = :crypted_password # change default crypted_password
@@ -88,7 +109,7 @@ Rails.application.config.sorcery.configure do |config|
88
109
  #
89
110
  # WARNING:
90
111
  #
91
- # If used for users' passwords, changing this key
112
+ # If used for users' passwords, changing this key
92
113
  # will leave passwords undecryptable!
93
114
 
94
115
  # user.custom_encryption_provider = nil # use an external encryption
data/lib/sorcery.rb CHANGED
@@ -34,6 +34,8 @@ module Sorcery
34
34
  autoload :Twitter, 'sorcery/controller/submodules/external/providers/twitter'
35
35
  autoload :Facebook, 'sorcery/controller/submodules/external/providers/facebook'
36
36
  autoload :Github, 'sorcery/controller/submodules/external/providers/github'
37
+ autoload :Google, 'sorcery/controller/submodules/external/providers/google'
38
+ autoload :Liveid, 'sorcery/controller/submodules/external/providers/liveid'
37
39
  end
38
40
  end
39
41
  end
@@ -8,35 +8,34 @@ module Sorcery
8
8
  def oauth_version
9
9
  "2.0"
10
10
  end
11
-
11
+
12
12
  def authorize_url(options = {})
13
- defaults = {
14
- :site => @site,
15
- :ssl => { :ca_file => Config.ca_file }
16
- }
17
- client = ::OAuth2::Client.new(
18
- @key,
19
- @secret,
20
- defaults.merge!(options)
21
- )
13
+ client = build_client(options)
22
14
  client.web_server.authorize_url(
23
15
  :redirect_uri => @callback_url,
24
16
  :scope => @scope
25
17
  )
26
18
  end
27
-
28
- def get_access_token(args)
29
- client = ::OAuth2::Client.new(
30
- @key,
31
- @secret,
32
- :site => @site,
33
- :ssl => { :ca_file => Config.ca_file }
34
- )
19
+
20
+ def get_access_token(args, options = {})
21
+ client = build_client(options)
35
22
  client.web_server.get_access_token(
36
23
  args[:code],
37
24
  :redirect_uri => @callback_url
38
25
  )
39
26
  end
27
+
28
+ def build_client(options = {})
29
+ defaults = {
30
+ :site => @site,
31
+ :ssl => { :ca_file => Config.ca_file }
32
+ }
33
+ ::OAuth2::Client.new(
34
+ @key,
35
+ @secret,
36
+ defaults.merge!(options)
37
+ )
38
+ end
40
39
  end
41
40
  end
42
41
  end
@@ -31,6 +31,8 @@ module Sorcery
31
31
  attr_accessor :key,
32
32
  :secret,
33
33
  :callback_url,
34
+ :auth_path,
35
+ :token_path,
34
36
  :site,
35
37
  :user_info_path,
36
38
  :user_info_mapping
@@ -39,7 +41,9 @@ module Sorcery
39
41
 
40
42
  def init
41
43
  @site = "https://github.com/"
42
- @user_info_path = "/api/v2/json/user/show"
44
+ @user_info_path = "https://api.github.com/user"
45
+ @auth_path = "/login/oauth/authorize"
46
+ @token_path = "/login/oauth/access_token"
43
47
  @user_info_mapping = {}
44
48
  end
45
49
 
@@ -58,14 +62,18 @@ module Sorcery
58
62
  # calculates and returns the url to which the user should be redirected,
59
63
  # to get authenticated at the external provider's site.
60
64
  def login_url(params,session)
61
- self.authorize_url({:authorize_path => '/login/oauth/authorize'})
65
+ self.authorize_url({:authorize_path => @auth_path})
62
66
  end
63
67
 
64
68
  # tries to login the user from access token
65
69
  def process_callback(params,session)
66
70
  args = {}
67
71
  args.merge!({:code => params[:code]}) if params[:code]
68
- @access_token = self.get_access_token(args)
72
+ options = {
73
+ :access_token_path => @token_path,
74
+ :access_token_method => :post
75
+ }
76
+ @access_token = self.get_access_token(args, options)
69
77
  end
70
78
 
71
79
  end
@@ -0,0 +1,89 @@
1
+ module Sorcery
2
+ module Controller
3
+ module Submodules
4
+ module External
5
+ module Providers
6
+ # This module adds support for OAuth with google.com.
7
+ # When included in the 'config.providers' option, it adds a new option, 'config.google'.
8
+ # Via this new option you can configure Google specific settings like your app's key and secret.
9
+ #
10
+ # config.google.key = <key>
11
+ # config.google.secret = <secret>
12
+ # ...
13
+ #
14
+ module Google
15
+ def self.included(base)
16
+ base.module_eval do
17
+ class << self
18
+ attr_reader :google # access to google_client.
19
+
20
+ def merge_google_defaults!
21
+ @defaults.merge!(:@google => GoogleClient)
22
+ end
23
+ end
24
+ merge_google_defaults!
25
+ update!
26
+ end
27
+ end
28
+
29
+ module GoogleClient
30
+ class << self
31
+ attr_accessor :key,
32
+ :secret,
33
+ :callback_url,
34
+ :site,
35
+ :auth_url,
36
+ :token_path,
37
+ :user_info_url,
38
+ :scope,
39
+ :user_info_mapping
40
+
41
+ include Protocols::Oauth2
42
+
43
+ def init
44
+ @site = "https://accounts.google.com"
45
+ @auth_url = "/o/oauth2/auth"
46
+ @token_path = "/o/oauth2/token"
47
+ @user_info_url = "https://www.googleapis.com/oauth2/v1/userinfo"
48
+ @scope = "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
49
+ @user_info_mapping = {}
50
+ end
51
+
52
+ def get_user_hash
53
+ user_hash = {}
54
+ response = @access_token.get(@user_info_url)
55
+ user_hash[:user_info] = JSON.parse(response)
56
+ user_hash[:uid] = user_hash[:user_info]['id']
57
+ user_hash
58
+ end
59
+
60
+ def has_callback?
61
+ true
62
+ end
63
+
64
+ # calculates and returns the url to which the user should be redirected,
65
+ # to get authenticated at the external provider's site.
66
+ def login_url(params,session)
67
+ self.authorize_url({:authorize_url => @auth_url})
68
+ end
69
+
70
+ # tries to login the user from access token
71
+ def process_callback(params,session)
72
+ args = {}
73
+ args.merge!({:code => params[:code]}) if params[:code]
74
+ options = {
75
+ :access_token_path => @token_path,
76
+ :access_token_method => :post
77
+ }
78
+ @access_token = self.get_access_token(args, options)
79
+ end
80
+ end
81
+ init
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,90 @@
1
+ module Sorcery
2
+ module Controller
3
+ module Submodules
4
+ module External
5
+ module Providers
6
+ # This module adds support for OAuth with microsoft liveid
7
+ # When included in the 'config.providers' option, it adds a new option, 'config.liveid'.
8
+ # Via this new option you can configure LiveId specific settings like your app's key and secret.
9
+ #
10
+ # config.liveid.key = <key>
11
+ # config.liveid.secret = <secret>
12
+ # ...
13
+ #
14
+ module Liveid
15
+ def self.included(base)
16
+ base.module_eval do
17
+ class << self
18
+ attr_reader :liveid # access to liveid_client.
19
+
20
+ def merge_liveid_defaults!
21
+ @defaults.merge!(:@liveid => LiveidClient)
22
+ end
23
+ end
24
+ merge_liveid_defaults!
25
+ update!
26
+ end
27
+ end
28
+
29
+ module LiveidClient
30
+ class << self
31
+ attr_accessor :key,
32
+ :secret,
33
+ :callback_url,
34
+ :site,
35
+ :auth_url,
36
+ :token_path,
37
+ :user_info_url,
38
+ :scope,
39
+ :user_info_mapping
40
+
41
+ include Protocols::Oauth2
42
+
43
+ def init
44
+ @site = "https://oauth.live.com/"
45
+ @auth_url = "/authorize"
46
+ @token_path = "/token"
47
+ @user_info_url = "https://apis.live.net/v5.0/me"
48
+ @scope = "wl.basic wl.emails wl.offline_access"
49
+ @user_info_mapping = {}
50
+ end
51
+
52
+ def get_user_hash
53
+ user_hash = {}
54
+ @access_token.token_param = "access_token"
55
+ response = @access_token.get(@user_info_url)
56
+ user_hash[:user_info] = JSON.parse(response)
57
+ user_hash[:uid] = user_hash[:user_info]['id']
58
+ user_hash
59
+ end
60
+
61
+ def has_callback?
62
+ true
63
+ end
64
+
65
+ # calculates and returns the url to which the user should be redirected,
66
+ # to get authenticated at the external provider's site.
67
+ def login_url(params,session)
68
+ self.authorize_url({:authorize_url => @auth_url})
69
+ end
70
+
71
+ # tries to login the user from access token
72
+ def process_callback(params,session)
73
+ args = {}
74
+ args.merge!({:code => params[:code]}) if params[:code]
75
+ options = {
76
+ :access_token_path => @token_path,
77
+ :access_token_method => :post
78
+ }
79
+ @access_token = self.get_access_token(args, options)
80
+ end
81
+ end
82
+ init
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
data/lib/sorcery/model.rb CHANGED
@@ -104,7 +104,11 @@ module Sorcery
104
104
  # returns the user if success, nil otherwise.
105
105
  def authenticate(*credentials)
106
106
  raise ArgumentError, "at least 2 arguments required" if credentials.size < 2
107
+ credentials[0].downcase! if @sorcery_config.downcase_username_before_authenticating
107
108
  user = find_by_credentials(credentials)
109
+
110
+ set_encryption_attributes()
111
+
108
112
  _salt = user.send(@sorcery_config.salt_attribute_name) if user && !@sorcery_config.salt_attribute_name.nil? && !@sorcery_config.encryption_provider.nil?
109
113
  user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && credentials_match?(user.send(@sorcery_config.crypted_password_attribute_name),credentials[1],_salt)
110
114
  end
@@ -113,14 +117,19 @@ module Sorcery
113
117
  def encrypt(*tokens)
114
118
  return tokens.first if @sorcery_config.encryption_provider.nil?
115
119
 
116
- @sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
117
- @sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
120
+ set_encryption_attributes()
121
+
118
122
  CryptoProviders::AES256.key = @sorcery_config.encryption_key
119
123
  @sorcery_config.encryption_provider.encrypt(*tokens)
120
124
  end
121
125
 
122
126
  protected
123
-
127
+
128
+ def set_encryption_attributes()
129
+ @sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
130
+ @sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
131
+ end
132
+
124
133
  # Calls the configured encryption provider to compare the supplied password with the encrypted one.
125
134
  def credentials_match?(crypted, *tokens)
126
135
  return crypted == tokens.join if @sorcery_config.encryption_provider.nil?
@@ -193,6 +202,9 @@ module Sorcery
193
202
  # until an encrypted one is generated.
194
203
 
195
204
  :email_attribute_name, # change default email attribute.
205
+
206
+ :downcase_username_before_authenticating, # downcase the username before trying to authenticate, default is false
207
+
196
208
  :crypted_password_attribute_name, # change default crypted_password attribute.
197
209
  :salt_join_token, # what pattern to use to join the password with the salt
198
210
  :salt_attribute_name, # change default salt attribute.
@@ -220,6 +232,7 @@ module Sorcery
220
232
  :@submodules => [],
221
233
  :@username_attribute_names => [:username],
222
234
  :@password_attribute_name => :password,
235
+ :@downcase_username_before_authenticating => false,
223
236
  :@email_attribute_name => :email,
224
237
  :@crypted_password_attribute_name => :crypted_password,
225
238
  :@encryption_algorithm => :bcrypt,
@@ -268,4 +281,4 @@ module Sorcery
268
281
  end
269
282
 
270
283
  end
271
- end
284
+ end