lsdr-authlogic-connect 0.0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +240 -0
- data/Rakefile +71 -0
- data/init.rb +1 -0
- data/lib/authlogic-connect.rb +27 -0
- data/lib/authlogic_connect/authlogic_connect.rb +46 -0
- data/lib/authlogic_connect/callback_filter.rb +19 -0
- data/lib/authlogic_connect/common.rb +10 -0
- data/lib/authlogic_connect/common/session.rb +27 -0
- data/lib/authlogic_connect/common/state.rb +16 -0
- data/lib/authlogic_connect/common/user.rb +115 -0
- data/lib/authlogic_connect/common/variables.rb +77 -0
- data/lib/authlogic_connect/engine.rb +14 -0
- data/lib/authlogic_connect/ext.rb +56 -0
- data/lib/authlogic_connect/oauth.rb +14 -0
- data/lib/authlogic_connect/oauth/helper.rb +20 -0
- data/lib/authlogic_connect/oauth/process.rb +68 -0
- data/lib/authlogic_connect/oauth/session.rb +58 -0
- data/lib/authlogic_connect/oauth/state.rb +54 -0
- data/lib/authlogic_connect/oauth/tokens/facebook_token.rb +11 -0
- data/lib/authlogic_connect/oauth/tokens/get_satisfaction_token.rb +9 -0
- data/lib/authlogic_connect/oauth/tokens/google_token.rb +41 -0
- data/lib/authlogic_connect/oauth/tokens/linked_in_token.rb +19 -0
- data/lib/authlogic_connect/oauth/tokens/myspace_token.rb +26 -0
- data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +131 -0
- data/lib/authlogic_connect/oauth/tokens/opensocial_token.rb +0 -0
- data/lib/authlogic_connect/oauth/tokens/twitter_token.rb +8 -0
- data/lib/authlogic_connect/oauth/tokens/vimeo_token.rb +18 -0
- data/lib/authlogic_connect/oauth/tokens/yahoo_token.rb +19 -0
- data/lib/authlogic_connect/oauth/user.rb +68 -0
- data/lib/authlogic_connect/oauth/variables.rb +55 -0
- data/lib/authlogic_connect/openid.rb +11 -0
- data/lib/authlogic_connect/openid/process.rb +30 -0
- data/lib/authlogic_connect/openid/session.rb +78 -0
- data/lib/authlogic_connect/openid/state.rb +47 -0
- data/lib/authlogic_connect/openid/tokens/aol_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/blogger_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/flickr_token.rb +0 -0
- data/lib/authlogic_connect/openid/tokens/my_openid_token.rb +3 -0
- data/lib/authlogic_connect/openid/tokens/openid_token.rb +9 -0
- data/lib/authlogic_connect/openid/user.rb +62 -0
- data/lib/authlogic_connect/openid/variables.rb +19 -0
- data/lib/authlogic_connect/token.rb +53 -0
- data/lib/open_id_authentication.rb +128 -0
- data/rails/init.rb +19 -0
- data/test/controllers/test_users_controller.rb +21 -0
- data/test/libs/database.rb +48 -0
- data/test/libs/user.rb +3 -0
- data/test/libs/user_session.rb +2 -0
- data/test/old.rb +53 -0
- data/test/test_authlogic_connect.rb +13 -0
- data/test/test_helper.rb +153 -0
- data/test/test_user.rb +255 -0
- metadata +247 -0
@@ -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,30 @@
|
|
1
|
+
module AuthlogicConnect::Openid::Process
|
2
|
+
|
3
|
+
include AuthlogicConnect::Openid::Variables
|
4
|
+
|
5
|
+
# want to do this after the final save
|
6
|
+
def cleanup_openid_session
|
7
|
+
[:auth_attributes, :authentication_type, :auth_callback_method].each {|key| auth_session.delete(key)}
|
8
|
+
auth_session.each_key do |key|
|
9
|
+
auth_session.delete(key) if key.to_s =~ /^OpenID/
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate_by_openid
|
14
|
+
errors.add(:tokens, "had the following error: #{@openid_error}") if @openid_error
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_openid_session
|
18
|
+
# Tell our rack callback filter what method the current request is using
|
19
|
+
auth_session[:auth_callback_method] = auth_controller.request.method
|
20
|
+
auth_session[:auth_attributes] = attributes_to_save
|
21
|
+
auth_session[:authentication_type] = auth_params[:authentication_type]
|
22
|
+
auth_session[:auth_method] = "openid"
|
23
|
+
end
|
24
|
+
|
25
|
+
def restore_attributes
|
26
|
+
# Restore any attributes which were saved before redirecting to the auth server
|
27
|
+
self.attributes = auth_session[:auth_attributes]
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,78 @@
|
|
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_openid_error
|
17
|
+
validate :validate_by_openid, :if => :authenticating_with_openid?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Hooks into credentials so that you can pass an :openid_identifier key.
|
22
|
+
def credentials=(value)
|
23
|
+
super
|
24
|
+
values = value.is_a?(Array) ? value : [value]
|
25
|
+
hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil
|
26
|
+
self.openid_identifier = hash[:openid_identifier] if !hash.nil? && hash.key?(:openid_identifier)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Cleaers out the block if we are authenticating with OpenID, so that we can redirect without a DoubleRender
|
30
|
+
# error.
|
31
|
+
def save_with_openid(&block)
|
32
|
+
block = nil if Token.find_by_key(openid_identifier.normalize_identifier)
|
33
|
+
return block.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def authenticating_with_openid?
|
38
|
+
attempted_record.nil? && errors.empty? && (!openid_identifier.blank? || (controller.params[:open_id_complete] && controller.params[:for_session]))
|
39
|
+
end
|
40
|
+
|
41
|
+
def auto_register?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_by_openid
|
46
|
+
self.remember_me = auth_params[:remember_me] == "true" if auth_params.key?(:remember_me)
|
47
|
+
token = Token.find_by_key(openid_identifier.normalize_identifier, :include => [:user])
|
48
|
+
self.attempted_record = token.user if token
|
49
|
+
if !attempted_record
|
50
|
+
if auto_register?
|
51
|
+
self.attempted_record = klass.new :openid_identifier => openid_identifier
|
52
|
+
attempted_record.save do |result|
|
53
|
+
if result
|
54
|
+
true
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
else
|
60
|
+
errors.add(:openid_identifier, "did not match any users in our database, have you set up your account to use OpenID?")
|
61
|
+
end
|
62
|
+
return
|
63
|
+
end
|
64
|
+
controller.send(:authenticate_with_open_id, openid_identifier, :return_to => controller.url_for(:for_session => "1", :remember_me => remember_me?)) do |result, openid_identifier|
|
65
|
+
if result.unsuccessful?
|
66
|
+
errors.add_to_base(result.message)
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_openid_error
|
74
|
+
errors.add(:openid_identifier, @openid_error) if @openid_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# all these methods must return true or false
|
2
|
+
module AuthlogicConnect::Openid::State
|
3
|
+
# 1. to call
|
4
|
+
def openid_request?
|
5
|
+
!openid_identifier.blank?
|
6
|
+
end
|
7
|
+
|
8
|
+
def openid_identifier?
|
9
|
+
openid_request?
|
10
|
+
end
|
11
|
+
|
12
|
+
def openid_provider?
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
# 2. from call
|
17
|
+
# better check needed
|
18
|
+
def openid_response?
|
19
|
+
!auth_session[:auth_attributes].nil? && auth_session[:auth_method] == "openid"
|
20
|
+
end
|
21
|
+
alias_method :openid_complete?, :openid_response?
|
22
|
+
|
23
|
+
# 3. either to or from call
|
24
|
+
# this should include more!
|
25
|
+
# we know we are using open id if:
|
26
|
+
# the params passed in have "openid_identifier"
|
27
|
+
def using_openid?
|
28
|
+
openid_request? || openid_response?
|
29
|
+
end
|
30
|
+
|
31
|
+
def authenticating_with_openid?
|
32
|
+
session_class.activated? && using_openid?
|
33
|
+
end
|
34
|
+
|
35
|
+
def allow_openid_redirect?
|
36
|
+
authenticating_with_openid?
|
37
|
+
end
|
38
|
+
|
39
|
+
def redirecting_to_openid_server?
|
40
|
+
allow_openid_redirect? && !authenticate_with_openid
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_password_with_openid?
|
44
|
+
!using_openid? && require_password?
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,62 @@
|
|
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 authenticate_with_openid
|
25
|
+
@openid_error = nil
|
26
|
+
if !openid_response?
|
27
|
+
save_openid_session
|
28
|
+
else
|
29
|
+
restore_attributes
|
30
|
+
end
|
31
|
+
options = {}
|
32
|
+
options[:return_to] = auth_callback_url(:for_model => "1", :action => "create")
|
33
|
+
auth_controller.send(:authenticate_with_open_id, openid_identifier, options) do |result, openid_identifier|
|
34
|
+
create_openid_token(result, openid_identifier)
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_openid_token(result, openid_identifier)
|
41
|
+
if result.unsuccessful?
|
42
|
+
@openid_error = result.message
|
43
|
+
elsif Token.find_by_key(openid_identifier.normalize_identifier)
|
44
|
+
else
|
45
|
+
token = OpenidToken.new(:key => openid_identifier)
|
46
|
+
self.tokens << token
|
47
|
+
self.active_token = token
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def attributes_to_save
|
52
|
+
attr_list = [:id, :password, crypted_password_field, password_salt_field, :persistence_token, :perishable_token, :single_access_token, :login_count,
|
53
|
+
:failed_login_count, :last_request_at, :current_login_at, :last_login_at, :current_login_ip, :last_login_ip, :created_at,
|
54
|
+
:updated_at, :lock_version]
|
55
|
+
attrs_to_save = attributes.clone.delete_if do |k, v|
|
56
|
+
attr_list.include?(k.to_sym)
|
57
|
+
end
|
58
|
+
attrs_to_save.merge!(:password => password, :password_confirmation => password_confirmation)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module AuthlogicConnect::Openid::Variables
|
2
|
+
include AuthlogicConnect::Openid::State
|
3
|
+
|
4
|
+
# openid_provider = "blogger", "myopenid", etc.
|
5
|
+
# openid_identifier = "viatropos.myopenid.com", etc.
|
6
|
+
# openid_key = "viatropos"
|
7
|
+
# def openid_attributes
|
8
|
+
# [:openid_provider, :openid_identifier, :openid_key]
|
9
|
+
# end
|
10
|
+
|
11
|
+
def openid_identifier
|
12
|
+
auth_params[:openid_identifier]
|
13
|
+
end
|
14
|
+
|
15
|
+
def openid_provider
|
16
|
+
from_session_or_params(:openid_provider)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Token < ActiveRecord::Base
|
2
|
+
belongs_to :user
|
3
|
+
|
4
|
+
def client
|
5
|
+
self.class.client
|
6
|
+
end
|
7
|
+
|
8
|
+
def consumer
|
9
|
+
self.class.consumer
|
10
|
+
end
|
11
|
+
|
12
|
+
def service_name
|
13
|
+
self.class.service_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def settings
|
17
|
+
self.class.settings
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(path)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def service_name
|
26
|
+
@service_name ||= self.to_s.underscore.scan(/^(.*?)(_token)?$/)[0][0].to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
def client
|
30
|
+
raise "implement client in subclass"
|
31
|
+
end
|
32
|
+
|
33
|
+
def consumer
|
34
|
+
raise "implement consumer in subclass"
|
35
|
+
end
|
36
|
+
|
37
|
+
def settings(site, hash = {})
|
38
|
+
@settings = hash.merge(:site => site)
|
39
|
+
end
|
40
|
+
|
41
|
+
def config
|
42
|
+
@settings ||= {}
|
43
|
+
@settings.dup
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def credentials
|
49
|
+
@credentials ||= AuthlogicConnect.credentials(service_name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# copied from open_id_authentication plugin on github
|
2
|
+
require 'uri'
|
3
|
+
require 'openid'
|
4
|
+
require 'rack/openid'
|
5
|
+
|
6
|
+
module OpenIdAuthentication
|
7
|
+
def self.new(app)
|
8
|
+
store = OpenIdAuthentication.store
|
9
|
+
if store.nil?
|
10
|
+
Rails.logger.warn "OpenIdAuthentication.store is nil. Using in-memory store."
|
11
|
+
end
|
12
|
+
|
13
|
+
::Rack::OpenID.new(app, OpenIdAuthentication.store)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.store
|
17
|
+
@@store
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.store=(*store_option)
|
21
|
+
store, *parameters = *([ store_option ].flatten)
|
22
|
+
|
23
|
+
@@store = case store
|
24
|
+
when :memory
|
25
|
+
require 'openid/store/memory'
|
26
|
+
OpenID::Store::Memory.new
|
27
|
+
when :file
|
28
|
+
require 'openid/store/filesystem'
|
29
|
+
OpenID::Store::Filesystem.new(Rails.root.join('tmp/openids'))
|
30
|
+
when :memcache
|
31
|
+
require 'memcache'
|
32
|
+
require 'openid/store/memcache'
|
33
|
+
OpenID::Store::Memcache.new(MemCache.new(parameters))
|
34
|
+
else
|
35
|
+
store
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
self.store = nil
|
40
|
+
|
41
|
+
class Result
|
42
|
+
ERROR_MESSAGES = {
|
43
|
+
:missing => "Sorry, the OpenID server couldn't be found",
|
44
|
+
:invalid => "Sorry, but this does not appear to be a valid OpenID",
|
45
|
+
:canceled => "OpenID verification was canceled",
|
46
|
+
:failed => "OpenID verification failed",
|
47
|
+
:setup_needed => "OpenID verification needs setup"
|
48
|
+
}
|
49
|
+
|
50
|
+
def self.[](code)
|
51
|
+
new(code)
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(code)
|
55
|
+
@code = code
|
56
|
+
end
|
57
|
+
|
58
|
+
def status
|
59
|
+
@code
|
60
|
+
end
|
61
|
+
|
62
|
+
ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
|
63
|
+
|
64
|
+
def successful?
|
65
|
+
@code == :successful
|
66
|
+
end
|
67
|
+
|
68
|
+
def unsuccessful?
|
69
|
+
ERROR_MESSAGES.keys.include?(@code)
|
70
|
+
end
|
71
|
+
|
72
|
+
def message
|
73
|
+
ERROR_MESSAGES[@code]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
# The parameter name of "openid_identifier" is used rather than
|
79
|
+
# the Rails convention "open_id_identifier" because that's what
|
80
|
+
# the specification dictates in order to get browser auto-complete
|
81
|
+
# working across sites
|
82
|
+
def using_open_id?(identifier = nil) #:doc:
|
83
|
+
identifier ||= open_id_identifier
|
84
|
+
!identifier.blank? || request.env[Rack::OpenID::RESPONSE]
|
85
|
+
end
|
86
|
+
|
87
|
+
def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc:
|
88
|
+
identifier ||= open_id_identifier
|
89
|
+
if request.env[Rack::OpenID::RESPONSE]
|
90
|
+
complete_open_id_authentication(&block)
|
91
|
+
else
|
92
|
+
begin_open_id_authentication(identifier, options, &block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def open_id_identifier
|
98
|
+
params[:openid_identifier] || params[:openid_url]
|
99
|
+
end
|
100
|
+
|
101
|
+
def begin_open_id_authentication(identifier, options = {})
|
102
|
+
options[:identifier] = identifier
|
103
|
+
value = Rack::OpenID.build_header(options)
|
104
|
+
response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value
|
105
|
+
head :unauthorized
|
106
|
+
end
|
107
|
+
|
108
|
+
def complete_open_id_authentication
|
109
|
+
response = request.env[Rack::OpenID::RESPONSE]
|
110
|
+
identifier = response.display_identifier
|
111
|
+
|
112
|
+
case response.status
|
113
|
+
when OpenID::Consumer::SUCCESS
|
114
|
+
yield Result[:successful], identifier,
|
115
|
+
OpenID::SReg::Response.from_success_response(response)
|
116
|
+
when :missing
|
117
|
+
yield Result[:missing], identifier, nil
|
118
|
+
when :invalid
|
119
|
+
yield Result[:invalid], identifier, nil
|
120
|
+
when OpenID::Consumer::CANCEL
|
121
|
+
yield Result[:canceled], identifier, nil
|
122
|
+
when OpenID::Consumer::FAILURE
|
123
|
+
yield Result[:failed], identifier, nil
|
124
|
+
when OpenID::Consumer::SETUP_NEEDED
|
125
|
+
yield Result[:setup_needed], response.setup_url, nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|