Skip to content
This repository
Newer
Older
100644 262 lines (173 sloc) 15.3 kb
1b98335c » yourewelcome
2008-10-24 Initial commit
1 = Authgasm
2
e77ca8a3 » yourewelcome
2008-10-25 Updated readme
3 Authgasm is "rails authentication done right"
1b98335c » yourewelcome
2008-10-24 Initial commit
4
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
5 The last thing we need is another authentication solution for rails, right? That's what I thought until I tried out some of the current solutions. None of them felt right. They were either too complicated, bloated, littered my application with tons of code, or were just confusing. This is not the simple / elegant rails we all fell in love with. We need a "rails like" authentication solution. Authgasm is my attempt to satisfy that need...
ae1d3bb0 » yourewelcome
2008-10-26 Released v0.9.1
6
7 What if you could have authentication up and running in minutes without having to run a generator? All because it's simple, like everything else in rails.
1b98335c » yourewelcome
2008-10-24 Initial commit
8
21554776 » yourewelcome
2008-10-28 Updated readme
9 Wouldn't it be nice to keep your app up to date with the latest and greatest security techniques with a simple update of a plugin?
10
34b225cf » yourewelcome
2008-10-25 Updated readme
11 What if creating a user session could be as simple as...
e77ca8a3 » yourewelcome
2008-10-25 Updated readme
12
4b1f8faf » yourewelcome
2008-10-28 User column_names instead of colums when determining if a column exists
13 UserSession.create(params[:user_session])
e77ca8a3 » yourewelcome
2008-10-25 Updated readme
14
34b225cf » yourewelcome
2008-10-25 Updated readme
15 What if your user sessions controller could look just like your other controllers...
1b98335c » yourewelcome
2008-10-24 Initial commit
16
17 class UserSessionsController < ApplicationController
18 def new
19 @user_session = UserSession.new
20 end
21
22 def create
23 @user_session = UserSession.new(params[:user_session])
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
24 if @user_session.save
c93bec2d » yourewelcome
2008-10-24 Changed scope to id
25 redirect_to account_url
1b98335c » yourewelcome
2008-10-24 Initial commit
26 else
27 render :action => :new
28 end
29 end
30
31 def destroy
32 @user_session.destroy
33 end
34 end
35
24501b4c » yourewelcome
2008-10-29 Release v0.10.2
36 Look familiar? If you didn't know any better, you would think UserSession was an ActiveRecord model. I think that's pretty cool, because it fits nicely into the RESTful development pattern, a style we all know and love. What about the view...
1b98335c » yourewelcome
2008-10-24 Initial commit
37
38 <%= error_messages_for "user_session" %>
39 <% form_for @user_session do |f| %>
40 <%= f.label :login %><br />
41 <%= f.text_field :login %><br />
42 <br />
43 <%= f.label :password %><br />
44 <%= f.password_field :password %><br />
45 <br />
46 <%= f.submit "Login" %>
47 <% end %>
48
34b225cf » yourewelcome
2008-10-25 Updated readme
49 Or how about persisting the session...
1b98335c » yourewelcome
2008-10-24 Initial commit
50
51 class ApplicationController
52 before_filter :load_user
53
54 protected
55 def load_user
56 @user_session = UserSession.find
57 @current_user = @user_session && @user_session.record
58 end
59 end
60
34b225cf » yourewelcome
2008-10-25 Updated readme
61 Authgasm makes this a reality. This is just the tip of the ice berg. Keep reading to find out everything Authgasm can do.
1b98335c » yourewelcome
2008-10-24 Initial commit
62
63 == Helpful links
64
65 * <b>Documentation:</b> http://authgasm.rubyforge.org
66 * <b>Authgasm tutorial:</b> coming soon...
67 * <b>Live example of the tutorial above (with source):</b> coming soon....
68 * <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/18752-authgasm
69
70 == Install and use
71
72 === Install the gem / plugin
73
74 $ sudo gem install authgasm
75 $ cd vendor/plugins
76 $ sudo gem unpack authgasm
77
78 Or as a plugin
79
80 script/plugin install git://github.com/binarylogic/authgasm.git
81
77798f20 » yourewelcome
2008-10-25 Updated installation guide
82 === Create your session
1b98335c » yourewelcome
2008-10-24 Initial commit
83
77798f20 » yourewelcome
2008-10-25 Updated installation guide
84 For this walk through lets assume you are setting up a session for your User model.
1b98335c » yourewelcome
2008-10-24 Initial commit
85
77798f20 » yourewelcome
2008-10-25 Updated installation guide
86 Create your user_session.rb file:
1b98335c » yourewelcome
2008-10-24 Initial commit
87
77798f20 » yourewelcome
2008-10-25 Updated installation guide
88 # app/models/user_session.rb
89 class UserSession < Authgasm::Session::Base
90 # configuration here, just like ActiveRecord, or in an initializer
91 # See Authgasm::Session::Config::ClassMethods for more details
92 end
1b98335c » yourewelcome
2008-10-24 Initial commit
93
ae1d3bb0 » yourewelcome
2008-10-26 Released v0.9.1
94 It is important to set your configuration for your session before you set the configuration for your model. This will save you some time. Your model will try to guess its own configuration based on what you set in the session. These are completely separate, making Authgasm as flexible as it needs to be, but the majority of the time they will be the same and no one likes to repeat their self.
1b98335c » yourewelcome
2008-10-24 Initial commit
95
3691177a » yourewelcome
2008-10-25 Updated readme
96 === Ensure proper database fields
1b98335c » yourewelcome
2008-10-24 Initial commit
97
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
98 The user model needs to have the following columns. The names of these columns can be changed with configuration. Better yet, Authgasm tries to guess these names by checking for the existence of common names. See Authgasm::Session::Config::ClassMethods for more details, but chances are you won't have to specify any configuration for your field names, even if they aren't the same names as below.
1b98335c » yourewelcome
2008-10-24 Initial commit
99
100 t.string :login, :null => false
101 t.string :crypted_password, :null => false
102 t.string :password_salt, :null => false # not needed if you are encrypting your pw instead of using a hash algorithm
103 t.string :remember_token, :null => false
c00672f7 » yourewelcome
2008-10-25 Updated automatic session maintenance
104 t.integer :login_count # This is optional, it is a "magic" column, just like "created_at". See below for a list of all magic columns.
1b98335c » yourewelcome
2008-10-24 Initial commit
105
77798f20 » yourewelcome
2008-10-25 Updated installation guide
106 === Set up your model
1b98335c » yourewelcome
2008-10-24 Initial commit
107
77798f20 » yourewelcome
2008-10-25 Updated installation guide
108 Make sure you have a model that you will be authenticating with. For this example let's say you have a User model:
109
110 class User < ActiveRecord::Base
111 acts_as_authentic # for options see documentation: Authgasm::ActsAsAuthentic::ClassMethods
1b98335c » yourewelcome
2008-10-24 Initial commit
112 end
113
114 Done! Now go use it just like you would with any other ActiveRecord model (see above).
115
116 == Magic Columns
117
118 Just like ActiveRecord has "magic" columns, such as: created_at and updated_at. Authgasm has its own "magic" columns too:
119
120 Column name Description
ae1d3bb0 » yourewelcome
2008-10-26 Released v0.9.1
121 login_count Increased every time an explicit login is made. This will *NOT* increase if logging in by a session, cookie, or basic http auth
e77ca8a3 » yourewelcome
2008-10-25 Updated readme
122 last_request_at Updates every time the user logs in, either by explicitly logging in, or logging in by cookie, session, or http auth
1b98335c » yourewelcome
2008-10-24 Initial commit
123 current_login_at Updates with the current time when an explicit login is made.
124 last_login_at Updates with the value of current_login_at before it is reset.
125 current_login_ip Updates with the request remote_ip when an explicit login is made.
126 last_login_ip Updates with the value of current_login_ip before it is reset.
127
128 == Magic States
129
130 Authgasm tries to check the state of the record before creating the session. If your record responds to the following methods and any of them return false, validation will fail:
131
132 Method name Description
21554776 » yourewelcome
2008-10-28 Updated readme
133 active? Is the record marked as active?
1b98335c » yourewelcome
2008-10-24 Initial commit
134 approved? Has the record been approved?
135 confirmed? Has the record been conirmed?
136
ff673748 » yourewelcome
2008-10-25 Cleaned up identifier doc
137 What's neat about this is that these are checked upon any type of login. When logging in explicitly, by cookie, session, or basic http auth. So if you mark a user inactive in the middle of their session they wont be logged back in next time they refresh the page. Giving you complete control.
1b98335c » yourewelcome
2008-10-24 Initial commit
138
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
139 Need Authgasm to check your own "state"? No problem, check out the hooks section below. Add in a before_validation or after_validation to do your own checking.
140
1b98335c » yourewelcome
2008-10-24 Initial commit
141 == Hooks / Callbacks
142
143 Just like ActiveRecord you can create your own hooks / callbacks so that you can do whatever you want when certain actions are performed. Here they are:
144
145 before_create
146 after_create
147 before_destroy
148 after_destroy
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
149 before_save
150 after_save
1b98335c » yourewelcome
2008-10-24 Initial commit
151 before_update
152 after_update
153 before_validation
154 after_validation
155
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
156 == Errors
157
158 The errors in Authgasm work JUST LIKE ActiveRecord. In fact, it uses the exact same ActiveRecord errors class. Use it the same way:
159
160 class UserSession
161 before_validation :check_if_awesome
162
163 private
164 def check_if_awesome
165 errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
166 errors.add_to_base("You must be awesome to log in") unless record.awesome?
167 end
168 end
169
1b98335c » yourewelcome
2008-10-24 Initial commit
170 == Automatic Session Updating
171
4b1f8faf » yourewelcome
2008-10-28 User column_names instead of colums when determining if a column exists
172 This is one of my favorite features that I think is pretty cool. It's things like this that make a library great and let you know you are on the right track.
718f2cf5 » yourewelcome
2008-10-25 Updated readme on session updating
173
20fcb6fa » yourewelcome
2008-10-27 Bumped to Sha512
174 Just to clear up any confusion, Authgasm does not store the plain id in the session. It stores a token. This token changes with the password, this way stale sessions can not be persisted.
175
176 That being said...What if a user changes their password? You have to re-log them in with the new password, recreate the session, etc, pain in the ass. Or what if a user creates a new user account? You have to do the same thing. Here's an even better one: what if a user is in the admin area and changes his own password? There might even be another place passwords can change. It shouldn't matter, your code should be written in a way where you don't have to remember to do this.
718f2cf5 » yourewelcome
2008-10-25 Updated readme on session updating
177
34b225cf » yourewelcome
2008-10-25 Updated readme
178 Instead of updating sessions all over the place, doesn't it make sense to do this at a lower level? Like the User model? You're saying "but Ben, models can't mess around with sessions and cookies". True...but Authgasm can, and you can access Authgasm just like a model. I know in most situations it's not good practice to do this but I view this in the same class as sweepers, and feel like it actually is good practice here. User sessions are directly tied to users, they should be connected on the model level.
718f2cf5 » yourewelcome
2008-10-25 Updated readme on session updating
179
34b225cf » yourewelcome
2008-10-25 Updated readme
180 Fear not, because the acts_as_authentic method you call in your model takes care of this for you, by adding an after_create and after_update callback to automatically keep the session up to date. You don't have to worry about it anymore. Don't even think about it. Let your UsersController deal with users, not users *AND* sessions. *ANYTIME* the user changes his password in *ANY* way, his session will be updated.
718f2cf5 » yourewelcome
2008-10-25 Updated readme on session updating
181
34b225cf » yourewelcome
2008-10-25 Updated readme
182 Here is basically how this is done....
1b98335c » yourewelcome
2008-10-24 Initial commit
183
34b225cf » yourewelcome
2008-10-25 Updated readme
184 class User < ActiveRecord::Base
185 after_create :create_sessions!
186 after_update :update_sessions!
187
188 private
189 def create_sessions!
190 # create a new UserSession if they are not logged in
191 end
192
193 def update_sessions!
194 # find their session
195 # check that their session's record is the same one as this one: session.record == self
196 # update the session with the new info: session.update
197 end
198 end
199
ae1d3bb0 » yourewelcome
2008-10-26 Released v0.9.1
200 Obviously there is a little more to it than this, but hopefully this clarifies any confusion. Lastly, this can be altered / disabled via a configuration option.
1b98335c » yourewelcome
2008-10-24 Initial commit
201
202 When things come together like this I think its a sign that you are doing something right. Put that in your pipe and smoke it!
203
ff673748 » yourewelcome
2008-10-25 Cleaned up identifier doc
204 == Multiple Sessions / Session Identifiers
bf796a03 » yourewelcome
2008-10-24 Added info in the readme on multiple sessions
205
206 You're asking: "why would I want multiple sessions?". Take this example:
207
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
208 You have an app where users login and then need to re-login to view / change their billing information. Similar to how Apple's me.com works. What you could do is have the user login with their normal session, then have an entirely new session that represents their "secure" session. But wait, this is 2 users sessions. No problem:
bf796a03 » yourewelcome
2008-10-24 Added info in the readme on multiple sessions
209
210 # regular user session
211 @user_session = UserSession.new
212 @user_session.id
213 # => nil
214
215 # secure user session
216 @secure_user_session = UserSession.new(:secure)
217 @secure_user_session.id
218 # => :secure
219
7c5c3cbe » yourewelcome
2008-10-24 Added info in the readme on multiple sessions
220 This will keep everything separate. The :secure session will store its info in a separate cookie, separate session, etc. Just set the id and you are good to go. Need to retrieve the session?
221
222 @user_session = UserSession.find
223 @secure_user_session = UserSession.find(:secure)
224
225 For more information on ids checkout Authgasm::Session::Base#initialize
bf796a03 » yourewelcome
2008-10-24 Added info in the readme on multiple sessions
226
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
227 == What about [insert framework here]?
228
229 As of now, authgasm supports rails right out of the box. But I designed authgasm to be framework agnostic. The only thing stopping Authgasm from being implemented in merb, or any other framework, is a simple adapter. I have not had the opportunity to use Authgasm in anything other than rails. If you want to use this in merb or any other framework take a look at authgasm/controller/rails_adapter.rb.
230
1b98335c » yourewelcome
2008-10-24 Initial commit
231 == How it works
232
35f14baf » yourewelcome
2008-10-27 Released v0.10.0
233 Interested in how all of this all works? Basically a before_filter is automatically set in your controller which lets Authgasm know about the current controller object. This allows Authgasm to set sessions, cookies, login via basic http auth, etc. If you are using rails in a multiple thread environment, don't worry. I kept that in mind and made this thread safe.
1b98335c » yourewelcome
2008-10-24 Initial commit
234
77798f20 » yourewelcome
2008-10-25 Updated installation guide
235 From there it is pretty simple. When you try to create a new session the record is authenticated and then all of the session / cookie magic is done for you. The sky is the limit.
1b98335c » yourewelcome
2008-10-24 Initial commit
236
b49258fd » yourewelcome
2008-10-28 Updated readme
237 == What's wrong with the current solutions?
21554776 » yourewelcome
2008-10-28 Updated readme
238
239 You probably don't care, but I think releasing the millionth authentication solution for a framework that has been around for over 4 years requires a little explanation.
240
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
241 I don't necessarily think the current solutions are "wrong", nor am I saying Authgasm is the answer to your prayers. But, to me, the current solutions were lacking something. Here's what I came up with...
21554776 » yourewelcome
2008-10-28 Updated readme
242
9f0ec4fa » yourewelcome
2008-10-28 Released v0.10.0
243 === Generators are not the answer
21554776 » yourewelcome
2008-10-28 Updated readme
244
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
245 Generators have their place, and it is not to add authentication to a rails app. It doesn't make sense. Generators are meant to be a starting point for repetitive tasks that have no sustainable pattern. Take controllers, the set up is the same thing over and over, but they eventually evolve to a point where there is no clear cut pattern. Trying to extract a pattern out into a library would be extremely hard, messy, and overly complicated. As a result, generators make sense here.
21554776 » yourewelcome
2008-10-28 Updated readme
246
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
247 Authentication is a one time set up process for your app. It's the same thing over and over and the pattern never really changes. The only time it changes is to conform with newer / stricter security techniques. This is exactly why generators should not be an authentication solution. Generators add code to your application, once code crosses that line, you are responsible for maintaining it. You get to make sure it stays up with the latest and greatest security techniques. And when the plugin you used releases some major update, you can't just re-run the generator, you get to sift through the code to see what changed! Awesome! The cherry on top is the fact that you get to go through every app you've made and apply this update. You don't really have a choice either, because you can't ignore security updates.
21554776 » yourewelcome
2008-10-28 Updated readme
248
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
249 Using a library that hundreds of other people use has it advantages. Probably one of the biggest advantages if that you get to benefit from other people using the same code. When Bob in California figures out a new awesome security technique and adds it into Authgasm, you get to benefit from that with a single update. The catch is that this benefit is limited to code that is not "generated" or added into your app. As I said above, once code is "generated" and added into your app, it's your responsibility.
250
251 Lastly, there is a pattern here, why clutter up all of your applications with the same code? I recently switched over one of my apps to Authgasm and its amazing how much cleaner my app feels.
21554776 » yourewelcome
2008-10-28 Updated readme
252
253 === Limited to a single authentication
254
3f5055e5 » yourewelcome
2008-10-28 Added stretches to the crypto provider
255 I recently had an app where you could log in as a user and also log in as an employee. I won't go into the specifics of the app, but it made the most sense to do it this way. So I had two sessions in one app. None of the current solutions I found easily supported this. They all assumed a single session. One session was messy enough, adding another just put me over the edge and eventually forced me to write Authgasm. Authgasm can support 100 different sessions easily and in a clean format. Just like an app can support 100 different models and 100 different records of each model.
21554776 » yourewelcome
2008-10-28 Updated readme
256
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
257 === Too presumptuous
258
4d428027 » yourewelcome
2008-10-29 Ignore invalid credential fields, dont raise an exception
259 A lot of them forced me to name my password column as "this", or the key of my cookie had to be "this". They were a little too presumptuous. I am probably overly picky, but little details like that should be configurable. This also made it very hard to implement into an existing app.
832b7f0e » yourewelcome
2008-10-29 Cleaned up readme
260
1b98335c » yourewelcome
2008-10-24 Initial commit
261
262 Copyright (c) 2008 Ben Johnson of [Binary Logic](http://www.binarylogic.com), released under the MIT license
Something went wrong with that request. Please try again.