Archive for February 2009


Ruby on Rails and NTLM Authentication

February 24th, 2009 — 4:48pm

I had an interesting task at work. I needed to integrate NTLM Authentication into a Ruby on Rails application. Now on the face of it this sounded like a nightmare. Immediately thoughts of running Rails on IIS go through my mind. Bleh. Well, it turns out not to be that bad. But pretty damn close.

But add to the circumstance that this Rails app won’t run on Windows. It will run on RedHat Enterprise Linux through IBM WebSphere. Now the task becomes very interesting. Now this is a JRuby on Rails application and there won’t be a Windows box in sight. You have 16hrs … go!

So doing research I found out just what exactly NTLM is and how it works. It’s not magic at all really. It’s a simple handshake between server and browser using some HTTP headers to send back and forth.

Here are the steps. This is a very brief overview with no details. I will follow this with some code to provide a rough example. In the following steps “client” means your browser and “server” means the Rails application (specifically a before_filter in application controller).

  1. Client requests home page. GET / HTTP/1.1
  2. Server receives request and inspects headers for “Authorization” key.
  3. Server finds no request header with the key “Authorization” and builds a response with the header “WWW-Authenticate” with a value of “NTLM”. It returns this with a status of 401.
  4. Client receives this response and because of the 401 status and the “WWW-Authenticate” header value of “NTLM” it prepares a “Authorization” header value of “NTLM XXXXXXXXXXX” where “XXXXXXXXX” is a Base 64 encoded bit structure of information for the server. It then requests the home page again with this added header. This is the Type 1 message.
  5. Server receives this second request and finds the “Authorization” header and parses it’s value. It then prepares a “WWW-Authenticate” header with a value “NTLM XXXXXXX” where “XXXXXX” is a Base 64 encoded challenge. It returns this to the client with a 401 status. This is the Type 2 message.
  6. Client receives this response, recognizing the 401 and the NTLM challenge and it prompts the user with a login dialog. NOTE: Internet Explorer and properly configured FireFox browsers will not prompt the user and simply pass along the information due to NTLM integration.
  7. Client requests home page again, now with the “Authorization” header set with a “NTLM XXXXXXXXXXXX” value where “XXXXXXXX” is a Base 64 encoded bit structure populated with information from user dialog.
  8. Server receives this third request, recognizes the challenge response, parses the bit structure and finds the username, password, remote host and domain information of the user. This is the Type 3 message.
  9. With all of this information the Server can then authentication and authorize the user to the resource originally requested.

This all happens behind the scenes invisible to the user. All 9 steps look like 1 web request to the user. This is because the browser and server utilize Keep-Alive statuses of the Connection. Also recognize that in step 8 & 9 the user is NOT AUTHENTICATED. I repeat – this is not a complete authentication example, just an overview of the steps involved.

Notice however that in all the steps there is nothing that the Rails application can’t do itself. Meaning there isn’t a need for the server to do anything to the response/request cycle. Rails can manage all of this, notwithstanding the actual authenticating to a Windows domain. Here is some psuedo code to demonstrate.

class ApplicationController < ActionController::Base

  before_filter :authenticate

  def authenticate
    if request.headers["Authorization"].blank?
	  headers["WWW-Authenticate"] = "NTLM"
	  render :inline => "NTLM Auth !!", :status => 401, :layout => false
    else
	  # grab the request.headers["Authorization"] value
	  # and parse it. maybe create a class to do this and expose
	  # the message type property of the value
	  ntlm = NtlmAuthentication.new(request.headers["Authorization"])
      if ntlm.message_type == 1
	    headers["WWW-Authenticate"] = message # message is the base 64 encoded challenge
	    render :inline => "NTLM Auth Challenge !!", :status => 401, :layout => false
      elsif ntlm.message_type == 3
	# now within the ntlm message you have the user/domain/remotehost/password
        # with which you can authenticate/authorize ntlm.user_name, ntlm.password
      end
     end
  end
end

There are a ton of things missing from the example above but it hits the major steps. In particular the actual parsing of the Base 64 header value is not demonstrated. It is a bit structure that is quite gnarly (at least to me). I ended up using Java to encode/decode it and it worked out pretty nicely. This parsing step could be a post all by itself. And I think it will be!

