authlogic-connect 0.0.3.9 → 0.0.4.03

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/README.markdown +9 -5
  2. data/Rakefile +7 -3
  3. data/lib/authlogic-connect.rb +2 -2
  4. data/lib/authlogic_connect/{token.rb → access_token.rb} +1 -1
  5. data/lib/authlogic_connect/authlogic_connect.rb +0 -0
  6. data/lib/authlogic_connect/common/session.rb +13 -10
  7. data/lib/authlogic_connect/common/state.rb +21 -5
  8. data/lib/authlogic_connect/common/user.rb +27 -65
  9. data/lib/authlogic_connect/common/variables.rb +75 -11
  10. data/lib/authlogic_connect/oauth/helper.rb +0 -0
  11. data/lib/authlogic_connect/oauth/process.rb +19 -12
  12. data/lib/authlogic_connect/oauth/session.rb +15 -11
  13. data/lib/authlogic_connect/oauth/state.rb +19 -13
  14. data/lib/authlogic_connect/oauth/tokens/aol_token.rb +2 -0
  15. data/lib/authlogic_connect/oauth/tokens/google_token.rb +11 -11
  16. data/lib/authlogic_connect/oauth/tokens/meetup_token.rb +12 -0
  17. data/lib/authlogic_connect/oauth/tokens/netflix_token.rb +10 -0
  18. data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +6 -2
  19. data/lib/authlogic_connect/oauth/tokens/ohloh_token.rb +9 -0
  20. data/lib/authlogic_connect/oauth/user.rb +9 -14
  21. data/lib/authlogic_connect/oauth/variables.rb +9 -0
  22. data/lib/authlogic_connect/openid/process.rb +49 -5
  23. data/lib/authlogic_connect/openid/session.rb +13 -34
  24. data/lib/authlogic_connect/openid/state.rb +45 -44
  25. data/lib/authlogic_connect/openid/tokens/openid_token.rb +1 -1
  26. data/lib/authlogic_connect/openid/user.rb +5 -29
  27. data/lib/authlogic_connect/openid/variables.rb +2 -2
  28. data/lib/open_id_authentication.rb +0 -1
  29. data/test/controllers/test_users_controller.rb +0 -0
  30. data/test/libs/database.rb +0 -0
  31. data/test/libs/user.rb +6 -2
  32. data/test/libs/user_session.rb +0 -0
  33. data/test/test_helper.rb +1 -1
  34. data/test/test_user.rb +5 -66
  35. metadata +10 -6
data/README.markdown CHANGED
@@ -1,8 +1,8 @@
1
1
  # AuthlogicConnect
2
2
 
3
- AuthlogicConnect is an extension of the Authlogic library to add extensive Oauth and OpenID support.
3
+ AuthlogicConnect is an extension of the Authlogic library that aims to add complete and seamless Oauth and OpenID support to your application.
4
4
 
5
- It allows you to login through any of the 30+ Oauth and OpenID providers on the Internet.
5
+ It allows you to login through any of the 30+ Oauth and OpenID providers on the Internet without having to write any of the logic yourself.
6
6
 
7
7
  That makes life easy and gives you a lot of power.
8
8
 
