anideo-authlogic-connect 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +234 -0
  3. data/Rakefile +85 -0
  4. data/init.rb +1 -0
  5. data/lib/authlogic-connect.rb +39 -0
  6. data/lib/authlogic_connect/access_token.rb +61 -0
  7. data/lib/authlogic_connect/authlogic_connect.rb +46 -0
  8. data/lib/authlogic_connect/callback_filter.rb +19 -0
  9. data/lib/authlogic_connect/common.rb +10 -0
  10. data/lib/authlogic_connect/common/session.rb +30 -0
  11. data/lib/authlogic_connect/common/state.rb +45 -0
  12. data/lib/authlogic_connect/common/user.rb +77 -0
  13. data/lib/authlogic_connect/common/variables.rb +124 -0
  14. data/lib/authlogic_connect/engine.rb +14 -0
  15. data/lib/authlogic_connect/ext.rb +56 -0
  16. data/lib/authlogic_connect/oauth.rb +14 -0
  17. data/lib/authlogic_connect/oauth/helper.rb +20 -0
  18. data/lib/authlogic_connect/oauth/process.rb +75 -0
  19. data/lib/authlogic_connect/oauth/session.rb +62 -0
  20. data/lib/authlogic_connect/oauth/state.rb +60 -0
  21. data/lib/authlogic_connect/oauth/tokens/aol_token.rb +2 -0
  22. data/lib/authlogic_connect/oauth/tokens/facebook_token.rb +11 -0
  23. data/lib/authlogic_connect/oauth/tokens/foursquare_token.rb +15 -0
  24. data/lib/authlogic_connect/oauth/tokens/get_satisfaction_token.rb +9 -0
  25. data/lib/authlogic_connect/oauth/tokens/github_token.rb +14 -0
  26. data/lib/authlogic_connect/oauth/tokens/google_token.rb +41 -0
  27. data/lib/authlogic_connect/oauth/tokens/linked_in_token.rb +19 -0
  28. data/lib/authlogic_connect/oauth/tokens/meetup_token.rb +12 -0
  29. data/lib/authlogic_connect/oauth/tokens/myspace_token.rb +26 -0
  30. data/lib/authlogic_connect/oauth/tokens/netflix_token.rb +10 -0
  31. data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +164 -0
  32. data/lib/authlogic_connect/oauth/tokens/ohloh_token.rb +9 -0
  33. data/lib/authlogic_connect/oauth/tokens/opensocial_token.rb +0 -0
  34. data/lib/authlogic_connect/oauth/tokens/twitter_token.rb +8 -0
  35. data/lib/authlogic_connect/oauth/tokens/vimeo_token.rb +18 -0
  36. data/lib/authlogic_connect/oauth/tokens/yahoo_token.rb +19 -0
  37. data/lib/authlogic_connect/oauth/user.rb +64 -0
  38. data/lib/authlogic_connect/oauth/variables.rb +64 -0
  39. data/lib/authlogic_connect/openid.rb +11 -0
  40. data/lib/authlogic_connect/openid/process.rb +74 -0
  41. data/lib/authlogic_connect/openid/session.rb +56 -0
  42. data/lib/authlogic_connect/openid/state.rb +48 -0
  43. data/lib/authlogic_connect/openid/tokens/aol_token.rb +0 -0
  44. data/lib/authlogic_connect/openid/tokens/blogger_token.rb +0 -0
  45. data/lib/authlogic_connect/openid/tokens/flickr_token.rb +0 -0
  46. data/lib/authlogic_connect/openid/tokens/my_openid_token.rb +3 -0
  47. data/lib/authlogic_connect/openid/tokens/openid_token.rb +9 -0
  48. data/lib/authlogic_connect/openid/user.rb +38 -0
  49. data/lib/authlogic_connect/openid/variables.rb +19 -0
  50. data/lib/authlogic_connect/rack_state.rb +19 -0
  51. data/lib/open_id_authentication.rb +127 -0
  52. data/rails/init.rb +19 -0
  53. data/test/controllers/test_users_controller.rb +21 -0
  54. data/test/libs/database.rb +47 -0
  55. data/test/libs/user.rb +7 -0
  56. data/test/libs/user_session.rb +2 -0
  57. data/test/test_helper.rb +178 -0
  58. data/test/test_oauth.rb +178 -0
  59. data/test/test_openid.rb +71 -0
  60. data/test/test_user.rb +85 -0
  61. metadata +232 -0
