authpwn_rails 0.8.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/authpwn_rails.gemspec +6 -4
- data/lib/authpwn_rails/facebook_session.rb +33 -0
- data/lib/authpwn_rails/facebook_token_model.rb +66 -0
- data/lib/authpwn_rails/generators/templates/facebook_token.rb +1 -1
- data/lib/authpwn_rails/generators/templates/session_controller.rb +1 -1
- data/lib/authpwn_rails/generators/templates/user.rb +1 -1
- data/lib/authpwn_rails/session.rb +10 -117
- data/lib/authpwn_rails/session_controller.rb +102 -0
- data/lib/authpwn_rails/user_model.rb +83 -99
- data/lib/authpwn_rails.rb +3 -1
- data/test/cookie_controller_test.rb +2 -1
- metadata +27 -25
- data/lib/authpwn_rails/facebook_extensions.rb +0 -121
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/authpwn_rails.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{authpwn_rails}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.9.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = [%q{Victor Costan}]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-05}
|
13
13
|
s.description = %q{Works with Facebook.}
|
14
14
|
s.email = %q{victor@costan.us}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -29,7 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
"authpwn_rails.gemspec",
|
30
30
|
"lib/authpwn_rails.rb",
|
31
31
|
"lib/authpwn_rails/engine.rb",
|
32
|
-
"lib/authpwn_rails/
|
32
|
+
"lib/authpwn_rails/facebook_session.rb",
|
33
|
+
"lib/authpwn_rails/facebook_token_model.rb",
|
33
34
|
"lib/authpwn_rails/generators/facebook_generator.rb",
|
34
35
|
"lib/authpwn_rails/generators/session_generator.rb",
|
35
36
|
"lib/authpwn_rails/generators/templates/001_create_users.rb",
|
@@ -46,6 +47,7 @@ Gem::Specification.new do |s|
|
|
46
47
|
"lib/authpwn_rails/generators/templates/users.yml",
|
47
48
|
"lib/authpwn_rails/generators/users_generator.rb",
|
48
49
|
"lib/authpwn_rails/session.rb",
|
50
|
+
"lib/authpwn_rails/session_controller.rb",
|
49
51
|
"lib/authpwn_rails/user_model.rb",
|
50
52
|
"test/cookie_controller_test.rb",
|
51
53
|
"test/facebook_controller_test.rb",
|
@@ -62,7 +64,7 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.homepage = %q{http://github.com/pwnall/authpwn_rails}
|
63
65
|
s.licenses = [%q{MIT}]
|
64
66
|
s.require_paths = [%q{lib}]
|
65
|
-
s.rubygems_version = %q{1.8.
|
67
|
+
s.rubygems_version = %q{1.8.5}
|
66
68
|
s.summary = %q{User authentication for Rails 3 applications.}
|
67
69
|
|
68
70
|
if s.respond_to? :specification_version then
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
|
3
|
+
# :nodoc: add authenticates_using_facebook
|
4
|
+
class ActionController::Base
|
5
|
+
# Authenticates users via Facebook OAuth2, using fbgraph_rails.
|
6
|
+
#
|
7
|
+
# The User model class must implement for_facebook_token. The controller
|
8
|
+
# should obtain the Facebook token, using probes_facebook_access_token or
|
9
|
+
# requires_facebook_access_token.
|
10
|
+
def self.authenticates_using_facebook(options = {})
|
11
|
+
include AuthpwnRails::FacebookControllerInstanceMethods
|
12
|
+
before_filter :authenticate_using_facebook_access_token, options
|
13
|
+
end
|
14
|
+
end # module AuthpwnRails::FacebookExtensions::ControllerClassMethods
|
15
|
+
|
16
|
+
# :nodoc: namespace
|
17
|
+
module AuthpwnRails
|
18
|
+
|
19
|
+
# Included in controllers that call authenticates_using_facebook.
|
20
|
+
module FacebookControllerInstanceMethods
|
21
|
+
def authenticate_using_facebook_access_token
|
22
|
+
return true if current_user
|
23
|
+
if access_token = current_facebook_access_token
|
24
|
+
self.current_user = User.for_facebook_token access_token
|
25
|
+
# NOTE: nixing the token from the session so the user won't be logged on
|
26
|
+
# immediately after logging off
|
27
|
+
self.current_facebook_access_token = nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
private :authenticate_using_facebook_access_token
|
31
|
+
end # module AuthpwnRails::FacebookControllerInstanceMethods
|
32
|
+
|
33
|
+
end # namespace AuthpwnRails
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module AuthpwnRails
|
5
|
+
|
6
|
+
# Included by the model class that represents facebook tokens.
|
7
|
+
#
|
8
|
+
# Right now, some parts of the codebase assume the model will be named
|
9
|
+
# FacebookToken.
|
10
|
+
module FacebookTokenModel
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
# The user whose token this is.
|
15
|
+
belongs_to :user, :inverse_of => :facebook_token
|
16
|
+
validates :user, :presence => true
|
17
|
+
|
18
|
+
# A unique ID on the Facebook site for the user owning this token.
|
19
|
+
validates :external_uid, :length => 1..32, :presence => true
|
20
|
+
|
21
|
+
# The OAuth2 access token.
|
22
|
+
validates :access_token, :length => 1..128, :presence => true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Included in the metaclass of models that call pwnauth_facebook_token_model.
|
26
|
+
module ClassMethods
|
27
|
+
# Finds or creates the model containing a token.
|
28
|
+
#
|
29
|
+
# If a model for the same user exists, the model is updated with the given
|
30
|
+
# token. Otherwise, a new model will be created, together with a user.
|
31
|
+
def for(access_token)
|
32
|
+
uid = uid_from_token access_token
|
33
|
+
token = self.where(:external_uid => uid.to_str).first
|
34
|
+
if token
|
35
|
+
token.access_token = access_token
|
36
|
+
else
|
37
|
+
token = FacebookToken.new :external_uid => uid,
|
38
|
+
:access_token => access_token
|
39
|
+
token.user = User.create_with_facebook_token token
|
40
|
+
end
|
41
|
+
token.save!
|
42
|
+
token
|
43
|
+
end
|
44
|
+
|
45
|
+
# Extracts the Facebook user ID from a OAuth2 token.
|
46
|
+
#
|
47
|
+
# This is a hack. It works based on the current format, but might break at
|
48
|
+
# any time. Hopefully, we'll eventually have an official way of pulling the
|
49
|
+
# UID out of an OAuth2 token.
|
50
|
+
def uid_from_token(access_token)
|
51
|
+
access_token.split('|')[1].split('-').last
|
52
|
+
end
|
53
|
+
end # module AuthpwnRails::FacebookTokenModel::ClassMethods
|
54
|
+
|
55
|
+
|
56
|
+
# Included in models that include AuthpwnRails::FacebookTokenModel.
|
57
|
+
module InstanceMethods
|
58
|
+
# FBGraph client loaded with this access token.
|
59
|
+
def facebook_client
|
60
|
+
@client ||= FBGraphRails.fbclient(access_token)
|
61
|
+
end
|
62
|
+
end # module AuthpwnRails::FacebookTokenModel::InstanceMethods
|
63
|
+
|
64
|
+
end # namespace AuthpwnRails::FacebookTokenModel
|
65
|
+
|
66
|
+
end # namespace AuthpwnRails
|
@@ -1,40 +1,21 @@
|
|
1
1
|
require 'action_controller'
|
2
2
|
|
3
|
-
# :nodoc:
|
4
|
-
|
5
|
-
|
6
|
-
# :nodoc: namespace
|
7
|
-
module Session
|
8
|
-
|
9
|
-
# Mixed into ActiveController::Base
|
10
|
-
module ControllerMixin
|
11
|
-
def self.included(base)
|
12
|
-
base.send :extend, ControllerClassMethods
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Methods here become ActiveController::Base class methods.
|
17
|
-
module ControllerClassMethods
|
3
|
+
# :nodoc: adds authenticates_using_session
|
4
|
+
class ActionController::Base
|
18
5
|
# Keeps track of the currently authenticated user via the session.
|
19
6
|
#
|
20
7
|
# Assumes the existence of a User model. A bare ActiveModel model will do the
|
21
8
|
# trick. Model instances must implement id, and the model class must implement
|
22
9
|
# find_by_id.
|
23
|
-
def authenticates_using_session(options = {})
|
24
|
-
include ControllerInstanceMethods
|
10
|
+
def self.authenticates_using_session(options = {})
|
11
|
+
include AuthpwnRails::ControllerInstanceMethods
|
25
12
|
before_filter :authenticate_using_session, options
|
26
|
-
end
|
27
|
-
|
28
|
-
# Turns the current controller into the session processing controller.
|
29
|
-
#
|
30
|
-
# Right now, this should be called from SessionController. The controller name
|
31
|
-
# is hardwired in other parts of the implementation.
|
32
|
-
def authpwn_session_controller
|
33
|
-
include SessionControllerInstanceMethods
|
34
|
-
authenticates_using_session
|
35
|
-
end
|
13
|
+
end
|
36
14
|
end
|
37
15
|
|
16
|
+
# :nodoc: namespace
|
17
|
+
module AuthpwnRails
|
18
|
+
|
38
19
|
# Included in controllers that call authenticates_using_session.
|
39
20
|
module ControllerInstanceMethods
|
40
21
|
attr_reader :current_user
|
@@ -82,93 +63,9 @@ module ControllerInstanceMethods
|
|
82
63
|
end
|
83
64
|
end
|
84
65
|
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Included in controllers that call authpwn_session_controller.
|
88
|
-
module SessionControllerInstanceMethods
|
89
|
-
# GET /session/new
|
90
|
-
def new
|
91
|
-
@user = User.new
|
92
|
-
@redirect_url = flash[:auth_redirect_url]
|
93
|
-
redirect_to session_url if current_user
|
94
|
-
end
|
95
|
-
|
96
|
-
# GET /session
|
97
|
-
def show
|
98
|
-
@user = current_user || User.new
|
99
|
-
if @user.new_record?
|
100
|
-
welcome
|
101
|
-
unless performed?
|
102
|
-
respond_to do |format|
|
103
|
-
format.html { render :action => :welcome }
|
104
|
-
format.json { render :json => {} }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
else
|
108
|
-
home
|
109
|
-
unless performed?
|
110
|
-
respond_to do |format|
|
111
|
-
format.html { render :action => :home }
|
112
|
-
format.json do
|
113
|
-
user_data = @user.as_json
|
114
|
-
user_data = user_data['user'] if @user.class.include_root_in_json
|
115
|
-
render :json => { :user => user_data,
|
116
|
-
:csrf => form_authenticity_token }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# POST /session
|
124
|
-
def create
|
125
|
-
@user = User.new params[:user]
|
126
|
-
@redirect_url = params[:redirect_url] || session_url
|
127
|
-
self.current_user =
|
128
|
-
User.find_by_email_and_password @user.email, @user.password
|
129
|
-
|
130
|
-
respond_to do |format|
|
131
|
-
if current_user
|
132
|
-
format.html { redirect_to @redirect_url }
|
133
|
-
format.json do
|
134
|
-
user_data = @user.as_json
|
135
|
-
user_data = user_data['user'] if @user.class.include_root_in_json
|
136
|
-
render :json => { :user => user_data,
|
137
|
-
:csrf => form_authenticity_token }
|
138
|
-
end
|
139
|
-
else
|
140
|
-
notice = 'Invalid e-mail or password'
|
141
|
-
format.html do
|
142
|
-
redirect_to new_session_url, :flash => {
|
143
|
-
:notice => notice, :auth_redirect_url => @redirect_url }
|
144
|
-
end
|
145
|
-
format.json { render :json => { :error => notice} }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# DELETE /session
|
151
|
-
def destroy
|
152
|
-
self.current_user = nil
|
153
|
-
respond_to do |format|
|
154
|
-
format.html { redirect_to session_url }
|
155
|
-
format.json { head :ok }
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
# Hook for setting up the home view.
|
160
|
-
def home
|
161
|
-
end
|
162
|
-
private :home
|
163
|
-
|
164
|
-
# Hook for setting up the welcome view.
|
165
|
-
def welcome
|
166
|
-
end
|
167
|
-
private :welcome
|
168
|
-
end # module Authpwn::Session::SessionControllerInstanceMethods
|
169
|
-
|
170
|
-
ActionController::Base.send :include, ControllerMixin
|
66
|
+
end # module AuthpwnRails::ControllerInstanceMethods
|
171
67
|
|
68
|
+
end # namespace AuthpwnRails
|
172
69
|
|
173
70
|
# :nodoc: add session modification
|
174
71
|
class ActionController::TestCase
|
@@ -183,7 +80,3 @@ class ActionController::TestCase
|
|
183
80
|
User.find_by_param user_param
|
184
81
|
end
|
185
82
|
end
|
186
|
-
|
187
|
-
end # namespace AuthpwnRails::Session
|
188
|
-
|
189
|
-
end # namespace AuthpwnRails
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module AuthpwnRails
|
5
|
+
|
6
|
+
# Included by the controller that handles user authentication.
|
7
|
+
#
|
8
|
+
# Right now, some parts of the codebase assume the controller will be named
|
9
|
+
# Session.
|
10
|
+
module SessionController
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
authenticates_using_session
|
15
|
+
end
|
16
|
+
|
17
|
+
# Included in controllers that include AuthpwnRails::SessionController.
|
18
|
+
module InstanceMethods
|
19
|
+
# GET /session/new
|
20
|
+
def new
|
21
|
+
@user = User.new
|
22
|
+
@redirect_url = flash[:auth_redirect_url]
|
23
|
+
redirect_to session_url if current_user
|
24
|
+
end
|
25
|
+
|
26
|
+
# GET /session
|
27
|
+
def show
|
28
|
+
@user = current_user || User.new
|
29
|
+
if @user.new_record?
|
30
|
+
welcome
|
31
|
+
unless performed?
|
32
|
+
respond_to do |format|
|
33
|
+
format.html { render :action => :welcome }
|
34
|
+
format.json { render :json => {} }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
home
|
39
|
+
unless performed?
|
40
|
+
respond_to do |format|
|
41
|
+
format.html { render :action => :home }
|
42
|
+
format.json do
|
43
|
+
user_data = @user.as_json
|
44
|
+
user_data = user_data['user'] if @user.class.include_root_in_json
|
45
|
+
render :json => { :user => user_data,
|
46
|
+
:csrf => form_authenticity_token }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# POST /session
|
54
|
+
def create
|
55
|
+
@user = User.new params[:user]
|
56
|
+
@redirect_url = params[:redirect_url] || session_url
|
57
|
+
self.current_user =
|
58
|
+
User.find_by_email_and_password @user.email, @user.password
|
59
|
+
|
60
|
+
respond_to do |format|
|
61
|
+
if current_user
|
62
|
+
format.html { redirect_to @redirect_url }
|
63
|
+
format.json do
|
64
|
+
user_data = @user.as_json
|
65
|
+
user_data = user_data['user'] if @user.class.include_root_in_json
|
66
|
+
render :json => { :user => user_data,
|
67
|
+
:csrf => form_authenticity_token }
|
68
|
+
end
|
69
|
+
else
|
70
|
+
notice = 'Invalid e-mail or password'
|
71
|
+
format.html do
|
72
|
+
redirect_to new_session_url, :flash => {
|
73
|
+
:notice => notice, :auth_redirect_url => @redirect_url }
|
74
|
+
end
|
75
|
+
format.json { render :json => { :error => notice} }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# DELETE /session
|
81
|
+
def destroy
|
82
|
+
self.current_user = nil
|
83
|
+
respond_to do |format|
|
84
|
+
format.html { redirect_to session_url }
|
85
|
+
format.json { head :ok }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Hook for setting up the home view.
|
90
|
+
def home
|
91
|
+
end
|
92
|
+
private :home
|
93
|
+
|
94
|
+
# Hook for setting up the welcome view.
|
95
|
+
def welcome
|
96
|
+
end
|
97
|
+
private :welcome
|
98
|
+
end # module AuthpwnRails::SessionController::InstanceMethods
|
99
|
+
|
100
|
+
end # module AuthpwnRails::SessionController
|
101
|
+
|
102
|
+
end # namespace AuthpwnRails
|
@@ -1,24 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support'
|
2
3
|
|
3
4
|
# :nodoc: namespace
|
4
5
|
module AuthpwnRails
|
5
6
|
|
6
|
-
#
|
7
|
+
# Included by the model class that represents users.
|
8
|
+
#
|
9
|
+
# Right now, some parts of the codebase assume the model will be named User.
|
7
10
|
module UserModel
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
module ModelMixin
|
12
|
-
def self.included(base)
|
13
|
-
base.send :extend, ModelClassMethods
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
# Methods here become ActiveRecord::Base class methods.
|
19
|
-
module ModelClassMethods
|
20
|
-
# Extends the model with all that it needs to be PwnAuth's user model.
|
21
|
-
def pwnauth_user_model
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
22
14
|
# E-mail address identifying the user account.
|
23
15
|
validates :email, :format => /^[A-Za-z0-9.+_]+@[^@]*\.(\w+)$/,
|
24
16
|
:presence => true, :length => 1..128, :uniqueness => true
|
@@ -42,94 +34,86 @@ module ModelClassMethods
|
|
42
34
|
|
43
35
|
# Facebook token.
|
44
36
|
has_one :facebook_token, :dependent => :destroy, :inverse_of => :user
|
45
|
-
|
46
|
-
extend ModelMetaclassMethods
|
47
|
-
include ModelInstanceMethods
|
48
37
|
end
|
49
|
-
end # module AuthpwnRails::UserModel::ModelClassMethods
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
# The authenticated user or nil.
|
62
|
-
def find_by_email_and_password(email, password)
|
63
|
-
user = where(:email => email).first
|
64
|
-
(user && user.password_matches?(password)) ? user : nil
|
65
|
-
end
|
66
|
-
|
67
|
-
# Computes a password hash from a raw password and a salt.
|
68
|
-
def hash_password(password, salt)
|
69
|
-
Digest::SHA2.hexdigest(password + salt)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Generates a random salt value.
|
73
|
-
def random_salt
|
74
|
-
[(0...12).map { |i| 1 + rand(255) }.pack('C*')].pack('m').strip
|
75
|
-
end
|
76
|
-
|
77
|
-
# Fills out a new user's information based on a Facebook access token.
|
78
|
-
def create_with_facebook_token(token)
|
79
|
-
self.create! :email => "#{token.external_uid}@graph.facebook.com"
|
80
|
-
end
|
81
|
-
|
82
|
-
# The user that owns a given Facebook OAuth2 token.
|
83
|
-
#
|
84
|
-
# A new user will be created if the token doesn't belong to any user. This is
|
85
|
-
# the case for a new visitor.
|
86
|
-
def for_facebook_token(access_token)
|
87
|
-
FacebookToken.for(access_token).user
|
88
|
-
end
|
89
|
-
end # module AuthpwnRails::UserModel::ModelMetaclassMethods
|
90
|
-
|
91
|
-
|
92
|
-
# Included in models that call pwnauth_user_model.
|
93
|
-
module ModelInstanceMethods
|
94
|
-
# Resets the virtual password attributes.
|
95
|
-
def reset_password
|
96
|
-
@password = @password_confirmation = nil
|
97
|
-
end
|
39
|
+
# Class methods on models that include AuthpwnRails::UserModel.
|
40
|
+
module ClassMethods
|
41
|
+
# Queries the database using the value returned by User#to_param.
|
42
|
+
#
|
43
|
+
# Returns nil if no matching User exists.
|
44
|
+
def find_by_param(param)
|
45
|
+
where(:email_hash => param).first
|
46
|
+
end
|
98
47
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
48
|
+
# The authenticated user or nil.
|
49
|
+
def find_by_email_and_password(email, password)
|
50
|
+
user = where(:email => email).first
|
51
|
+
(user && user.password_matches?(password)) ? user : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# Computes a password hash from a raw password and a salt.
|
55
|
+
def hash_password(password, salt)
|
56
|
+
Digest::SHA2.hexdigest(password + salt)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generates a random salt value.
|
60
|
+
def random_salt
|
61
|
+
[(0...12).map { |i| 1 + rand(255) }.pack('C*')].pack('m').strip
|
62
|
+
end
|
63
|
+
|
64
|
+
# Fills out a new user's information based on a Facebook access token.
|
65
|
+
def create_with_facebook_token(token)
|
66
|
+
self.create! :email => "#{token.external_uid}@graph.facebook.com"
|
67
|
+
end
|
68
|
+
|
69
|
+
# The user that owns a given Facebook OAuth2 token.
|
70
|
+
#
|
71
|
+
# A new user will be created if the token doesn't belong to any user. This
|
72
|
+
# is the case for a new visitor.
|
73
|
+
def for_facebook_token(access_token)
|
74
|
+
FacebookToken.for(access_token).user
|
75
|
+
end
|
76
|
+
end # module AuthpwnRails::UserModel::ClassMethods
|
118
77
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
78
|
+
# Included in models that include AuthpwnRails::UserModel.
|
79
|
+
module InstanceMethods
|
80
|
+
# Resets the virtual password attributes.
|
81
|
+
def reset_password
|
82
|
+
@password = @password_confirmation = nil
|
83
|
+
end
|
84
|
+
|
85
|
+
# Compares the given password against the user's stored password.
|
86
|
+
#
|
87
|
+
# Returns +true+ for a match, +false+ otherwise.
|
88
|
+
def password_matches?(passwd)
|
89
|
+
password_hash == self.class.hash_password(passwd, password_salt)
|
90
|
+
end
|
124
91
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
92
|
+
# Password virtual attribute.
|
93
|
+
def password=(new_password)
|
94
|
+
@password = new_password
|
95
|
+
self.password_salt = self.class.random_salt
|
96
|
+
self.password_hash = new_password &&
|
97
|
+
self.class.hash_password(new_password, password_salt)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Use e-mails instead of exposing ActiveRecord IDs.
|
101
|
+
def to_param
|
102
|
+
email_hash
|
103
|
+
end
|
104
|
+
|
105
|
+
# :nodoc: overwrites
|
106
|
+
def email=(new_email)
|
107
|
+
super
|
108
|
+
self.email_hash = new_email && Digest::SHA2.hexdigest(new_email)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Do not expose password and ActiveRecord IDs in JSON representation.
|
112
|
+
def as_json(options = {})
|
113
|
+
options ||= {}
|
114
|
+
super(options.merge(:except => [:password_salt, :password_hash, :id]))
|
115
|
+
end
|
116
|
+
end # module AuthpwnRails::UserModel::InstanceMethods
|
133
117
|
|
134
118
|
end # namespace AuthpwnRails::UserModel
|
135
119
|
|
data/lib/authpwn_rails.rb
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
module AuthpwnRails
|
3
3
|
end
|
4
4
|
|
5
|
-
require 'authpwn_rails/
|
5
|
+
require 'authpwn_rails/facebook_session.rb'
|
6
|
+
require 'authpwn_rails/facebook_token_model.rb'
|
6
7
|
require 'authpwn_rails/session.rb'
|
8
|
+
require 'authpwn_rails/session_controller.rb'
|
7
9
|
require 'authpwn_rails/user_model.rb'
|
8
10
|
|
9
11
|
if defined?(Rails)
|
@@ -34,7 +34,8 @@ class CookieControllerTest < ActionController::TestCase
|
|
34
34
|
get :show
|
35
35
|
assert_response :success
|
36
36
|
assert_equal @user, assigns(:current_user)
|
37
|
-
assert_equal "User: #{Fixtures.identify(:john)}",
|
37
|
+
assert_equal "User: #{ActiveRecord::Fixtures.identify(:john)}",
|
38
|
+
response.body
|
38
39
|
end
|
39
40
|
|
40
41
|
test "invalid user_pid in session" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authpwn_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Victor Costan
|
@@ -15,11 +15,10 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-05 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
22
|
none: false
|
24
23
|
requirements:
|
25
24
|
- - ">="
|
@@ -30,12 +29,12 @@ dependencies:
|
|
30
29
|
- 1
|
31
30
|
- 7
|
32
31
|
version: 0.1.7
|
32
|
+
type: :runtime
|
33
|
+
requirement: *id001
|
33
34
|
prerelease: false
|
34
|
-
version_requirements: *id001
|
35
35
|
name: fbgraph_rails
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
39
|
requirements:
|
41
40
|
- - ">="
|
@@ -48,12 +47,12 @@ dependencies:
|
|
48
47
|
- rc
|
49
48
|
- 4
|
50
49
|
version: 3.1.0.rc4
|
50
|
+
type: :runtime
|
51
|
+
requirement: *id002
|
51
52
|
prerelease: false
|
52
|
-
version_requirements: *id002
|
53
53
|
name: rails
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
|
56
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
56
|
none: false
|
58
57
|
requirements:
|
59
58
|
- - ~>
|
@@ -64,12 +63,12 @@ dependencies:
|
|
64
63
|
- 0
|
65
64
|
- 0
|
66
65
|
version: 1.0.0
|
66
|
+
type: :development
|
67
|
+
requirement: *id003
|
67
68
|
prerelease: false
|
68
|
-
version_requirements: *id003
|
69
69
|
name: bundler
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
|
72
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
73
72
|
none: false
|
74
73
|
requirements:
|
75
74
|
- - ~>
|
@@ -80,12 +79,12 @@ dependencies:
|
|
80
79
|
- 6
|
81
80
|
- 0
|
82
81
|
version: 1.6.0
|
82
|
+
type: :development
|
83
|
+
requirement: *id004
|
83
84
|
prerelease: false
|
84
|
-
version_requirements: *id004
|
85
85
|
name: jeweler
|
86
86
|
- !ruby/object:Gem::Dependency
|
87
|
-
|
88
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
89
88
|
none: false
|
90
89
|
requirements:
|
91
90
|
- - ">="
|
@@ -94,12 +93,12 @@ dependencies:
|
|
94
93
|
segments:
|
95
94
|
- 0
|
96
95
|
version: "0"
|
96
|
+
type: :development
|
97
|
+
requirement: *id005
|
97
98
|
prerelease: false
|
98
|
-
version_requirements: *id005
|
99
99
|
name: rcov
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
|
-
|
102
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
103
102
|
none: false
|
104
103
|
requirements:
|
105
104
|
- - ">="
|
@@ -110,8 +109,9 @@ dependencies:
|
|
110
109
|
- 3
|
111
110
|
- 3
|
112
111
|
version: 1.3.3
|
112
|
+
type: :development
|
113
|
+
requirement: *id006
|
113
114
|
prerelease: false
|
114
|
-
version_requirements: *id006
|
115
115
|
name: sqlite3
|
116
116
|
description: Works with Facebook.
|
117
117
|
email: victor@costan.us
|
@@ -135,7 +135,8 @@ files:
|
|
135
135
|
- authpwn_rails.gemspec
|
136
136
|
- lib/authpwn_rails.rb
|
137
137
|
- lib/authpwn_rails/engine.rb
|
138
|
-
- lib/authpwn_rails/
|
138
|
+
- lib/authpwn_rails/facebook_session.rb
|
139
|
+
- lib/authpwn_rails/facebook_token_model.rb
|
139
140
|
- lib/authpwn_rails/generators/facebook_generator.rb
|
140
141
|
- lib/authpwn_rails/generators/session_generator.rb
|
141
142
|
- lib/authpwn_rails/generators/templates/001_create_users.rb
|
@@ -152,6 +153,7 @@ files:
|
|
152
153
|
- lib/authpwn_rails/generators/templates/users.yml
|
153
154
|
- lib/authpwn_rails/generators/users_generator.rb
|
154
155
|
- lib/authpwn_rails/session.rb
|
156
|
+
- lib/authpwn_rails/session_controller.rb
|
155
157
|
- lib/authpwn_rails/user_model.rb
|
156
158
|
- test/cookie_controller_test.rb
|
157
159
|
- test/facebook_controller_test.rb
|
@@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
195
|
requirements: []
|
194
196
|
|
195
197
|
rubyforge_project:
|
196
|
-
rubygems_version: 1.8.
|
198
|
+
rubygems_version: 1.8.5
|
197
199
|
signing_key:
|
198
200
|
specification_version: 3
|
199
201
|
summary: User authentication for Rails 3 applications.
|
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'action_controller'
|
2
|
-
require 'active_record'
|
3
|
-
|
4
|
-
# :nodoc: namespace
|
5
|
-
module AuthpwnRails
|
6
|
-
|
7
|
-
# :nodoc: namespace
|
8
|
-
module FacebookExtensions
|
9
|
-
|
10
|
-
|
11
|
-
# Mixed into ActiveController::Base
|
12
|
-
module ControllerMixin
|
13
|
-
def self.included(base)
|
14
|
-
base.send :extend, ControllerClassMethods
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
# Methods here become ActiveController::Base class methods.
|
20
|
-
module ControllerClassMethods
|
21
|
-
# Authenticates users via Facebook OAuth2, using fbgraph_rails.
|
22
|
-
#
|
23
|
-
# The User model class must implement for_facebook_token. The controller
|
24
|
-
# should obtain the Facebook token, using probes_facebook_access_token or
|
25
|
-
# requires_facebook_access_token.
|
26
|
-
def authenticates_using_facebook(options = {})
|
27
|
-
include ControllerInstanceMethods
|
28
|
-
before_filter :authenticate_using_facebook_access_token, options
|
29
|
-
end
|
30
|
-
end # module AuthpwnRails::FacebookExtensions::ControllerClassMethods
|
31
|
-
|
32
|
-
|
33
|
-
# Included in controllers that call authenticates_using_facebook.
|
34
|
-
module ControllerInstanceMethods
|
35
|
-
def authenticate_using_facebook_access_token
|
36
|
-
return true if current_user
|
37
|
-
if access_token = current_facebook_access_token
|
38
|
-
self.current_user = User.for_facebook_token access_token
|
39
|
-
# NOTE: nixing the token from the session so the user won't be logged on
|
40
|
-
# immediately after logging off
|
41
|
-
self.current_facebook_access_token = nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
private :authenticate_using_facebook_access_token
|
45
|
-
end # module AuthpwnRails::FacebookExtensions::ControllerInstanceMethods
|
46
|
-
|
47
|
-
ActionController::Base.send :include, ControllerMixin
|
48
|
-
|
49
|
-
|
50
|
-
# Mixed into ActiveRecord::Base
|
51
|
-
module ModelMixin
|
52
|
-
def self.included(base)
|
53
|
-
base.send :extend, ModelClassMethods
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
# Methods here become ActiveRecord::Base class methods.
|
59
|
-
module ModelClassMethods
|
60
|
-
# Extends the model with all that it needs to be PwnAuth's user model.
|
61
|
-
def pwnauth_facebook_token_model
|
62
|
-
# The user whose token this is.
|
63
|
-
belongs_to :user, :inverse_of => :facebook_token
|
64
|
-
validates :user, :presence => true
|
65
|
-
|
66
|
-
# A unique ID on the Facebook site for the user owning this token.
|
67
|
-
validates :external_uid, :length => 1..32, :presence => true
|
68
|
-
|
69
|
-
# The OAuth2 access token.
|
70
|
-
validates :access_token, :length => 1..128, :presence => true
|
71
|
-
|
72
|
-
extend ModelMetaclassMethods
|
73
|
-
include ModelInstanceMethods
|
74
|
-
end
|
75
|
-
end # module AuthpwnRails::UserModel::ModelClassMethods
|
76
|
-
|
77
|
-
|
78
|
-
# Included in the metaclass of models that call pwnauth_facebook_token_model.
|
79
|
-
module ModelMetaclassMethods
|
80
|
-
# Finds or creates the model containing a token.
|
81
|
-
#
|
82
|
-
# If a model for the same user exists, the model is updated with the given
|
83
|
-
# token. Otherwise, a new model will be created, together with a user.
|
84
|
-
def for(access_token)
|
85
|
-
uid = uid_from_token access_token
|
86
|
-
token = self.where(:external_uid => uid.to_str).first
|
87
|
-
if token
|
88
|
-
token.access_token = access_token
|
89
|
-
else
|
90
|
-
token = FacebookToken.new :external_uid => uid,
|
91
|
-
:access_token => access_token
|
92
|
-
token.user = User.create_with_facebook_token token
|
93
|
-
end
|
94
|
-
token.save!
|
95
|
-
token
|
96
|
-
end
|
97
|
-
|
98
|
-
# Extracts the Facebook user ID from a OAuth2 token.
|
99
|
-
#
|
100
|
-
# This is a hack. It works based on the current format, but might break at any
|
101
|
-
# time. Hopefully, we'll eventually have an official way of pulling the UID
|
102
|
-
# out of an OAuth2 token.
|
103
|
-
def uid_from_token(access_token)
|
104
|
-
access_token.split('|')[1].split('-').last
|
105
|
-
end
|
106
|
-
end # module AuthpwnRails::UserModel::ModelMetaclassMethods
|
107
|
-
|
108
|
-
|
109
|
-
# Included in models that call pwnauth_user_model.
|
110
|
-
module ModelInstanceMethods
|
111
|
-
# FBGraph client loaded with this access token.
|
112
|
-
def facebook_client
|
113
|
-
@client ||= FBGraphRails.fbclient(access_token)
|
114
|
-
end
|
115
|
-
end # module AuthpwnRails::UserModel::ModelInstanceMethods
|
116
|
-
|
117
|
-
ActiveRecord::Base.send :include, ModelMixin
|
118
|
-
|
119
|
-
end # namespace AuthpwnRails::FacebookExtensions
|
120
|
-
|
121
|
-
end # namespace AuthpwnRails
|