restful_authentication 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/CHANGELOG +68 -0
  2. data/LICENSE +20 -0
  3. data/README.textile +232 -0
  4. data/Rakefile +54 -0
  5. data/TODO +15 -0
  6. data/generators/authenticated/USAGE +1 -0
  7. data/generators/authenticated/authenticated_generator.rb +493 -0
  8. data/generators/authenticated/lib/insert_routes.rb +69 -0
  9. data/generators/authenticated/templates/_model_partial.html.erb +8 -0
  10. data/generators/authenticated/templates/activation.erb +3 -0
  11. data/generators/authenticated/templates/authenticated_system.rb +189 -0
  12. data/generators/authenticated/templates/authenticated_test_helper.rb +12 -0
  13. data/generators/authenticated/templates/controller.rb +43 -0
  14. data/generators/authenticated/templates/features/accounts.feature +67 -0
  15. data/generators/authenticated/templates/features/sessions.feature +77 -0
  16. data/generators/authenticated/templates/features/step_definitions/ra_env.rb +7 -0
  17. data/generators/authenticated/templates/features/step_definitions/user_steps.rb +31 -0
  18. data/generators/authenticated/templates/helper.rb +2 -0
  19. data/generators/authenticated/templates/login.html.erb +14 -0
  20. data/generators/authenticated/templates/machinist_spec.rb +5 -0
  21. data/generators/authenticated/templates/machinist_test.rb +5 -0
  22. data/generators/authenticated/templates/mailer.rb +25 -0
  23. data/generators/authenticated/templates/migration.rb +24 -0
  24. data/generators/authenticated/templates/model.rb +83 -0
  25. data/generators/authenticated/templates/model_controller.rb +96 -0
  26. data/generators/authenticated/templates/model_helper.rb +93 -0
  27. data/generators/authenticated/templates/model_helper_spec.rb +157 -0
  28. data/generators/authenticated/templates/observer.rb +11 -0
  29. data/generators/authenticated/templates/signup.html.erb +19 -0
  30. data/generators/authenticated/templates/signup_notification.erb +8 -0
  31. data/generators/authenticated/templates/site_keys.rb +38 -0
  32. data/generators/authenticated/templates/spec/blueprints/user.rb +13 -0
  33. data/generators/authenticated/templates/spec/controllers/access_control_spec.rb +89 -0
  34. data/generators/authenticated/templates/spec/controllers/authenticated_system_spec.rb +107 -0
  35. data/generators/authenticated/templates/spec/controllers/sessions_controller_spec.rb +138 -0
  36. data/generators/authenticated/templates/spec/controllers/users_controller_spec.rb +197 -0
  37. data/generators/authenticated/templates/spec/fixtures/users.yml +60 -0
  38. data/generators/authenticated/templates/spec/helpers/users_helper_spec.rb +141 -0
  39. data/generators/authenticated/templates/spec/models/user_spec.rb +298 -0
  40. data/generators/authenticated/templates/tasks/auth.rake +33 -0
  41. data/generators/authenticated/templates/test/functional_test.rb +84 -0
  42. data/generators/authenticated/templates/test/mailer_test.rb +31 -0
  43. data/generators/authenticated/templates/test/model_functional_test.rb +91 -0
  44. data/generators/authenticated/templates/test/unit_test.rb +177 -0
  45. data/lib/authentication.rb +40 -0
  46. data/lib/authentication/by_cookie_token.rb +82 -0
  47. data/lib/authentication/by_password.rb +64 -0
  48. data/lib/authorization.rb +14 -0
  49. data/lib/authorization/aasm_roles.rb +64 -0
  50. data/lib/authorization/stateful_roles.rb +64 -0
  51. data/lib/restful_authentication.rb +6 -0
  52. data/lib/trustification.rb +14 -0
  53. data/lib/trustification/email_validation.rb +20 -0
  54. data/notes/AccessControl.txt +2 -0
  55. data/notes/Authentication.txt +5 -0
  56. data/notes/Authorization.txt +154 -0
  57. data/notes/RailsPlugins.txt +78 -0
  58. data/notes/SecurityFramework.graffle +0 -0
  59. data/notes/SecurityFramework.png +0 -0
  60. data/notes/SecurityPatterns.txt +163 -0
  61. data/notes/Tradeoffs.txt +126 -0
  62. data/notes/Trustification.txt +49 -0
  63. data/restful_authentication.gemspec +32 -0
  64. metadata +128 -0
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Authentication
3
+ module ByCookieToken
4
+ # Stuff directives into including module
5
+ def self.included(recipient)
6
+ recipient.extend(ModelClassMethods)
7
+ recipient.class_eval do
8
+ include ModelInstanceMethods
9
+ end
10
+ end
11
+
12
+ #
13
+ # Class Methods
14
+ #
15
+ module ModelClassMethods
16
+ end # class methods
17
+
18
+ #
19
+ # Instance Methods
20
+ #
21
+ module ModelInstanceMethods
22
+ def remember_token?
23
+ (!remember_token.blank?) &&
24
+ remember_token_expires_at && (Time.now.utc < remember_token_expires_at.utc)
25
+ end
26
+
27
+ # These create and unset the fields required for remembering users between browser closes
28
+ def remember_me
29
+ remember_me_for 2.weeks
30
+ end
31
+
32
+ def remember_me_for(time)
33
+ remember_me_until time.from_now.utc
34
+ end
35
+
36
+ def remember_me_until(time)
37
+ self.remember_token_expires_at = time
38
+ self.remember_token = self.class.make_token
39
+ save(false)
40
+ end
41
+
42
+ # refresh token (keeping same expires_at) if it exists
43
+ def refresh_token
44
+ if remember_token?
45
+ self.remember_token = self.class.make_token
46
+ save(false)
47
+ end
48
+ end
49
+
50
+ #
51
+ # Deletes the server-side record of the authentication token. The
52
+ # client-side (browser cookie) and server-side (this remember_token) must
53
+ # always be deleted together.
54
+ #
55
+ def forget_me
56
+ self.remember_token_expires_at = nil
57
+ self.remember_token = nil
58
+ save(false)
59
+ end
60
+ end # instance methods
61
+ end
62
+
63
+ module ByCookieTokenController
64
+ # Stuff directives into including module
65
+ def self.included( recipient )
66
+ recipient.extend( ControllerClassMethods )
67
+ recipient.class_eval do
68
+ include ControllerInstanceMethods
69
+ end
70
+ end
71
+
72
+ #
73
+ # Class Methods
74
+ #
75
+ module ControllerClassMethods
76
+ end # class methods
77
+
78
+ module ControllerInstanceMethods
79
+ end # instance methods
80
+ end
81
+ end
82
+
@@ -0,0 +1,64 @@
1
+ module Authentication
2
+ module ByPassword
3
+ # Stuff directives into including module
4
+ def self.included(recipient)
5
+ recipient.extend(ModelClassMethods)
6
+ recipient.class_eval do
7
+ include ModelInstanceMethods
8
+
9
+ # Virtual attribute for the unencrypted password
10
+ attr_accessor :password
11
+ validates_presence_of :password, :if => :password_required?
12
+ validates_presence_of :password_confirmation, :if => :password_required?
13
+ validates_confirmation_of :password, :if => :password_required?
14
+ validates_length_of :password, :within => 6..40, :if => :password_required?
15
+ before_save :encrypt_password
16
+ end
17
+ end # #included directives
18
+
19
+ #
20
+ # Class Methods
21
+ #
22
+ module ModelClassMethods
23
+ # This provides a modest increased defense against a dictionary attack if
24
+ # your db were ever compromised, but will invalidate existing passwords.
25
+ # See the README and the file config/initializers/site_keys.rb
26
+ #
27
+ # It may not be obvious, but if you set REST_AUTH_SITE_KEY to nil and
28
+ # REST_AUTH_DIGEST_STRETCHES to 1 you'll have backwards compatibility with
29
+ # older versions of restful-authentication.
30
+ def password_digest(password, salt)
31
+ digest = REST_AUTH_SITE_KEY
32
+ REST_AUTH_DIGEST_STRETCHES.times do
33
+ digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
34
+ end
35
+ digest
36
+ end
37
+ end # class methods
38
+
39
+ #
40
+ # Instance Methods
41
+ #
42
+ module ModelInstanceMethods
43
+
44
+ # Encrypts the password with the user salt
45
+ def encrypt(password)
46
+ self.class.password_digest(password, salt)
47
+ end
48
+
49
+ def authenticated?(password)
50
+ crypted_password == encrypt(password)
51
+ end
52
+
53
+ # before filter
54
+ def encrypt_password
55
+ return if password.blank?
56
+ self.salt = self.class.make_token if new_record?
57
+ self.crypted_password = encrypt(password)
58
+ end
59
+ def password_required?
60
+ crypted_password.blank? || !password.blank?
61
+ end
62
+ end # instance methods
63
+ end
64
+ end
@@ -0,0 +1,14 @@
1
+ module Authorization
2
+ def self.included(recipient)
3
+ recipient.extend(ModelClassMethods)
4
+ recipient.class_eval do
5
+ include ModelInstanceMethods
6
+ end
7
+ end
8
+
9
+ module ModelClassMethods
10
+ end # class methods
11
+
12
+ module ModelInstanceMethods
13
+ end # instance methods
14
+ end
@@ -0,0 +1,64 @@
1
+ module Authorization
2
+ module AasmRoles
3
+ unless Object.constants.include? "STATEFUL_ROLES_CONSTANTS_DEFINED"
4
+ STATEFUL_ROLES_CONSTANTS_DEFINED = true # sorry for the C idiom
5
+ end
6
+
7
+ def self.included( recipient )
8
+ recipient.extend( StatefulRolesClassMethods )
9
+ recipient.class_eval do
10
+ include StatefulRolesInstanceMethods
11
+ include AASM
12
+
13
+ aasm_column :state
14
+ aasm_initial_state :initial => :pending
15
+ aasm_state :passive
16
+ aasm_state :pending, :enter => :make_activation_code
17
+ aasm_state :active, :enter => :do_activate
18
+ aasm_state :suspended
19
+ aasm_state :deleted, :enter => :do_delete
20
+
21
+ aasm_event :register do
22
+ transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| !(u.crypted_password.blank? && u.password.blank?) }
23
+ end
24
+
25
+ aasm_event :activate do
26
+ transitions :from => :pending, :to => :active
27
+ end
28
+
29
+ aasm_event :suspend do
30
+ transitions :from => [:passive, :pending, :active], :to => :suspended
31
+ end
32
+
33
+ aasm_event :delete do
34
+ transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
35
+ end
36
+
37
+ aasm_event :unsuspend do
38
+ transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| !u.activated_at.blank? }
39
+ transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| !u.activation_code.blank? }
40
+ transitions :from => :suspended, :to => :passive
41
+ end
42
+ end
43
+ end
44
+
45
+ module StatefulRolesClassMethods
46
+ end # class methods
47
+
48
+ module StatefulRolesInstanceMethods
49
+ # Returns true if the user has just been activated.
50
+ def recently_activated?
51
+ @activated
52
+ end
53
+ def do_delete
54
+ self.deleted_at = Time.now.utc
55
+ end
56
+
57
+ def do_activate
58
+ @activated = true
59
+ self.activated_at = Time.now.utc
60
+ self.deleted_at = self.activation_code = nil
61
+ end
62
+ end # instance methods
63
+ end
64
+ end
@@ -0,0 +1,64 @@
1
+ module Authorization
2
+ module StatefulRoles
3
+ unless Object.constants.include? "STATEFUL_ROLES_CONSTANTS_DEFINED"
4
+ STATEFUL_ROLES_CONSTANTS_DEFINED = true # sorry for the C idiom
5
+ end
6
+
7
+ def self.included( recipient )
8
+ recipient.extend( StatefulRolesClassMethods )
9
+ recipient.class_eval do
10
+ include AASM
11
+ include StatefulRolesInstanceMethods
12
+
13
+ aasm_column :state
14
+ aasm_initial_state :pending
15
+ aasm_state :passive
16
+ aasm_state :pending, :enter => :make_activation_code
17
+ aasm_state :active, :enter => :do_activate
18
+ aasm_state :suspended
19
+ aasm_state :deleted, :enter => :do_delete
20
+
21
+ aasm_event :register do
22
+ transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| !(u.crypted_password.blank? && u.password.blank?) }
23
+ end
24
+
25
+ aasm_event :activate do
26
+ transitions :from => :pending, :to => :active
27
+ end
28
+
29
+ aasm_event :suspend do
30
+ transitions :from => [:passive, :pending, :active], :to => :suspended
31
+ end
32
+
33
+ aasm_event :delete do
34
+ transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
35
+ end
36
+
37
+ aasm_event :unsuspend do
38
+ transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| !u.activated_at.blank? }
39
+ transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| !u.activation_code.blank? }
40
+ transitions :from => :suspended, :to => :passive
41
+ end
42
+ end
43
+ end
44
+
45
+ module StatefulRolesClassMethods
46
+ end # class methods
47
+
48
+ module StatefulRolesInstanceMethods
49
+ # Returns true if the user has just been activated.
50
+ def recently_activated?
51
+ @activated
52
+ end
53
+ def do_delete
54
+ self.deleted_at = Time.now.utc
55
+ end
56
+
57
+ def do_activate
58
+ @activated = true
59
+ self.activated_at = Time.now.utc
60
+ self.deleted_at = self.activation_code = nil
61
+ end
62
+ end # instance methods
63
+ end
64
+ end
@@ -0,0 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), "authentication")
2
+ require File.join(File.dirname(__FILE__), "authentication", "by_password")
3
+ require File.join(File.dirname(__FILE__), "authentication", "by_cookie_token")
4
+ require File.join(File.dirname(__FILE__), "authorization")
5
+ require File.join(File.dirname(__FILE__), "authorization", "aasm_roles")
6
+ require File.join(File.dirname(__FILE__), "authorization", "stateful_roles")
@@ -0,0 +1,14 @@
1
+ module Trustification
2
+ def self.included(recipient)
3
+ recipient.extend(ModelClassMethods)
4
+ recipient.class_eval do
5
+ include ModelInstanceMethods
6
+ end
7
+ end
8
+
9
+ module ModelClassMethods
10
+ end # class methods
11
+
12
+ module ModelInstanceMethods
13
+ end # instance methods
14
+ end
@@ -0,0 +1,20 @@
1
+ module Trustification
2
+ module EmailValidation
3
+ unless Object.constants.include? "CONSTANTS_DEFINED"
4
+ CONSTANTS_DEFINED = true # sorry for the C idiom
5
+ end
6
+
7
+ def self.included(recipient)
8
+ recipient.extend(ClassMethods)
9
+ recipient.class_eval do
10
+ include InstanceMethods
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ end # class methods
16
+
17
+ module InstanceMethods
18
+ end # instance methods
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+
2
+ See the notes in [[Authorization]]
@@ -0,0 +1,5 @@
1
+ Guides to best practices:
2
+ * "The OWASP Guide to Building Secure Web Applications":http://www.owasp.org/index.php/Category:OWASP_Guide_Project
3
+ ** specifically, of course, the chapter on Authentication.
4
+ * "Secure Programming for Linux and Unix HOWTO":http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/web-authentication.html
5
+ * "Authentication and Identification,":http://www.downes.ca/post/12 by Stephen Downes **Highly Recommended**
@@ -0,0 +1,154 @@
1
+ h2. Authorization
2
+
3
+ "Best Practices for Authorization":http://www.owasp.org/index.php/Guide_to_Authorization
4
+ # auth system should deny by default
5
+ # Principle of least privilege (fine-grain)
6
+ # each non-anonymous entry point have an access control check
7
+ # authorization check at or near the beginning of code implementing sensitive activities
8
+ # Ensure that Model code checks to ensure that the requesting user should have access to the protected resource.
9
+ # Reauthorization for high value activities or after idle out
10
+ # If custom code is required to perform authorization functions, consider
11
+ fail-safe authentication and exception handling – ensure that if an exception
12
+ is thrown, the user is logged out or at least prevented from accessing the
13
+ protected resource or function.
14
+ # Well written applications centralize access control routines, so if any bugs
15
+ are found, they can be fixed once and the results apply throughout the
16
+ application immediately.
17
+
18
+ h2. Authorization in a trust context
19
+
20
+ * [http://en.wikipedia.org/wiki/Authorization]
21
+ * remember: goal is **prediction** not **control**
22
+
23
+ h2. Patterns for Policy definition / Authorization / access control
24
+
25
+ *Reference Monitor (SecPatt p256)
26
+ ** Set of authorization rules
27
+ ** Actor, Action, Resource => Monitor+(rules) => ctrlr
28
+ * Role based:
29
+ subj, role, right. action, resource
30
+ RBAC, access is controlled at the system level, outside of the user's control
31
+ * Filter based
32
+ User x Controller x Action x Params --
33
+ * Object based
34
+ model security delegation
35
+ * Access Control Matrix http://en.wikipedia.org/wiki/Access_Control_Matrix
36
+ * CommandProcessor pattern (DSL approach)
37
+ * DENY FROM ... / ALLOW FROM ... approach
38
+ * Capability based control: bundle together the designation of an object and the permission to access that object
39
+ ie. I can name it if and only if I am allowed to get at it.
40
+
41
+ h2. Notes from "Security patterns":http://www.amazon.com/Security-Patterns-Integrating-Engineering-Software/dp/0470858842
42
+ by M Schumacher ("website for book":http://www.securitypatterns.org/)
43
+
44
+ Reference Monitor (SecPatt p256)
45
+ * Set of authorization rules
46
+ * Actor, Action, Resource => Monitor+(rules) => ctrlr
47
+
48
+ = Full access with Errors (SecPatt p305)
49
+
50
+ * Users should not be able to view data or perform operations for which they
51
+ have no permissions.
52
+ * Hiding an available and accessible function is inappropriate, because users
53
+ must be able to see what they can do.
54
+ * The visual appeal and usability of a graphical user interface (GUI) can be de-
55
+ graded by varying layouts depending on the (current) access rights of a
56
+ user. For example, blank space might appear for some users where others see
57
+ options they can access, or sequence and number of menu items might differ,
58
+ depending on the current user’s rights, and thus ‘blind’ operation of the menu
59
+ by an expe- rienced user is no longer possible.
60
+ * Showing currently unavailable functions can tease users to into upgrading
61
+ their access rights, for example by paying for the access or buying a license
62
+ after us- ing a demo version.
63
+ * Trial and error are ineffective means of learning which functions are
64
+ accessible. Invoking an operation only to learn that it doesn’t work with
65
+ your access rights is confusing.
66
+ * The privilege grouping of the typical user community might not be known at the
67
+ design time of the GUI, and it might change over time, for example through
68
+ organizational or business process changes, so that providing a few special
69
+ modes of the GUI depending on the corresponding user roles is inappropriate.
70
+ * Checking whether a function is allowed by a user is most efficient, robust and
71
+ secure, if done by the function itself—at least the code performing the checks
72
+ is then closely related to the code performing the subsequent operation
73
+ afterwards.
74
+
75
+ h2. Outcomes / Obligations
76
+
77
+ -- forbid
78
+ -- ask for trust escalation (eg log in, prove_as_human, validate_email, are_you_sure, send_me_ten_cents)
79
+ -- drag ass
80
+ -- permit
81
+
82
+ -- reinterpret past actions based on future evolution of trust
83
+ -- prioritize changesets based on trust.
84
+
85
+
86
+ h2. Notes from "Core Security Patterns":http://www.coresecuritypatterns.com/patterns.htm website
87
+
88
+ # Authentication Enforcer who the hell are you
89
+ # Intercepting Validator Is your request well-formed
90
+ # Authorization Enforcer Are you allowed to do that
91
+ # Secure Logger Know what's happening/happened
92
+ #
93
+
94
+ h2. notes from "XACML":http://www.nsitonline.in/hemant/stuff/xacml/XACML%20Tutorial%20with%20a%20Use%20Case%20Scenario%20for%20Academic%20Institutions.htm
95
+
96
+ PolicySets [Policy Combining Algorithm]
97
+ Policy [Rule Combining Algorithm] (defines access to particular resources.)
98
+ # Target
99
+ ## Subject Attributes
100
+ ## Resource Attributes
101
+ ## Action Attributes
102
+ ## Environment Attributes
103
+ # Rule [Effect] Identify various conditions or cases under which a policy may become applicable
104
+ ## Subject Attributes user who has made an access request
105
+ ## Resource Attributes object to which access is requested
106
+ ## Action Attributes action the subject wants to take on the resource
107
+ ## Environment Attributes request environment (time of day, ip, etc)
108
+ ## Conditions
109
+ # Obligations
110
+
111
+ Roles -- student, janitor, dean, stranger, ...
112
+ Branches -- Departments, etc.
113
+
114
+ * Examine applicable rules until you get an outcome, failure or passes thru (in which case rejected)
115
+ * Rule combining Algorithms
116
+
117
+ * Obligations -- things to do once requests have been denied or permitted
118
+
119
+ Reference Monitor (SecPatt p256)
120
+ * Set of authorization rules
121
+ * Actor, Action, Resource --> Monitor+(rules) --> ctrlr
122
+
123
+ #
124
+ # ask for permissions on arbitrary (subject, action, resource)
125
+ * roles
126
+ # get filtered object based on action (:public_info, :admin_info, etc.)
127
+ # attach a rule to a (subject|role, action, resource) triple
128
+ "subject should have role R"
129
+ "subject should have role R on resource X"
130
+ "should meet the
131
+
132
+ * Role supervisor:
133
+ * adds, defines, removes roles. no policy -- just attaches roles to users
134
+
135
+ * Policy
136
+ answers "can Actor do Action to Resource"
137
+ * Rules
138
+ * Rule resolution
139
+ * outcome, obligations.
140
+ policy definitions can come from many places, go to policy mgr.
141
+ * Hall monitor
142
+ enforces policy (before filters)
143
+ * Policy observers
144
+ handle policy obligations
145
+
146
+ * Athentication -- identification, really: securely attach visitor to identity
147
+ * Validation -- qualify trust
148
+ * Access control -- define policy
149
+ ** Roles
150
+ ** Acc. matrix
151
+ * Authorization -- enforce policy (reference monitor ; filter chain)
152
+ * Obligations
153
+ ** Audit -- (observer)
154
+