Skip to content
Newer
Older
100644 328 lines (212 sloc) 18.9 KB
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
1 = Authlogic
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
2
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 5, 2008
3 Authlogic is a framework agnostic object based authentication solution that handles all of the non sense for you. It's as easy as ActiveRecord is with a database. Put simply, its the Chuck Norris of authentication solutions for rails, merb, etc.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
4
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
5 The last thing we need is another authentication solution, right? That's what I thought until I tried out some of the current solutions in both rails and merb. 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 ruby we all fell in love with. We need a "ruby like" authentication solution. Authlogic is my attempt to satisfy that need...
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
6
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
7 Let's take a rails application, 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?
2155477 @binarylogic Updated readme
authored Oct 28, 2008
8
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
9 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.
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
10
34b225c @binarylogic Updated readme
authored Oct 25, 2008
11 What if creating a user session could be as simple as...
e77ca8a @binarylogic Updated readme
authored Oct 25, 2008
12
4b1f8fa @binarylogic User column_names instead of colums when determining if a column exists
authored Oct 28, 2008
13 UserSession.create(params[:user_session])
e77ca8a @binarylogic Updated readme
authored Oct 25, 2008
14
34b225c @binarylogic Updated readme
authored Oct 25, 2008
15 What if your user sessions controller could look just like your other controllers...
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
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])
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
24 if @user_session.save
c93bec2 @binarylogic Changed scope to id
authored Oct 24, 2008
25 redirect_to account_url
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
26 else
27 render :action => :new
28 end
29 end
30
31 def destroy
32 @user_session.destroy
33 end
34 end
35
24501b4 @binarylogic Release v0.10.2
authored Oct 29, 2008
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...
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
37
38 <% form_for @user_session do |f| %>
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
39 <%= f.error_messages %>
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
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
34b225c @binarylogic Updated readme
authored Oct 25, 2008
49 Or how about persisting the session...
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
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
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
61 Authlogic makes this a reality. This is just the tip of the ice berg. Keep reading to find out everything Authlogic can do.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
62
63 == Helpful links
64
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
65 * <b>Documentation:</b> http://authlogic.rubyforge.org
06c8289 @binarylogic Added tutorial links in readme
authored Nov 3, 2008
66 * <b>Authlogic setup tutorial:</b> http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup
67 * <b>Live example of the setup tutorial above (with source):</b> http://authlogic_example.binarylogic.com
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
68 * <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/18752-authlogic
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
69
70 == Install and use
71
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
72 Install the gem / plugin
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
73
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
74 $ sudo gem install authlogic
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
75 $ cd vendor/plugins
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
76 $ sudo gem unpack authlogic
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
77
78 Or as a plugin
79
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
80 script/plugin install git://github.com/binarylogic/authlogic.git
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
81
6af9b61 @binarylogic Updated readme
authored Nov 3, 2008
82 === Create your session
83
84 Lets assume you are setting up a session for your User model.
85
86 Create your user_session.rb file:
87
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
93
94 === Ensure proper database fields
95
96 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.
97
98 t.string :login, :null => false
99 t.string :crypted_password, :null => false
100 t.string :password_salt, :null => false # not needed if you are encrypting your pw instead of using a hash algorithm
101 t.string :remember_token, :null => false
102 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.
103
104 === Set up your model
105
106 Make sure you have a model that you will be authenticating with. For this example let's say you have a User model:
107
108 class User < ActiveRecord::Base
109 acts_as_authentic # for options see documentation: Authgasm::ActsAsAuthentic::ClassMethods
110 end
111
112 The options for acts_as_authentic are based on the UserSession configuration. So if you specified configuration for your UserSession model you should not have to specify any options for acts_as_authentic, unless you want them to be different.
113
114 Done! Now go use it just like you would with any other ActiveRecord model. Either glance at the code at the beginning of this readme or check out the tutorial (see above in "helpful links") for a more detailed walk through.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
115
116 == Magic Columns
117
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
118 Just like ActiveRecord has "magic" columns, such as: created_at and updated_at. Authlogic has its own "magic" columns too:
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
119
120 Column name Description
ae1d3bb @binarylogic Released v0.9.1
authored Oct 26, 2008
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
e77ca8a @binarylogic Updated readme
authored Oct 25, 2008
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
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
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
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
130 Authlogic 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:
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
131
132 Method name Description
2155477 @binarylogic Updated readme
authored Oct 28, 2008
133 active? Is the record marked as active?
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
134 approved? Has the record been approved?
135 confirmed? Has the record been conirmed?
136
ff67374 @binarylogic Cleaned up identifier doc
authored Oct 25, 2008
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.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
138
2479aa0 @binarylogic Allow for login_count to be nil and initialize with 1
authored Nov 3, 2008
139 Need Authlogic to check your own "state"? No problem, check out the hooks section below. Add in a before_validation to do your own checking. The sky is the limit.
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
140
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
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
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
149 before_save
150 after_save
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
151 before_update
152 after_update
153 before_validation
154 after_validation
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
155
156 == Multiple Sessions / Session Identifiers
157
158 You're asking: "why would I want multiple sessions?". Take this example:
159
160 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:
161
162 # regular user session
163 @user_session = UserSession.new
164 @user_session.id
165 # => nil
166
167 # secure user session
168 @secure_user_session = UserSession.new(:secure)
169 @secure_user_session.id
170 # => :secure
171
172 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?
173
174 @user_session = UserSession.find
175 @secure_user_session = UserSession.find(:secure)
176
177 For more information on ids checkout Authlogic::Session::Base#initialize
178
179 == Scoping
180
181 Scoping with authentication is a little tricky because it can come in many different flavors:
182
183 1. Accounts have many users, meaning users can only belong to one account at a time.
184 2. Accounts have and belong to many users, meaning a user can belong to more than one account.
185 3. Users access their accounts via subdomains.
186 4. Users access their accounts by selecting their account and storing their selection, *NOT* using subdomains. Maybe you store their selection in a session, cookie, or the database. It doesn't matter.
187
188 Now mix and match the above, it can get pretty hairy. Fear not, because Authlogic is designed in a manner where it doesn't care how you do it, all that you have to do is break it down. When scoping a session there are 3 parts you might want to scope:
189
190 1. The model (the validations, etc)
191 2. The session (finding the record)
192 3. The cookies (the names of the session key and cookie)
193
194 I will describe each below, in order.
195
196 === Scoping your model
197
198 This scopes your login field validation, so that users are allowed to have the same login, just not in the same account.
199
200 # app/models/user.rb
201 class User < ActiveRecord::Base
202 acts_as_authentic :scope => :account_id
203 end
204
205 === Scoping your session
206
2479aa0 @binarylogic Allow for login_count to be nil and initialize with 1
authored Nov 3, 2008
207 When the session tries to validate it searches for a record. You want to scope that search. No problem...
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
208
209 The goal of Authlogic was to not try and introduce anything new. As a result I came up with:
210
211 @account.user_sessions.find
212 @account.user_sessions.create
213 @account.user_sessions.build
214 # ... etc
215
216 This works just like ActiveRecord, so it should come natural. Here is how you get this functionality:
217
218 class Account < ActiveRecord::Base
219 authenticates_many :user_sessions
220 end
221
222 === Scoping cookies
223
2479aa0 @binarylogic Allow for login_count to be nil and initialize with 1
authored Nov 3, 2008
224 What's neat about cookies is that if you use sub domains they automatically scope their self. Meaning if you create a cookie in whatever.yourdomain.com it will not exist in another.yourdomain.com. So if you are using subdomains to scope your users, you don't have to do anything.
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
225
2479aa0 @binarylogic Allow for login_count to be nil and initialize with 1
authored Nov 3, 2008
226 But what if you *don't* want to separate your cookies by subdomains? You can accomplish this by doing:
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
227
228 ActionController::Base.session_options[:session_domain] = ‘.mydomain.com’
229
230 If for some reason the above doesn't work for you, do some simple Google searches. There are a million blog posts on this.
231
232 Now let's look at this from the other angle. What if you are *NOT* using subdomains, but still want to separate cookies for each account. Simple, set the :scope_cookies option for authenticate_many:
233
234 class Account < ActiveRecord::Base
235 authenticates_many :user_sessions, :scope_cookies => true
236 end
237
238 Done, Authlogic will give each cookie a unique name depending on the account.
239
2479aa0 @binarylogic Allow for login_count to be nil and initialize with 1
authored Nov 3, 2008
240 With the above information you should be able to scope your sessions any way you want. Just mix and match the tools above to accomplish this. Also check out the documentation on Authlogic::ActiveRecord::AuthenticatesMany.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
241
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
242 == Errors
243
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
244 The errors in Authlogic work JUST LIKE ActiveRecord. In fact, it uses the exact same ActiveRecord errors class. Use it the same way:
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
245
246 class UserSession
247 before_validation :check_if_awesome
248
249 private
250 def check_if_awesome
251 errors.add(:login, "must contain awesome") if login && !login.include?("awesome")
252 errors.add_to_base("You must be awesome to log in") unless record.awesome?
253 end
254 end
255
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
256 == Automatic Session Updating
257
4b1f8fa @binarylogic User column_names instead of colums when determining if a column exists
authored Oct 29, 2008
258 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.
718f2cf @binarylogic Updated readme on session updating
authored Oct 25, 2008
259
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
260 Just to clear up any confusion, Authlogic 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.
20fcb6f @binarylogic Bumped to Sha512
authored Oct 27, 2008
261
262 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.
718f2cf @binarylogic Updated readme on session updating
authored Oct 25, 2008
263
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
264 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 Authlogic can, and you can access Authlogic 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.
718f2cf @binarylogic Updated readme on session updating
authored Oct 25, 2008
265
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
266 Fear not, because the acts_as_authentic method you call in your model takes care of this for you, by adding an after_save 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.
718f2cf @binarylogic Updated readme on session updating
authored Oct 25, 2008
267
34b225c @binarylogic Updated readme
authored Oct 25, 2008
268 Here is basically how this is done....
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
269
34b225c @binarylogic Updated readme
authored Oct 25, 2008
270 class User < ActiveRecord::Base
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
271 after_save :maintain_sessions!
34b225c @binarylogic Updated readme
authored Oct 25, 2008
272 after_update :update_sessions!
273
274 private
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
275 def maintain_sessions!
276 # If we aren't logged in at all and the password was changed, go ahead and log the user in
277 # If we are logged in and the password has change, update the sessions
34b225c @binarylogic Updated readme
authored Oct 25, 2008
278 end
279 end
280
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
281 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. Just set :session_ids => nil when calling acts_as_authentic.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
282
283 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!
284
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
285 == Framework agnostic (Rails, Merb, etc.)
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
286
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
287 I designed Authlogic to be framework agnostic, meaning it doesn't care what framework you use it in. Right out of the box it supports rails and merb. I have not had the opportunity to use other frameworks, but the only thing stopping Authlogic from being used in other frameworks is a simple adapter. Check out controller_adapters/rails_adapter, or controller_adapters/merb_adapter.
288
289 Since pretty much all of the frameworks in ruby follow the Rack conventions, the code should be very similar across adapters. You're saying "but Ben, why not just hook into Rack and avoid the need for controller adapters all together?". It's not that simple, because rails doesn't inherit from the Rack::Request class, plus there are small differences between how rack is implemented in each framework. Authlogic has to hook into your controller with a before_filter anyways, so it can "activate" itself. Why not just use the controller object?
290
291 The point in all of this rambling is that implementing Authlogic is as simple as creating an adapter. I created both the rails and merb adapters in under 10 minutes. If you have an adapter you created and would like to add please let me know and I will add it into the source.
35f14ba @binarylogic Released v0.10.0
authored Oct 27, 2008
292
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
293 == How it works
294
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
295 Interested in how all of this all works? Basically a before_filter is automatically set in your controller which lets Authlogic know about the current controller object. This "activates" Authlogic and allows Authlogic to set sessions, cookies, login via basic http auth, etc. If you are using your framework in a multiple thread environment, don't worry. I kept that in mind and made this thread safe.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
296
77798f2 @binarylogic Updated installation guide
authored Oct 25, 2008
297 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.
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
298
b49258f @binarylogic Updated readme
authored Oct 28, 2008
299 == What's wrong with the current solutions?
2155477 @binarylogic Updated readme
authored Oct 28, 2008
300
301 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.
302
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
303 I don't necessarily think the current solutions are "wrong", nor am I saying Authlogic is the answer to your prayers. But, to me, the current solutions were lacking something. Here's what I came up with...
2155477 @binarylogic Updated readme
authored Oct 28, 2008
304
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
305 === Generators are messy
2155477 @binarylogic Updated readme
authored Oct 28, 2008
306
791f700 @binarylogic Released v1.0.0 (see changelog)
authored Nov 6, 2008
307 Generators have their place, and it is not to add authentication to an 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.
2155477 @binarylogic Updated readme
authored Oct 28, 2008
308
a03f931 @binarylogic Fix readme errors
authored Oct 31, 2008
309 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. You don't really have a choice either, because you can't ignore security updates.
2155477 @binarylogic Updated readme
authored Oct 28, 2008
310
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
311 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 Authlogic, 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.
832b7f0 @binarylogic Cleaned up readme
authored Oct 29, 2008
312
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
313 Lastly, there is a pattern here, why clutter up all of your applications with the same code over and over?
2155477 @binarylogic Updated readme
authored Oct 28, 2008
314
315 === Limited to a single authentication
316
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
317 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 Authlogic. Authlogic 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.
2155477 @binarylogic Updated readme
authored Oct 28, 2008
318
832b7f0 @binarylogic Cleaned up readme
authored Oct 29, 2008
319 === Too presumptuous
320
4d42802 @binarylogic Ignore invalid credential fields, dont raise an exception
authored Oct 29, 2008
321 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.
832b7f0 @binarylogic Cleaned up readme
authored Oct 29, 2008
322
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
323 === Disclaimer
324
43e849c @binarylogic Released v0.10.4
authored Nov 3, 2008
325 I am not trying to "bash" any other authentication solutions. These are just my opinions, formulate your own opinion. I released Authlogic because it has made my life easier and I enjoy using it, hopefully it does the same for you.
ec0eb78 @binarylogic Updated readme
authored Oct 31, 2008
326
1b98335 @binarylogic Initial commit
authored Oct 24, 2008
327
328 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.