views:

374

answers:

1

I'm using the casrack-the-authenticator gem for CAS authentication. My server is running Thin on top of Sinatra. I've gotten the CAS authentication bit working, but I'm not sure how to tell Rack to intercept "/index.html" requests to confirm the CAS login, and if the user is not allowed to view the page, return a HTTP 403 response instead of serving the actual page. Does anyone have experience with this? Thanks.

My app:

class Foo < Sinatra::Base
    enable :sessions
    set :public, "public"
    use CasrackTheAuthenticator::Simple, :cas_server => "https://my.cas_server.com"
    use CasrackTheAuthenticator::RequireCAS

    get '/' do
        puts "Hello World"
    end
end

My rackup file:

require 'foo'

use Rack::CommonLogger
use Rack::Lint

run Foo

Initial attempt at getting Rack to understand authentication in its file service (comments and thoughts welcome):

builder = Rack::Builder.new do
    map '/foo/index.html' do
        run Proc.new { |env|
            user = Rack::Request.new(env).session[CasrackTheAuthenticator::USERNAME_PARAM]
            [401, { "Content-Type" => "text/html" }, "CAS Authentication Required"] unless user
            # Serve index.html because we detected user
         }
    end

    map '/foo' do
        run Foo
    end
end

run builder
+1  A: 

Casrack-the-Authenticator will put the CAS information into the Rack session. You can pull that out in another piece of Rack middleware or in your Sinatra app.

The following is for a Rails application, but the concept is similar for Sinatra or a Rack middleware:

# in app/controllers/application_controller.rb:
protected

def require_sign_in!
  render :nothing => true, :status => 403 unless signed_in?
end

def signed_in?
  current_user.present?
end

def current_user
  @current_user ||= Person.find_by_username(session[CasrackTheAuthenticator::USERNAME_PARAM])
end
James A. Rosen
Thanks for the info, that piece of code makes sense. What I'm not sure of is the Rack equivalent of hooking into the static content server. My JSON requests from the browser are being rejected properly, for example, but the static file service seems to be bypassing my Sinatra application and providing index.html anyway.
Kenny Peng
Are you using `Rack::Static`? If so, is it behind the Casrack middleware? Perhaps showing your rackup file would help.
James A. Rosen
I wasn't using `Rack::Static` before. I actually put casrack into my class that extends Sinatra::Base, because for some reason, I couldn't have it in my rackup and have it work with `enable :sessions` (I probably missed a simple syntax or configuration option, though). I posted basically what my rackup and Sinatra app currently look like.
Kenny Peng
I think the problem with the sessions is that Casrack needs sessions enabled before it runs, so you can't put it outside Sinatra. Would it be possible to use Rack::Session::Cookie instead of Sinatra's version?
James A. Rosen
Sure, I can try that. The session management section is less important than the static content redirection for 403 responses. I'm posting what I have in the main section as an initial shot at hooking into the Rack server.
Kenny Peng