<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Binary Logic &#187; tutorial</title>
	<atom:link href="http://www.binarylogic.com/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.binarylogic.com</link>
	<description>Ben Johnson's thoughts and programming techniques</description>
	<lastBuildDate>Sat, 23 Jan 2010 21:19:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Tutorial: Using OpenID with Authlogic</title>
		<link>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/</link>
		<comments>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 02:12:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Authlogic]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">0/2009/03/30/tutorial-using-openid-with-authlogic</guid>
		<description><![CDATA[Please note this tutorial is outdated and has been deleted, please see the official Authlogic OpenID addon, which makes OpenID integration extrmely easy. The content that used to be in this tutorial was for Authlogic 1.x and will not work properly with Authlogic 2.x.
]]></description>
			<content:encoded><![CDATA[<p><strong>Please note this tutorial is outdated and has been deleted, please see <a href="http://github.com/binarylogic/authlogic_openid">the official Authlogic OpenID addon</a>, which makes OpenID integration extrmely easy. The content that used to be in this tutorial was for Authlogic 1.x and will not work properly with Authlogic 2.x.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/11/21/tutorial-using-openid-with-authlogic/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Tutorial: Reset passwords with Authlogic the RESTful way</title>
		<link>http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/</link>
		<comments>http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/#comments</comments>
		<pubDate>Sun, 16 Nov 2008 15:19:00 +0000</pubDate>
		<dc:creator>benjohnson</dc:creator>
				<category><![CDATA[Authlogic]]></category>
		<category><![CDATA[passwords]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">0/2009/03/23/tutorial-reset-passwords-with-authlogic</guid>
		<description><![CDATA[I&#8217;ve been getting emails asking me how to reset passwords with Authlogic, or how to confirm accounts. In this tutorial I&#8217;ll cover resetting passwords, since it is more complex, but after reading this tutorial there is no reason why you couldn&#8217;t set up account confirmation as well. In fact, my next tutorial will cover just [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been getting emails asking me how to reset passwords with <a href="http://github.com/binarylogic/authlogic">Authlogic</a>, or how to confirm accounts. In this tutorial I&#8217;ll cover resetting passwords, since it is more complex, but after reading this tutorial there is no reason why you couldn&#8217;t set up account confirmation as well. In fact, my next tutorial will cover just that.</p>
<h2>What am I about to read?</h2>
<p>You are going to read a tutorial on how to reset passwords the RESTful way. I am going to pick up where I left off on the <a href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Authlogic basic setup tutorial</a>, so if you have not read that I highly recommend doing so.</p>
<p>Want to see it in action before you start? Check it out for yourself:</p>
<h3><a href="http://authlogic_example.binarylogic.com">A live example of this tutorial</a></h3>
<p>Before we begin, let me walk you through the basic process of resetting a password as I see it:</p>
<p><span id="more-133"></span></p>
<ol>
<li>A user requests a password reset</li>
<li>An email is sent to them with a link to reset their password</li>
<li>The user verifies their identity be using the link we emailed them</li>
<li>They are presented with a basic form to change their password</li>
<li>After they change their password we log them in, redirect them to their account, and expire the URL we just sent them</li>
</ol>
<p>That seems pretty simple, right? So let&#8217;s get started&#8230;</p>
<h2>Helpful links</h2>
<p>Before we start I want give you some helpful / related links:</p>
<ul>
<li><a href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Tutorial: Authlogic basic setup</a></li>
<li><a href="http://authlogic_example.binarylogic.com/">Live example of the this tutorial</a></li>
<li><a href="http://github.com/binarylogic/authlogic_example/tree/with-password-resets">Source code of this tutorial</a></li>
<li><a href="http://github.com/binarylogic/authlogic">Authlogic repository</a></li>
<li><a href="http://authlogic.rubyforge.org/">Authlogic documentation</a></li>
</ul>
<h2>1. Add in the reset_password_token and email fields</h2>
<p>I am going to pick up from the <a href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Authlogic basic setup tutorial</a>, so I am assuming you are familiar with Authlogic and the basic setup.</p>
<p>With this tutorial I am introducing a new field in your database called <strong>perishable_token</strong>. Authlogic will take care of maintaining this for you. Here is how:</p>
<ol>
<li>The token gets set to a unique value before validation, which constantly changes the token. The value is a &#8220;friendly&#8221; value, something like: 4LiXF7FiGUppIPubBPey, not as long or as hardcore as a Sha512 hash, so it doesn&#8217;t cause problems when emailed or copying and pasting into a browser.</li>
<li>After a session is successfully saved (aka logged in) the the token will be reset. This makes the email we sent them before no longer usable.</li>
</ol>
<p>Generate your migration:</p>
<pre>$ script/generate migration add_users_password_reset_fields</pre>
<p>Now update the migration:</p>
<pre name="code" class="ruby">
class AddUsersPasswordResetFields &lt; ActiveRecord::Migration
def self.up
add_column :users, :perishable_token, :string, :default =&gt; "", :null =&gt; false
add_column :users, :email, :string, :default =&gt; "", :null =&gt; false

add_index :users, :perishable_token
add_index :users, :email
end

def self.down
remove_column :users, :perishable_token
remove_column :users, :email
end
end
</pre>
<p>Migrate your database:</p>
<pre>$ rake db:migrate</pre>
<p>When adding the email field Authlogic will notice this and validate it for you, making sure the email is unique and a valid email address. If you wish to disable this just pass the :validate_email_field =&gt; false option to acts_as_authentic. You can also have it ignore the email field all together by passing the :email_field =&gt; nil option.</p>
<h2>2. Let users request a password reset</h2>
<p>We need to know if users lost their password, why not create another resource for this?</p>
<pre>$ script/generate controller password_resets</pre>
<p>Let&#8217;s fill out this controller with some actions (I will explain them below):</p>
<p>Now update your routes:</p>
<pre name="code" class="ruby">
# app/controllers/password_resets_controller.rb
class PasswordResetsController &lt; ApplicationController
def new
render
end

def create
@user = User.find_by_email(params[:email])
if @user
@user.deliver_password_reset_instructions!
flash[:notice] = "Instructions to reset your password have been emailed to you. " +
"Please check your email."
redirect_to root_url
else
flash[:notice] = "No user was found with that email address"
render :action =&gt; :new
end
end
end
</pre>
<p><strong>What did I just do?</strong></p>
<p>The deliver_password_reset_instructions! is a method I added, you can call it whatever you want. All that it does is reset the password reset token and send an email.</p>
<p>Here is what I did in my own application:</p>
<pre name="code" class="ruby">
# app/models/user.rb
class User &lt; ActiveRecord::Base
def deliver_password_reset_instructions!
reset_perishable_token!
Notifier.deliver_password_reset_instructions(self)
end
end
</pre>
<p>The reset_perishable_token! is a handy method Authlogic gives you. It basically resets the field to a unique &#8220;friendly&#8221; token and then saves the record.</p>
<p>My Notifier action looks like this:</p>
<pre name="code" class="ruby">
# app/models/notifier.rb
class Notifier &lt; ActionMailer::Base
default_url_options[:host] = "authlogic_example.binarylogic.com"

def password_reset_instructions(user)
subject       "Password Reset Instructions"
from          "Binary Logic Notifier "
recipients    user.email
sent_on       Time.now
body          :edit_password_reset_url =&gt; edit_password_reset_url(user.perishable_token)
end
end
</pre>
<p>Then the email looks like:</p>
<pre name="code" class="ruby">
# app/views/notifier/password_reset_instructions.erb
A request to reset your password has been made.
If you did not make this request, simply ignore this email.
If you did make this request just click the link below:

If the above URL does not work try copying and pasting it into your browser.
If you continue to have problem please feel free to contact us.
</pre>
<p>You can do the above any way you want. I actually recommend creating a text and html version of this email, but for the sake of brevity I only included the text version.</p>
<h2>3. Let users reset their password</h2>
<p>Once they get that email and click the link in it, it needs to take them somewhere. So let&#8217;s add some methods to our PasswordResetsController:</p>
<pre name="code" class="ruby">
# app/controllers/password_resets_controller.rb
before_filter :load_user_using_perishable_token, :only =&gt; [:edit, :update]

def edit
render
end

def update
@user.password = params[:user][:password]
@user.password_confirmation = params[:user][: password_confirmation]
if @user.save
flash[:notice] = "Password successfully updated"
redirect_to account_url
else
render :action =&gt; :edit
end
end

private
def load_user_using_perishable_token
@user = User.find_using_perishable_token(params[:id])
unless @user
flash[:notice] = "We're sorry, but we could not locate your account. " +
"If you are having issues try copying and pasting the URL " +
"from your email into your browser or restarting the " +
"reset password process."
redirect_to root_url
end
end
</pre>
<p><strong>What did I just do?</strong></p>
<ol>
<li>You really don&#8217;t need to add the edit method because its a blank method, the before_filter takes care of everything we need to do there. There is only a view for this method.</li>
<li>The update method is nice, because if the user is successfully saved, Authlogic will automatically log them in, keeping your PasswordResetsController focused on resetting passwords, not sessions.</li>
<li>The load_user_using_perishable_token has a unique method: find_using_perishable_token. This is a special method that Authlogic gives you. Here is what it does for extra security:
<ol>
<li>Ignores blank tokens</li>
<li>Only finds records that match the token and have an updated_at (if present) value that is not older than 10 minutes. This way, if someone gets the data in your database any valid perishable tokens will expire in 10 minutes. Chances are they will expire quicker because the token is changing during user activity as well.</li>
</ol>
</li>
</ol>
<h2>4. Restrict access</h2>
<p>Now we just need to make sure the user is logged out when accessing these methods. Modify your before filters in your PasswordResetsController to look like:</p>
<pre name="code" class="ruby">
before_filter :require_no_user
</pre>
<h2>Where are the views?</h2>
<p>Instead of cluttering up this tutorial with a bunch of basic views, I left them out. There is nothing crazy going on in the views, nor do I really need to explain anything. If you noticed in the helpful links section I have a live example of this tutorial.</p>
<p><a href="http://github.com/binarylogic/authlogic_example/tree/with-password-resets/app/views">Here is a direct link to the users views source code, you can copy the views over from here</a></p>
<h2>Why not reset passwords this way&#8230;?</h2>
<p>If you care, here are my thoughts behind this tutorial and ultimately why I recommend resetting passwords this way&#8230;</p>
<p>My goal with Authlogic was to stay away from generating code and give you the proper tools so that you could easily and effectively write the code yourself. If you noticed, in this tutorial, all that we really did was add a simple PasswordResetsController. Most of this tutorial was explaining what was going on, so you could understand what you were doing. I can&#8217;t write that controller for you, because it is application specific. I want to keep the authentication logic in Authlogic and your application logic in your application. The tutorial above produces simpler and cleaner code than a generator. The most important part is that you understand what is going on and it works the way you want. I am basically laying out tools for you to use and explaining them. You get to use them how you wish. There is no &#8220;Surprise! Here are hundreds of lines of code, hope you like it&#8221;. If you want to change passwords a different way, go for it, you now know how Authlogic can assist you in your journey to resetting passwords.</p>
<p>Lastly, I know there are a few other common ways to reset passwords, so I will address those and why I decided against them:</p>
<ol>
<li><strong>Changing / randomizing the password during the first step and then emailing them their new password</strong><br />
You should NEVER change anyone&#8217;s password until they have proven they are that user. What if Billy 13 year old starts typing in random logins and resetting peoples passwords? Those people aren&#8217;t going to be happy.</li>
<li><strong>Using an already existing token that is not unique or perishable</strong><br />
A lot of people are tempted to use the remember_token, single_access_token, or even the crypted_password for authenticating the user for a password change. There is a reason we have all of these and none of these should be used for resetting password. What if Billy 13 year old gets ahold of any of these, he will have full access to resetting that user&#8217;s password, and then have full access to their account. If for some reason he gets any of these things, your users should still be protected, which is why we need a unique and perishable token.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
	</channel>
</rss>
