I've been flirting with Adobe AIR and decided to build an AIR AJAX-
based client for my Heroku app (http://poetry.heroku.com).  The client
would be used to write poems and an AJAX request would call create.  I
ran in to some trouble, however.  I had a very hard time finding
documentation on authenticating with AJAX, and then once I solved that
problem I had some issues with acts_as_authenticated not handling the
authentication.  Here are some tips, in case you attempt to go through
the same pain.

If you know better ways to do this, I'm all ears.  I Googled for
hours.

Step 1 - Basic HTTP Authentication in AJAX

Note: this is an AIR app, but AIR pretty much just lets you do
straight HTML and javascript so this is un-molested Prototype.  You
need to install JS to do base64 encoding.  Check out
http://coderseye.com/2007/how-to-do-http-basic-auth-in-ajax.html.

<script src="lib/webtoolkit.base64.js" type="text/javascript"></
script>

function make_base_auth(username, password)
{
        var tok = username + ':' + password;
        var hash = Base64.encode(tok);
        return "Basic " + hash;
}

Then, you need to add an Authorization header to your requestHeaders
parameters in the Ajax.Request Prototype call.

requestHeaders: {
        Accept: "application/xml",
        Authorization: make_base_auth('username', 'password')
},

Step 2 - Controller XHR? Check

The parameter style from the AJAX request differs from my form
submission.  I can probably improve this so the check is unnecessary
but watch out for cases where your AJAX request does not provide
sufficient parameters compared to your normal forms.

if request.xhr?
      @poem = Poem.new
      params[:title].empty? ? @poem.title = 'Untitled' : @poem.title =
params[:title]
      @poem.body = params[:body]
      @poem.user = current_user
else
      @poem = Poem.new(params[:poem])
end

Also, I had to unprotect the controller from forgery because of the
authenticity token.  I've heard that protect_from_forgery only works
against very weak forgery attempts, so I'm not too upset about this.

protect_from_forgery :except => :create

Step 3 - Modify Acts_As_Authenticated

I had to change the login_required filter to recognize the xhr and use
basic authentication, which is what the AJAX call provides.  Notice
that I check not only for xhr but also for the specific controller and
action because I don't want to mess up the login behavior for any
other xhr I use in my app (like tagging, comments, etc.).

def login_required
      if request.xhr? && (request.request_uri == '/poems/create')
        self.current_user = authenticate_with_http_basic { |u, p|
User.authenticate(u, p) || :false if u && p }
        logged_in? && authorized? ? true : access_denied
      else
        username, passwd = get_auth_data
        self.current_user ||= User.authenticate(username, passwd)
|| :false if username && passwd
        logged_in? && authorized? ? true : access_denied
      end
end

I also added another format to access_denied to handle javascript.
Not sure if this helps or not, but saw it recommended on a website.
I'll need to revisit this to make sure I'm handling errors as best as
I can.

accepts.js do
          render(:update) { |page| page.redirect_to(:controller => '/
account', :action => 'login') }
end



Hope all this helps you one day.  I like AIR, so I hope to get in to
more of this.  Using my (meager) HTML and JS skills to build proper
desktop apps with self-upgrade capabilities and other niceties is...
nice.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Heroku" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/heroku?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to