@@ -32,7 +32,7 @@ AuthlogicConnect currently allows you to login with 7 Oauth providers and all th
32
32
  - [OpenID Providers](http://en.wikipedia.org/wiki/List_of_OpenID_providers)
33
33
  - [More OpenID](http://openid.net/get-an-openid/)
34
34
 
35
- ## Install and use
35
+ ## Install
36
36
 
37
37
  ### 1. Install AuthlogicConnect
38
38
 
@@ -57,7 +57,7 @@ Rails 3: `Gemfile`
57
57
  gem "oauth2"
58
58
  gem "authlogic-connect"
59
59
 
60
- ### 3. Add the `OpenIdAuthentication.store`
60
+ ### 3. Add the OpenIdAuthentication.store
61
61
 
62
62
  Do to [some strange problem](http://github.com/openid/ruby-openid/issues#issue/1) I have yet to really understand, Rails 2.3.5 doesn't like when `OpenIdAuthentication.store` is null, which means it uses the "in memory" store and for some reason fails.
63
63
 
@@ -237,4 +237,8 @@ Thanks for the people that are already extending the project, all the input maki
237
237
 
238
238
  Feel free to add to the wiki if you figure things out or make new distinctions.
239
239
 
240
- https://rpxnow.com/features
240
+ ## Flow
241
+
242
+ - Try to create a session
243
+ - Session logs into provider
244
+ - On success, if no user, redirect to User#create
data/Rakefile CHANGED
@@ -6,11 +6,11 @@ require 'rake/gempackagetask'
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = "authlogic-connect"
8
8
  s.author = "Lance Pollard"
9
- s.version = "0.0.3.9"
10
- s.summary = "Authlogic Connect: Let your app use all of Oauth and OpenID"
9
+ s.version = "0.0.4.03"
10
+ s.summary = "Authlogic Connect: Oauth and OpenID made dead simple"
11
11
  s.homepage = "http://github.com/viatropos/authlogic-connect"
12
12
  s.email = "lancejpollard@gmail.com"
13
- s.description = "Let your app use all of Oauth and OpenID"
13
+ s.description = "Oauth and OpenID made dead simple"
14
14
  s.has_rdoc = true
15
15
  s.rubyforge_project = "authlogic-connect"
16
16
  s.platform = Gem::Platform::RUBY
@@ -68,4 +68,8 @@ Rake::RDocTask.new do |rdoc|
68
68
  rdoc.rdoc_files.add(files)
69
69
  rdoc.main = "README.markdown"
70
70
  rdoc.title = spec.summary
71
+ end
72
+
73
+ task :yank do
74
+ `gem yank #{spec.name} -v #{spec.version}`
71
75
  end
@@ -11,13 +11,13 @@ require "#{this}/open_id_authentication"
11
11
  require "#{library}/ext"
12
12
  require "#{library}/authlogic_connect"
13
13
  require "#{library}/callback_filter"
14
- require "#{library}/token"
14
+ require "#{library}/access_token"
15
15
  require "#{library}/openid"
16
16
  require "#{library}/oauth"
17
17
  require "#{library}/common"
18
18
  require "#{library}/engine" if defined?(Rails) && Rails::VERSION::MAJOR == 3
19
19
 
20
- custom_models = ["#{library}/token"]
20
+ custom_models = ["#{library}/access_token"]
21
21
  custom_models += Dir["#{library}/oauth/tokens"]
22
22
  custom_models += Dir["#{library}/openid/tokens"]
23
23
 
@@ -1,4 +1,4 @@
1
- class Token < ActiveRecord::Base
1
+ class AccessToken < ActiveRecord::Base
2
2
  belongs_to :user
3
3
 
4
4
  def client
File without changes
@@ -1,7 +1,7 @@
1
1
  module AuthlogicConnect::Common
2
2
  module Session
3
3
 
4
- def self.included(base)
4
+ def self.included(base)
5
5
  base.class_eval do
6
6
  include Variables
7
7
  include InstanceMethods
@@ -10,18 +10,21 @@ module AuthlogicConnect::Common
10
10
 
11
11
  module InstanceMethods
12
12
 
13
- # core save method coordinating how to save the session
13
+ # core save method coordinating how to save the session.
14
+ # want to destroy the block if we redirect to a remote service, that's it.
15
+ # otherwise the block contains the render methods we wan to use
14
16
  def save(&block)
15
- block_destroyed = false
16
- if authenticating_with_openid?
17
- block_destroyed = save_with_openid(&block)
18
- elsif authenticating_with_oauth?
19
- block_destroyed = save_with_oauth(&block)
17
+ self.errors.clear
18
+ # log_state
19
+ authenticate_via_protocol(block_given?) do |redirecting|
20
+ block = nil if redirecting
21
+ result = super(&block)
22
+ cleanup_authentication_session unless block.nil?
23
+ result
20
24
  end
21
- block = nil if block_destroyed
22
- super(&block)
23
25
  end
26
+
24
27
  end
25
28
 
26
29
  end
27
- end
30
+ end
@@ -1,16 +1,32 @@
1
1
  # This class holds query/state variables common to oauth and openid
2
2
  module AuthlogicConnect::Common::State
3
3
 
4
- def auth_session?
5
- !auth_session.blank?
4
+ def auth_controller?
5
+ !auth_controller.blank?
6
6
  end
7
-
7
+
8
8
  def auth_params?
9
- !auth_params.blank?
9
+ auth_controller? && !auth_params.blank?
10
+ end
11
+
12
+ def auth_session?
13
+ !auth_session.blank?
10
14
  end
11
15
 
12
16
  def is_auth_session?
13
17
  self.is_a?(Authlogic::Session::Base)
14
18
  end
15
19
 
16
- end
20
+ def start_authentication?
21
+ start_oauth? || start_openid?
22
+ end
23
+
24
+ def validate_password_with_oauth?
25
+ !using_openid? && super
26
+ end
27
+
28
+ def validate_password_with_openid?
29
+ !using_oauth? && super
30
+ end
31
+
32
+ end
@@ -14,18 +14,18 @@ module AuthlogicConnect::Common::User
14
14
 
15
15
  def self.included(base)
16
16
  base.class_eval do
17
- has_many :tokens, :class_name => "Token", :dependent => :destroy
18
- belongs_to :active_token, :class_name => "Token", :dependent => :destroy
19
- accepts_nested_attributes_for :tokens, :active_token
17
+ has_many :access_tokens, :class_name => "AccessToken", :dependent => :destroy
18
+ belongs_to :active_token, :class_name => "AccessToken", :dependent => :destroy
19
+ accepts_nested_attributes_for :access_tokens, :active_token
20
20
  end
21
21
  end
22
22
 
23
23
  def authenticated_with
24
- @authenticated_with ||= self.tokens.collect{|t| t.service_name.to_s}
24
+ @authenticated_with ||= self.access_tokens.collect{|t| t.service_name.to_s}
25
25
  end
26
26
 
27
27
  def authenticated_with?(service)
28
- self.tokens.detect{|t| t.service_name.to_s == service.to_s}
28
+ self.access_tokens.detect{|t| t.service_name.to_s == service.to_s}
29
29
  end
30
30
 
31
31
  def update_attributes(attributes, &block)
@@ -38,7 +38,7 @@ module AuthlogicConnect::Common::User
38
38
  end
39
39
 
40
40
  def get_token(service_name)
41
- self.tokens.detect {|i| i.service_name.to_s == service_name.to_s}
41
+ self.access_tokens.detect {|i| i.service_name.to_s == service_name.to_s}
42
42
  end
43
43
 
44
44
  # core save method coordinating how to save the user.
@@ -46,68 +46,30 @@ module AuthlogicConnect::Common::User
46
46
  # authentication mission we are trying to accomplish.
47
47
  # instead, we just return save as false.
48
48
  # the next time around, when we recieve the callback,
49
- # we will run the validations
49
+ # we will run the validations.
50
+ # when you call 'current_user_session' in ApplicationController,
51
+ # it leads to calling 'save' on this User object via "session.record.save",
52
+ # from the 'persisting?' method. So we don't want any of this to occur
53
+ # when that save is called, and the only way to check currently is
54
+ # to check if there is a block_given?
50
55
  def save(options = {}, &block)
51
- # debug_user_save_pre(options, &block)
56
+ self.errors.clear
57
+ # log_state
52
58
  options = {} if options == false
53
- unless options[:skip_redirect] == true
54
- return false if remotely_authenticating?(&block)
55
- end
56
- # forces you to validate, maybe get rid of if needed,
57
- # but everything depends on this
58
- if ActiveRecord::VERSION::MAJOR < 3
59
- result = super(true) # validate!
60
- else
61
- result = super(options.merge(:validate => true))
62
- end
63
- # debug_user_save_post
64
- yield(result) if block_given? # give back to controller
59
+ options[:validate] = true unless options.has_key?(:validate)
60
+ save_options = ActiveRecord::VERSION::MAJOR < 3 ? options[:validate] : options
65
61
 
66
- cleanup_auth_session if result && !(options.has_key?(:keep_session) && options[:keep_session])
67
-
68
- result
69
- end
70
-
71
- def remotely_authenticating?(&block)
72
- return redirecting_to_oauth_server? if using_oauth? && block_given?
73
- return redirecting_to_openid_server? if using_openid?
74
- return false
75
- end
76
-
77
- # it only reaches this point once it has returned, or you
78
- # have manually skipped the redirect and save was called directly.
79
- def cleanup_auth_session
80
- cleanup_oauth_session
81
- cleanup_openid_session
82
- end
83
-
84
- def validate_password_with_oauth?
85
- !using_openid? && super
86
- end
87
-
88
- def validate_password_with_openid?
89
- !using_oauth? && super
90
- end
91
-
92
- # test methods for dev/debugging, commented out by default
93
- def debug_user_save_pre(options = {}, &block)
94
- puts "USER SAVE "
95
- puts "block_given? #{block_given?.to_s}"
96
- puts "using_oauth? #{using_oauth?.to_s}"
97
- puts "using_openid? #{using_openid?.to_s}"
98
- puts "authenticating_with_oauth? #{authenticating_with_oauth?.to_s}"
99
- puts "authenticating_with_openid? #{authenticating_with_openid?.to_s}"
100
- puts "validate_password_with_oauth? #{validate_password_with_oauth?.to_s}"
101
- puts "validate_password_with_openid? #{validate_password_with_openid?.to_s}"
102
- puts "!using_openid? && require_password? #{(!using_openid? && require_password?).to_s}"
103
- end
104
-
105
- def debug_user_save_post
106
- puts "ERRORS: #{errors.full_messages}"
107
- puts "using_oauth? #{using_oauth?.to_s}"
108
- puts "using_openid? #{using_openid?.to_s}"
109
- puts "validate_password_with_oauth? #{validate_password_with_oauth?.to_s}"
110
- puts "validate_password_with_openid? #{validate_password_with_openid?.to_s}"
62
+ # kill the block if we're starting authentication
63
+ authenticate_via_protocol(block_given?, options) do |redirecting|
64
+ block = nil if redirecting
65
+ # forces you to validate, only if a block is given
66
+ result = super(save_options) # validate!
67
+ unless block.nil?
68
+ cleanup_authentication_session(options)
69
+ yield(result)
70
+ end
71
+ result
72
+ end
111
73
  end
112
74
 
113
75
  end
@@ -1,19 +1,18 @@
1
1
  module AuthlogicConnect::Common::Variables
2
2
  include AuthlogicConnect::Common::State
3
+
4
+ attr_reader :processing_authentication
3
5
 
4
- def auth_controller
5
- is_auth_session? ? controller : session_class.controller
6
+ def auth_class
7
+ is_auth_session? ? self.class : session_class
6
8
  end
7
9
 
8
- def auth_session
9
- auth_controller.session.symbolize_keys!
10
- auth_controller.session.keys.each do |key|
11
- auth_controller.session[key.to_s] = auth_controller.session.delete(key) if key.to_s =~ /^OpenID/
12
- end
13
- auth_controller.session
10
+ def auth_controller
11
+ is_auth_session? ? controller : session_class.controller
14
12
  end
15
13
 
16
14
  def auth_params
15
+ return nil unless auth_controller?
17
16
  auth_controller.params.symbolize_keys!
18
17
  auth_controller.params.keys.each do |key|
19
18
  auth_controller.params[key.to_s] = auth_controller.params.delete(key) if key.to_s =~ /^OpenID/
@@ -21,6 +20,15 @@ module AuthlogicConnect::Common::Variables
21
20
  auth_controller.params
22
21
  end
23
22
 
23
+ def auth_session
24
+ return nil unless auth_controller?
25
+ auth_controller.session.symbolize_keys!
26
+ auth_controller.session.keys.each do |key|
27
+ auth_controller.session[key.to_s] = auth_controller.session.delete(key) if key.to_s =~ /^OpenID/
28
+ end
29
+ auth_controller.session
30
+ end
31
+
24
32
  def auth_callback_url(options = {})
25
33
  auth_controller.url_for({:controller => auth_controller.controller_name, :action => auth_controller.action_name}.merge(options))
26
34
  end
@@ -31,10 +39,11 @@ module AuthlogicConnect::Common::Variables
31
39
  end
32
40
 
33
41
  # auth_params and auth_session attributes are all String!
34
- def from_session_or_params(by)
35
- key = by.is_a?(Symbol) ? by : by.to_sym
42
+ def from_session_or_params(attribute)
43
+ return nil unless auth_controller?
44
+ key = attribute.is_a?(Symbol) ? attribute : attribute.to_sym
36
45
  result = auth_params[key] if (auth_params && auth_params[key])
37
- result = auth_session[key] if result.blank? # might be null here too
46
+ result = auth_session[key] if (result.nil? || result.blank?)
38
47
  result
39
48
  end
40
49
 
@@ -42,6 +51,8 @@ module AuthlogicConnect::Common::Variables
42
51
  # uncertain as to how they are saved. So this makes sure if we are
43
52
  # logging in, it must be saving the session, otherwise the user.
44
53
  def correct_request_class?
54
+ return false unless auth_params?
55
+
45
56
  if is_auth_session?
46
57
  auth_type.to_s == "session"
47
58
  else
@@ -53,6 +64,55 @@ module AuthlogicConnect::Common::Variables
53
64
 
54
65
  end
55
66
 
67
+ def remove_session_key(key)
68
+ keys = key.is_a?(Symbol) ? [key, key.to_s] : [key, key.to_sym]
69
+ keys.each {|k| auth_session.delete(k)}
70
+ end
71
+
72
+ # wraps the call to "save" (in yield).
73
+ # reason being, we need to somehow not allow oauth/openid validations to run
74
+ # when we don't have a block. We can't know that using class methods, so we create
75
+ # this property "processing_authentication", which is used in the validation method.
76
+ # it's value is set to "block_given", which is the value of block_given?
77
+ def authenticate_via_protocol(block_given = false, options = {}, &block)
78
+ @processing_authentication = auth_controller? && block_given
79
+ saved = yield start_authentication?
80
+ @processing_authentication = false
81
+ saved
82
+ end
83
+
84
+ # returns boolean
85
+ def authentication_protocol(with, phase)
86
+ returning(send("#{phase.to_s}_#{with.to_s}?")) do |ready|
87
+ send("#{phase.to_s}_#{with.to_s}") if ready
88
+ end if send("using_#{with.to_s}?")
89
+ end
90
+
91
+ # it only reaches this point once it has returned, or you
92
+ # have manually skipped the redirect and save was called directly.
93
+ def cleanup_authentication_session(options = {}, &block)
94
+ unless (options.has_key?(:keep_session) && options[:keep_session])
95
+ %w(oauth openid).each do |type|
96
+ send("cleanup_#{type.to_s}_session")
97
+ end
98
+ end
99
+ end
100
+
101
+ def log(*methods)
102
+ methods.each do |method|
103
+ puts "#{method.to_s}: #{send(method).inspect}"
104
+ end
105
+ end
106
+
107
+ def log_state
108
+ log(:correct_request_class?)
109
+ log(:using_oauth?, :start_oauth?, :complete_oauth?)
110
+ log(:oauth_request?, :oauth_response?, :stored_oauth_token_and_secret?)
111
+ log(:using_openid?, :start_openid?, :complete_openid?, :openid_request?, :openid_response?)
112
+ log(:authenticating_with_openid?)
113
+ log(:stored_oauth_token_and_secret)
114
+ end
115
+
56
116
  # because we may need to store 6+ session variables, all with pretty lengthy names,
57
117
  # might as well just tinify them.
58
118
  # just an idea
@@ -70,4 +130,8 @@ module AuthlogicConnect::Common::Variables
70
130
  @optimized_session_keys[key]
71
131
  end
72
132
 
133
+ def auto_register?
134
+ true
135
+ end
136
+
73
137
  end
File without changes
@@ -4,15 +4,13 @@ module AuthlogicConnect::Oauth::Process
4
4
 
5
5
  # Step 2: after save is called, it runs this method for validation
6
6
  def validate_by_oauth
7
- validate_email_field = false
8
- unless new_oauth_request? # shouldn't be validating if it's redirecting...
9
- restore_attributes
10
- complete_oauth_transaction
7
+ if processing_authentication
8
+ authentication_protocol(:oauth, :start) || authentication_protocol(:oauth, :complete)
11
9
  end
12
10
  end
13
11
 
14
12
  # Step 3: if new_oauth_request?, redirect to oauth provider
15
- def redirect_to_oauth
13
+ def start_oauth
16
14
  save_oauth_session
17
15
  authorize_url = token_class.authorize_url(auth_callback_url) do |request_token|
18
16
  save_auth_session_token(request_token) # only for oauth version 1
@@ -20,6 +18,17 @@ module AuthlogicConnect::Oauth::Process
20
18
  auth_controller.redirect_to authorize_url
21
19
  end
22
20
 
21
+ # Step 4: on callback, run this method
22
+ def complete_oauth
23
+ # implemented in User and Session Oauth modules
24
+ unless new_oauth_request? # shouldn't be validating if it's redirecting...
25
+ restore_attributes
26
+ complete_oauth_transaction
27
+ return true
28
+ end
29
+ return false
30
+ end
31
+
23
32
  # Step 3a: save our passed-parameters into the session,
24
33
  # so we can retrieve them after the redirect calls back
25
34
  def save_oauth_session
@@ -45,11 +54,6 @@ module AuthlogicConnect::Oauth::Process
45
54
  def restore_attributes
46
55
  end
47
56
 
48
- # Step 4: on callback, run this method
49
- def authenticate_with_oauth
50
- # implemented in User and Session Oauth modules
51
- end
52
-
53
57
  # Step last, after the response
54
58
  # having lots of trouble testing logging and out multiple times,
55
59
  # so there needs to be a solid way to know when a user has messed up loggin in.
@@ -61,8 +65,11 @@ module AuthlogicConnect::Oauth::Process
61
65
  :oauth_provider,
62
66
  :auth_callback_method,
63
67
  :oauth_request_token,
64
- :oauth_request_token_secret
65
- ].each {|key| auth_session.delete(key)}
68
+ :oauth_request_token_secret,
69
+ :_key,
70
+ :_token,
71
+ :_secret,
72
+ ].each {|key| remove_session_key(key)}
66
73
  end
67
74
 
68
75
  end