padrino/padrino-framework — Issue #717: Session cleared unexpectedly when using Omniauth
Author: mutewinter
Created: 2011-11-09 00:10:07+00:00
State: open

### My Setup

I'm trying to setup a basic GitHub login with [OmniAuth 1.0](https://github.com/intridea/omniauth). I am using the [omniauth-github](https://github.com/intridea/omniauth-github) strategy.

I direct the user to login with GitHub with the following code.

``` ruby
= link_to 'Login with GitHub', '/auth/github'
```

When they accept the new application on GitHub it redirects them back to `/auth/github/callback`. Here is the controller method that is being called at that point:

``` ruby
get :auth, :map => '/auth/:provider/callback' do
auth = request.env["omniauth.auth"]
@account = Account.first(:uid => auth['uid'], :provider => auth['provider']) ||
Account.create_with_omniauth(auth)

if @account.saved?
flash[:success] = "Logged in as #{@account.username}"
session[:account_id] = @account.id

redirect url(:account, :show, :id => account.id)
else
if @account.errors
flash[:error] = "Failed to login to GitHub"
end
redirect '/'
end
end
```

### The Problem

This code works fine to direct the user to their account page. However, the session is clobbered as soon as the redirect takes place. This means that the user ends up on the account page _without_ `:account_id` set in their session. When the next page is loaded, a new cookie `session_id` is generated by the application and none of their session data is persisted.

### Things I Have Tried

* The first thing I discovered was that OmniAuth is known to clobber the session after a POST request according to the [OmniAuth FAQ](https://github.com/intridea/omniauth/wiki/FAQ). However, I was unable to locate the Padrino equivalent of Rails' `protect_from_forgery` method.

* Next, I investigated the possibility that [rack-protection](https://github.com/rkh/rack-protection) being [included by Sinatra 1.3](http://www.padrinorb.com/blog/padrino-0-10-3-sinatra-1-3-documentation-minitest-improved-logger-and-more) was causing the session to be cleared by a cross-site POST. However, I discovered that rack-protection isn't setup by default for Padrino, and therefore not the problem.

* I tried switching my `redirect url(:account, :show, :id => account.id)` to a render method. That worked to show a _single_ page containing the right session information. However, as soon as the user navigates to a different page, the session is revealed to have already been cleared (or is cleared by the navigation away from this page, I'm not sure which).

I'm stumped as to what might be causing the session to be cleared. I am going to write a simple Sinatra application to test my code outside of Padrino to verify that this isn't a Sinatra bug next.