Posts Tagged ‘authlogic’

Redirecting to a secure subdomain with Authlogic

Monday, April 19th, 2010

In my application, I wanted to redirect my users from my domain to https://secure.mydomain.com for checkout, so their credit card info would be transmitted securely.

Unfortunately, if I just do a simple redirect, the user gets logged out, because Authlogic (and maybe the cookies themselves?) only work on a per-domain basis.

There are various ways to do this, including having Authlogic authenticate for your whole domain, and not just the one subdomain, but the solution I chose is to use Authlogic’s single use tokens. This just means, I get a token that can sign the user in one time, and I pass the user with that token to my secure domain.

Here’s the relevant bits of my controller:

class CheckoutController < ApplicationController
  before_filter :require_user, :except => [:with_authentication]
 
  def index
    if RAILS_ENV == 'production' && !request.ssl?
      domain = "https://secure.mydomain.com"
      token = Authlogic::Random.friendly_token
      current_user.update_attributes(:single_access_token => token)
      redirect_to "#{domain}/checkout/with_authentication?user_credentials=#{token}"
    else
  end
 
  def with_authentication
    user = User.find_by_single_access_token(params[:user_credentials])
    session = UserSession.new(user)
    session.save
    redirect_to '/checkout'
  end
end

I also had to add the single_use_token field to my users table:

script/generate migration add_single_access_token_to_users single_access_token:string
rake db:migrate

What happens now is if a user goes to /checkout and they’re not using SSL, they get redirected to something like http://secure.mydomain.com/checkout/with_authentication?user_credentials=fh3f83ahfa92ha, which authenticates them and creates a new session on the secure subdomain. Then it redirects them to /checkout on that domain.

The one thing that wasn’t very well explained on The Google is how you get the single use token in the first place. The docs explain how to use it, but now how to create it. As you see above, you just have to generate a random one with Authlogic::Random.friendly_token and then stick it in your user model.

Seems to work ok.

One of the other issues is that this totally screws up your Cucumber features. Cucumber basically expects you to stay on one domain. There are some good suggestions on the Rspec mailing list for getting around this, but I ultimately chose the hacky, ugly solution of just selectively redirecting when we’re in the production environment. It didn’t seem worth it to do it the right way… especially given that the “right” ways aren’t all that much prettier.

Keywords: login to multiple subdomains, cucumber ssl redirect, https

Conditional validation with Authlogic

Tuesday, March 30th, 2010

Update: I ended up abandoning this method because on further testing it wasn’t working ask I had hoped. I basically used Kevin Triplett’s method in the end after all. There are some subtleties to AuthLogic and the way it interprets the :unless parameter that make that method a pretty reliable way to go.

I’ll leave the original post here, but it’s out of date:


On my site, I let visitors start using the site right away, without creating a username and password. In order to do this, I loosen the validation on my Authlogic User model so that it doesn’t require the username and password:

class User < ActiveRecord::Base
  acts_as_authentic do |c|
    c.validate_login_field = false
    c.validate_password_field = false
    c.validate_email_field = false
  end
end

The trouble is, when these users move on to signing up, I want to start validating those fields. It took some head scratching, but I found it works just to have an active? method that knows whether the user is (trying to become) active, and thenupdate those config vars conditionally before validating:

class User < ActiveRecord::Base
  acts_as_authentic
  before_validation :update_authlogic_config
 
  def update_authlogic_config
    validate_login_field = active?
    validate_password_field = active?
    validate_email_field = active?
  end
end

Works like a charm.

Stubbing Authlogic’s current_user in specs

Wednesday, March 10th, 2010

I’m using Rspec to test my app, and I’m doing integration tests where I want to be able to stub the currrent user. There’s supposedly a set_session_for(user) helper, but it didn’t work for me. Stubbing it by hand was easy enough though:

UserSession.stub!(:find).and_return(mock_model(UserSession, :user => user))