@@ -0,0 +1,9 @@
1
+ # https://www.ohloh.net/
2
+ # http://www.ohloh.net/api/oauth
3
+ class OhlohToken < OauthToken
4
+
5
+ key :user_id
6
+
7
+ settings "http://www.ohloh.net"
8
+
9
+ end
@@ -0,0 +1,8 @@
1
+ class TwitterToken < OauthToken
2
+
3
+ key :user_id
4
+
5
+ settings "http://api.twitter.com",
6
+ :authorize_url => "http://api.twitter.com/oauth/authenticate"
7
+
8
+ end
@@ -0,0 +1,18 @@
1
+ # http://www.vimeo.com/api/docs/oauth
2
+ # http://www.vimeo.com/api/applications/new
3
+ # http://vimeo.com/api/applications
4
+ class VimeoToken < OauthToken
5
+
6
+ key do |access_token|
7
+ body = JSON.parse(access_token.get("http://vimeo.com/api/v2/#{access_token.token}/info.json"))
8
+ user_id = body.first["id"]
9
+ end
10
+
11
+ settings "http://vimeo.com",
12
+ :request_token_path => "/oauth/request_token",
13
+ :authorize_path => "/oauth/authorize",
14
+ :access_token_path => "/oauth/access_token",
15
+ :http_method => "get",
16
+ :scheme => :query_string
17
+
18
+ end
@@ -0,0 +1,19 @@
1
+ # https://developer.apps.yahoo.com/dashboard/createKey.html
2
+ # https://developer.apps.yahoo.com/projects
3
+ # http://developer.yahoo.com/oauth/guide/oauth-accesstoken.html
4
+ # http://developer.yahoo.com/oauth/guide/oauth-auth-flow.html
5
+ # http://code.google.com/apis/gadgets/docs/oauth.html
6
+ # http://developer.yahoo.com/social/rest_api_guide/web-services-guids.html
7
+ # A GUID identifies a person
8
+ # http://social.yahooapis.com/v1/me/guid
9
+ class YahooToken < OauthToken
10
+
11
+ # http://social.yahooapis.com/v1/me/guid
12
+ key :xoauth_yahoo_guid
13
+
14
+ settings "https://api.login.yahoo.com",
15
+ :request_token_path => '/oauth/v2/get_request_token',
16
+ :access_token_path => '/oauth/v2/get_token',
17
+ :authorize_path => '/oauth/v2/request_auth'
18
+
19
+ end
@@ -0,0 +1,64 @@
1
+ module AuthlogicConnect::Oauth::User
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+ # add_acts_as_authentic_module makes sure it is
6
+ # only added to the user model, not all activerecord models.
7
+ add_acts_as_authentic_module(InstanceMethods, :prepend)
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ include AuthlogicConnect::Oauth::Process
13
+
14
+ # Set up some simple validations
15
+ def self.included(base)
16
+ base.class_eval do
17
+
18
+ validate :validate_by_oauth, :if => :authenticating_with_oauth?
19
+
20
+ # need these validation options if you don't want it to choke
21
+ # on password length, which you don't need if you're using oauth
22
+ validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_oauth?)
23
+ validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_oauth?)
24
+ validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:if => :validate_password_with_oauth?)
25
+ validates_length_of_login_field_options validates_length_of_login_field_options.merge(:if => :validate_password_with_oauth?)
26
+ validates_format_of_login_field_options validates_format_of_login_field_options.merge(:if => :validate_password_with_oauth?)
27
+
28
+ end
29
+ end
30
+
31
+ # user adds a few extra things to this method from Process
32
+ # modules work like inheritance
33
+ def save_oauth_session
34
+ super
35
+ auth_session[:auth_attributes] = attributes.reject!{|k, v| v.blank? || !self.respond_to?(k)} unless is_auth_session?
36
+ end
37
+
38
+ def redirect_to_oauth
39
+ return has_token?(oauth_provider) ? false : super
40
+ end
41
+
42
+ def restore_attributes
43
+ # Restore any attributes which were saved before redirecting to the auth server
44
+ self.attributes = auth_session[:auth_attributes]
45
+ end
46
+
47
+ # single implementation method for oauth.
48
+ # this is called after we get the callback url and we are saving the user
49
+ # to the database.
50
+ # it is called by the validation chain.
51
+ def complete_oauth_transaction
52
+ token = token_class.new(oauth_token_and_secret)
53
+ old_token = token_class.find_by_key_or_token(token.key, token.token)
54
+ token = old_token if old_token
55
+
56
+ if has_token?(oauth_provider)
57
+ self.errors.add(:tokens, "you have already created an account using your #{token_class.service_name} account, so it")
58
+ else
59
+ self.access_tokens << token
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,64 @@
1
+ module AuthlogicConnect::Oauth::Variables
2
+ include AuthlogicConnect::Oauth::State
3
+
4
+ # this doesn't do anything yet, just to show what variables
5
+ # we need from the form
6
+ def oauth_variables
7
+ [:oauth_provider]
8
+ end
9
+
10
+ # this comes straight from either the params or session.
11
+ # it is required for most of the other accessors in here
12
+ def oauth_provider
13
+ from_session_or_params(:oauth_provider)
14
+ end
15
+
16
+ # next is "token_class", which is found from the oauth_provider key.
17
+ # it is the OauthToken subclass, such as TwitterToken, which we
18
+ # use as the api for accessing oauth and saving the response to the database for a user.
19
+ def token_class
20
+ AuthlogicConnect.token(oauth_provider) unless oauth_provider.blank?
21
+ end
22
+
23
+ # This should go...
24
+ def oauth_response
25
+ auth_params && oauth_token
26
+ end
27
+
28
+ # the token from the response parameters
29
+ def oauth_token
30
+ return nil unless token_class
31
+ oauth_version == 1.0 ? auth_params[:oauth_token] : auth_params[:code]
32
+ end
33
+
34
+ # the version of oauth we're using. Accessed from the OauthToken subclass
35
+ def oauth_version
36
+ token_class.oauth_version
37
+ end
38
+
39
+ # the Oauth gem consumer, whereby we can make requests to the server
40
+ def oauth_consumer
41
+ token_class.consumer
42
+ end
43
+
44
+ def stored_oauth_token_and_secret
45
+ if auth_controller?
46
+ {:key => auth_params[:_key], :token => auth_params[:_token], :secret => auth_params[:_secret]}
47
+ else
48
+ {:key => nil, :token => nil, :secret => nil}
49
+ end
50
+ end
51
+
52
+ # this is a thick method.
53
+ # it gives you the final key and secret that we will store in the database
54
+ def oauth_token_and_secret
55
+ return stored_oauth_token_and_secret if stored_oauth_token_and_secret?
56
+ token_class.get_token_and_secret(
57
+ :token => auth_session[:oauth_request_token],
58
+ :secret => oauth_version == 1.0 ? auth_session[:oauth_request_token_secret] : oauth_token,
59
+ :oauth_verifier => auth_params[:oauth_verifier],
60
+ :redirect_uri => auth_callback_url
61
+ )
62
+ end
63
+
64
+ end
@@ -0,0 +1,11 @@
1
+ module AuthlogicConnect::Openid
2
+ end
3
+
4
+ require File.dirname(__FILE__) + "/openid/state"
5
+ require File.dirname(__FILE__) + "/openid/variables"
6
+ require File.dirname(__FILE__) + "/openid/process"
7
+ require File.dirname(__FILE__) + "/openid/user"
8
+ require File.dirname(__FILE__) + "/openid/session"
9
+
10
+ ActiveRecord::Base.send(:include, AuthlogicConnect::Openid::User)
11
+ Authlogic::Session::Base.send(:include, AuthlogicConnect::Openid::Session)
@@ -0,0 +1,74 @@
1
+ module AuthlogicConnect::Openid::Process
2
+
3
+ include AuthlogicConnect::Openid::Variables
4
+
5
+ def start_openid
6
+ save_openid_session
7
+ call_openid
8
+ end
9
+
10
+ def complete_openid
11
+ restore_attributes
12
+ call_openid
13
+ end
14
+
15
+ def call_openid
16
+ options = {}
17
+ options[:return_to] = auth_callback_url
18
+ # this is called both on start and complete.
19
+ # reason being, in the open_id_authentication library (where "authenticate_with_open_id" is defined),
20
+ # it checks the rack session to find openid pareters, and knows whether we're at
21
+ # start or complete
22
+ auth_controller.send(:authenticate_with_open_id, openid_identifier, options) do |result, openid_identifier|
23
+ complete_openid_transaction(result, openid_identifier)
24
+ return true
25
+ end
26
+ return false
27
+ end
28
+
29
+ def complete_openid_transaction(result, openid_identifier)
30
+ if result.unsuccessful?
31
+ errors.add_to_base(result.message)
32
+ end
33
+
34
+ if AccessToken.find_by_key(openid_identifier.normalize_identifier)
35
+ else
36
+ token = OpenidToken.new(:key => openid_identifier)
37
+ self.access_tokens << token
38
+ self.active_token = token
39
+ end
40
+ end
41
+
42
+ # want to do this after the final save
43
+ def cleanup_openid_session
44
+ [:auth_attributes, :authentication_type, :auth_callback_method].each {|key| remove_session_key(key)}
45
+ auth_session.each_key do |key|
46
+ remove_session_key(key) if key.to_s =~ /^OpenID/
47
+ end
48
+ end
49
+
50
+ def validate_by_openid
51
+ if processing_authentication
52
+ authentication_protocol(:openid, :start) || authentication_protocol(:openid, :complete)
53
+ errors.add(:access_tokens, "had the following error: #{@openid_error}") if @openid_error
54
+ end
55
+ end
56
+
57
+ def save_openid_session
58
+ # Tell our rack callback filter what method the current request is using
59
+ auth_session[:auth_callback_method] = auth_controller.request.method
60
+ auth_session[:auth_attributes] = attributes_to_save
61
+ auth_session[:authentication_type] = auth_params[:authentication_type]
62
+ auth_session[:auth_method] = "openid"
63
+ end
64
+
65
+ def attributes_to_save
66
+ {}
67
+ end
68
+
69
+ def restore_attributes
70
+ # Restore any attributes which were saved before redirecting to the auth server
71
+ self.attributes = auth_session[:auth_attributes] unless is_auth_session?
72
+ end
73
+
74
+ end
@@ -0,0 +1,56 @@
1
+ module AuthlogicConnect::Openid
2
+ # This module is responsible for adding all of the OpenID goodness to the Authlogic::Session::Base class.
3
+ module Session
4
+ # Add a simple openid_identifier attribute and some validations for the field.
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ include InstanceMethods
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ include AuthlogicConnect::Openid::Process
13
+
14
+ def self.included(klass)
15
+ klass.class_eval do
16
+ validate :validate_by_openid, :if => :authenticating_with_openid?
17
+ end
18
+ end
19
+
20
+ # Hooks into credentials so that you can pass an :openid_identifier key.
21
+ def credentials=(value)
22
+ super
23
+ values = value.is_a?(Array) ? value : [value]
24
+ hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil
25
+ end
26
+
27
+ private
28
+
29
+ def auto_register?
30
+ false
31
+ end
32
+
33
+ def complete_openid_transaction(result, openid_identifier)
34
+ if result.unsuccessful?
35
+ errors.add_to_base(result.message)
36
+ end
37
+
38
+ token = AccessToken.find_by_key(openid_identifier.normalize_identifier, :include => [:user])
39
+
40
+ self.attempted_record = token.user if token
41
+
42
+ if !attempted_record
43
+ if auto_register?
44
+ self.attempted_record = klass.new
45
+ self.attempted_record.access_tokens << OpenidToken.new(:key => openid_identifier.normalize_identifier)
46
+ self.attempted_record.save
47
+ else
48
+ auth_session[:openid_identifier] = openid_identifier
49
+ errors.add(:user, "Could not find user in our database, have you registered with your openid account?")
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ # all these methods must return true or false
2
+ module AuthlogicConnect::Openid::State
3
+
4
+ # 1. to call
5
+ def openid_request?
6
+ !openid_identifier.blank? && auth_session[:auth_attributes].nil?
7
+ end
8
+
9
+ def openid_identifier?
10
+ openid_request?
11
+ end
12
+
13
+ def openid_provider?
14
+
15
+ end
16
+
17
+ # 2. from call
18
+ # better check needed
19
+ def openid_response?
20
+ auth_controller? && !auth_session[:auth_attributes].nil? && auth_session[:auth_method] == "openid"
21
+ end
22
+ alias_method :openid_complete?, :openid_response?
23
+
24
+ # 3. either to or from call
25
+ # this should include more!
26
+ # we know we are using open id if:
27
+ # the params passed in have "openid_identifier"
28
+ def using_openid?
29
+ auth_controller? && (openid_request? || openid_response?)
30
+ end
31
+
32
+ def authenticating_with_openid?
33
+ auth_controller? && auth_class.activated? && using_openid?
34
+ end
35
+
36
+ def start_openid?
37
+ authenticating_with_openid? && !openid_response?
38
+ end
39
+
40
+ def complete_openid?
41
+ openid_complete?
42
+ end
43
+
44
+ def validate_password_with_openid?
45
+ !using_openid? && require_password?
46
+ end
47
+
48
+ end
@@ -0,0 +1,3 @@
1
+ class MyOpenidToken < OpenidToken
2
+
3
+ end
@@ -0,0 +1,9 @@
1
+ class OpenidToken < AccessToken
2
+
3
+ before_save :format_identifier
4
+
5
+ def format_identifier
6
+ self.key = self.key.to_s.normalize_identifier unless self.key.blank?
7
+ end
8
+
9
+ end
@@ -0,0 +1,38 @@
1
+ module AuthlogicConnect::Openid
2
+ module User
3
+ def self.included(base)
4
+ base.class_eval do
5
+ add_acts_as_authentic_module(AuthlogicConnect::Openid::Process, :prepend)
6
+ add_acts_as_authentic_module(InstanceMethods, :append)
7
+ end
8
+ end
9
+
10
+ module InstanceMethods
11
+
12
+ def self.included(base)
13
+ base.class_eval do
14
+ validate :validate_by_openid, :if => :authenticating_with_openid?
15
+
16
+ validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_openid?)
17
+ validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_openid?)
18
+ validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:if => :validate_password_with_openid?)
19
+ validates_length_of_login_field_options validates_length_of_login_field_options.merge(:if => :validate_password_with_openid?)
20
+ validates_format_of_login_field_options validates_format_of_login_field_options.merge(:if => :validate_password_with_openid?)
21
+ end
22
+ end
23
+
24
+ def attributes_to_save
25
+ attr_list = [:id, :password, crypted_password_field, password_salt_field, :persistence_token, :perishable_token, :single_access_token, :login_count,
26
+ :failed_login_count, :last_request_at, :current_login_at, :last_login_at, :current_login_ip, :last_login_ip, :created_at,
27
+ :updated_at, :lock_version]
28
+ attrs_to_save = attributes.clone.delete_if do |k, v|
29
+ attr_list.include?(k.to_sym)
30
+ end
31
+ if self.respond_to?(:password) && self.respond_to?(:password_confirmation)
32
+ attrs_to_save.merge!(:password => password, :password_confirmation => password_confirmation)
33
+ end
34
+ attrs_to_save.reject!{|k, v| v.blank? || !self.respond_to?(k)}
35
+ end
36
+ end
37
+ end
38
+ end