My solution worked. But after implementing it to WebSphere there was a funny behavior. If IHS was used in front of the app server, IE would fail to finish the NTLM handshake. If IHS was not used and the request goes straight to the app server – all is well. Still debugging this one.

3 comments » | Code

Major downside to VB

February 19th, 2009 — 2:21pm

In this article the author makes the following statement (emphasis mine):

The major downside of using VB and XML Literals is that you lose IntelliSense support for HTML and JavaScript.

Hmm. Seems to me he is missing a few more major downsides. But I digress.

This topic of IntelliSense is what literally drove me out of the Microsoft .NET world of programming. In that world developers needed IntelliSense. Without it they couldn’t write code. They didn’t know the framework libraries well enough to type by hand and worse: their code probably wouldn’t compile because of this due to typos and format issues.

The irony of it all is that I think the Microsoft Visual Studio products are some of the best in the world. They have to be. How else could you explain the effect of developers not knowing how to write code by hand? Easy – Visual Studio did all the work.

The major downside to using VB in the context of the article is not losing IntelliSense. The downside is that the language has raised millions of developers who depend on VB tools to build software for them.

And these are the developers whom you hear clamoring for IDEs in their new language of choice. When you meet one, ask them why. 5 times. IntelliSense is always the last answer.

Comment » | Code

REST, _method, PUT and Rack::MethodOverride

February 14th, 2009 — 6:27pm

In my Siffer project I’m building a website that will manage the entire Siffer installation. This website is simple in that it doesn’t really manage many things. Some Zone Integration Servers, their Agents and the list of Data Models outlined in the SIF documentation. It has some viewing capabilities into the ZIS and Agents, to monitor their activity and see the messages going through. But most of that functionality will be handled in those separate components. The main administration site will simply create, read, update and delete ZIS and Agents.

In choosing a framework to build this site I first chose Rails. But almost immediately I realized that it was too heavy. I wanted this administration site to ship with the Ruby gem and not be a separate piece. Which in turn, I didn’t want it to be very big at all. Rails was bloat. So I went looking for a micro-framework and found Sinatra. I heart Sinatra. But that’s not what I’m posting about today.

Building the site and using REST was going along smoothly. Until I started writing my routes and actions to update the ZIS. My PUT methods weren’t being hit. Sinatra was throwing exceptions (love this one BTW: “Sinatra doesn’t know this ditty”). I checked everything.

I had a hidden element named “_method” with a value of “PUT”.

<input type="hidden" name="_method" value="PUT"/>

I had a method like the following:

put "/servers/:id" do
  @server = Database::Models::Server[params[:id]]
  begin
    @server.update(params[:server])
    redirect "/servers"
  rescue
    haml :'servers/edit'
  end
end

I couldn’t understand it. I followed the documentation to the letter. I am familiar with this little pattern from Rails and yet I just couldn’t figure it out. I even made a quick Sinatra application with this:

require 'rubygems'
require 'sinatra'
get "/" do
  body = <<EOF
<form action="/putup/28" method="post">
<input type="hidden" value="PUT" name="_method"/>
<input type="text" name="tester" id="tester"/>
<input type="submit" value="Putter"/>
</form>
EOF
end
put "/putup/:id" do
  body = "Got Putup!#{params[:id]}"
end

And that works! Man – sometimes I just feel hopeless. My site is only different in that I’m not using the single file pattern, rather I’m using Sinatra::Application and then setting up a Rack::Builder object to run it. But it should be the same. I spent an hour reading the Sinatra code. It’s the same.

Doh! But it’s not. And it’s my fault.

It turned out I wasn’t using a very critical piece of middleware if I wanted to have my “_method” field read and change a “POST” method to a “PUT” method. That would be Rack::MethodOverride. Hmmm. Too obvious? Well it wasn’t for me at the time. And ironically this is one of the beauties of Rack. I’m turning into a big Rack zealot. All problems are starting to look like Rack solutions. I need to be careful.

Now that I have included that in my Rack::Builder all is right.

Sidebar: If you haven’t yet looked at Sinatra you really should. It’s a pleasure to work with. Sinatra with Sequel is the bees knees.

3 comments » | Code

Back to top