Converting a Rails App: Omniath CAS

Configuring Devise with CAS in my Rails application was as simple as install the devise gem, running the generator and then adding config.omniauth :cas, host: "...", url: "..." to my devise configuration. Then I had to implement a call back and I was “done”. Devise did most of the rest of the lift.

In Hanami I was still able to utilize the same Omniath cas gem. It took me a bit to figure out all the correct configuration, so I thought I would put it out here for other folks.

I had to configure the gem as middleware. I missed adding Warden first and it took me a bit to find the syntax to provide the provider variables.

# config/application.rb
config.middleware.use Warden::Manager
config.middleware.use OmniAuth::Builder do
   provider :cas, host: Hanami.app.settings.cas_host, url: Hanami.app.settings.cas_url
end

I had to make sure to include my callback location (and service url) when I redirecting to the CAS server.

# app/actions/sessions/new
          OmniAuth.strategies.first.configure(host: Hanami.app.settings.cas_host, url: Hanami.app.settings.cas_url)
          omniauth_strategy = OmniAuth.strategies.first.new(Hanami.app)
          service_url = omniauth_strategy.append_params(routes.url(:auth_callback, provider: 'cas'),
                                                        { url: request.referer })
          omniauth_strategy.login_url(service_url)

And then finally I got back the same token that I had in my rails application so I could parse it and know who is logged in. This code was copied directly from my rails application.

# app/actions/session/create
          auth_hash = request.env['omniauth.auth']
          user = user_repo.from_cas(auth_hash)

Next, I put the current_user method in the base action and exposed it in the base view so I could show the logged in user in my main menu bar.

# app/action.rb
    before :current_user

    def current_user(request, response)
      if request.env['warden']
        response[:current_user] = user_repo.find_by_uid(request.env['warden'].user)
      end
    end
# app/view
 expose :current_user, layout: true

I will also have to check that the user is present for each action that requires a login and redirect to my session/new action if needed, but accessing single sign on and knowing who is logged in was a huge step!

4 Likes

Hi All!
I realized I was missing some automation that Omniauth included in the above post.

If you add get to allowed_request_methods then Omniauth will intercept get requests to /auth/cas and you did not need the session.new action. session.new had some complex code I did not love and didn’t really want to maintain. Luckily for me it can be removed.

# config/app.rb
OmniAuth.config.allowed_request_methods = %i[get post]

All my login links then needed to link to 'auth/cas' as the href location

 <%= link_to("Log-in", '/auth/cas',id: "login-button", class: "button" %>

On a side note, I tried to utilize post and I got some browsers that redirected correctly and others that did not. Firefox was the one that redirected consistently and Chrome did not for the posts to /auth/cas. In the browsers that did not redirect it looked entirely like omniauth was doing nothing until I looked at the network traffic and saw the 301 response with the correct url.