Saturday, 27 March 2010

Authlogic, custom logins and persisting sessions

If you haven't used the authlogic plugin for authentication, you're possibly missing a trick. It's a great piece of code.

However, it's poorly documented for anything out of the well trodden path. Which is a pity because it's so powerful.

Authlogic makes assumptions about how your login facility will work. In particular, it assumes that you will have a login and a password. Which, for more enterprise applications and larger web services, fall short of the mark. Most larger services need a three-way, not two-way authentication. Typically it is customerID, user ID and password. Meaning that user IDs are not unique across customers. Which makes sense given that for most markets, different clients will have the same usernames (e.g. admin, sales, info, etc).

This means that to use authlogic, you need to extend it to use your additional fields.

The easy way to do this is to extend your UserSession class by adding an accessor. For example, we use a company short name as a company ID, so in our case, it's:

class UserSession < Authlogic::Session::Base

attr_accessor :company_sname # Adds company ID to the default Authlogic session fields because this isn't there in standard Authlogic

end

This in turn means that you have to now modify your user_sessions_controller so that you make your logins company-aware:
class UserSessionsController < ApplicationController
  before_filter :require_no_user, :only => [:new, :create]
  before_filter :require_user, :only => :destroy
  protect_from_forgery :except => [:create]

  def index
      render :action => :new
  end

  def new
  end

  def create
    @prevCompSname=params[:user_session]["company_sname"] || ""
    company=Company.find(:all,:conditions => ["lower(short_name) = lower(?)",@prevCompSname]).first
    $companyID=(company&&company.id)||0

    if $companyID > 0
      @user_session = UserSession.new(params[:user_session])
      if @user_session.save
        flash[:notice] = "Login successful!"

        @user_session.user.reset_persistence_token!
        @user_session.save
           
        redirect_to '/mycontroller'
      else
        flash[:error] = "Login failed!"
        redirect_to :action => :show, :controller => :failure_page
      end
    else
      flash[:error] = "Login failed!"
      redirect_to :action => :show, :controller => :failure_page
    end
  end

  def destroy
    current_user_session.destroy
    flash[:notice] = "Logout successful!"
      render :action => :new
  end

end


Unfortunately, there is an obscure bug in authlogic that means that the persistence sometimes breaks. You end up with an attempt to select from your user table with perishable_token=1 instead of a string, which results in an SQL error and the login failing.

Some people have found work-arounds to this by unpacking the gem. However, a more reliable fix that we found was to simply explicitly call the method to force a persistent token in the User model:

@user_session.user.reset_persistence_token!

and then to make sure that this persistence token is saved for the sesssion, you have to call the session save:
@user_session.save

This then gives you a persistence token that is saved across the sessions as it should be.

Thursday, 4 March 2010

Working with Postgres views, Rails models and user-based security

So the biggest flaw in Rails at the moment is the fact that it assumes logging in with full application privileges to the database. This has many holes in it but the huge chasm, the barn door in terms of security breaches is that your data, potentially private data, is seriously at risk.

As awesome as Rails is, it cannot guarantee you that you will not make a mistake. One unfortunate bug that fails to implement user-based filtering of data and the wonders of Rails' ActiveRecord quickly becomes that proverbial thread on the thorn... the jumper unravels very quickly and the data security breach slide becomes an avalanche.

That is why database technology, since the mid 1900s, has had user-based security built into it. Users should be accessing data through views and updates should be made through triggers and rules. Your application should not be accessing the raw, underlying table. Postgres, Oracle, Ingres, DB2 and other "enterprise" databases all have a long track record of implementing these facilities. In fact, it would be a very foolhardy IT manager that sanctions the use of a database that doesn't have these services.

The correct place for data security to reside is within the database. Implementing this in the application is a highly insecure practice (a discussion worthy of several blog posts in its own right). Not only is leaving security up to the application insecure, it also introduces the very serious risk of bugs and "forgetting" to implement security during the natural maintenance lifecycle of the application. In addition to this, every application needs to implement the same security features for the same database, something that flies in the face of Rail's DRY principle and drives up the cost, complexity and maintenance overhead of the security system exponentially. For example, tweaking just one security rule forces an update, test, release cycle for every single application using that database.

The correct database implementation for data security within the database follows this pattern:

1) The DBA account owns the tables and has read/write/update/delete access to these tables. Specifically, the user accounts do not have any CRUD permissions on the underlying tables.
2) The DBA account creates views, rules and triggers on the tables. These have built in security and data filtering that restricts users to see only that data that they are entitled to see. User-based security for selects is implemented through views, user-based security for update, delete and insert functions is implemented through triggers and rules on the views.
3) The application logs in as a user account.
4) The DBA account grants only those permissions needed on each view/trigger to each user account required for the actions that the user in question has permissions to perform on that data.
5) The views restrict the user to just those rows (and columns) that they have permission to access. This is based on the user's login.
6) The triggers and rules ensure that the underlying data integrity is maintained, including the injection of security details (e.g. maintaining a user_id column or audit trail) where these are needed.

This approach radically simplifies the design and maintenance of real world web applications. It also reduces the risk of bugs and the introduction of security flaws through errors in application modifications and it provides a consistent enforcement of data integrity across all uses of the database, no matter how many applications use that database.

By maintaining a user_id column on each table, it is possible to write a generic view that restricts the user to only those rows that (s)he owns.

Take, for example, an accounting package. If you have the table salary that looks like this:

create table salary (
   id serial primary key,
   employee_name text,
   salary float,
   user_id int references users(id));

Obviously you would have a users table as well, for example:

create table users (
   id serial primary key,
   username text)

In the users table, the username column is the user's database account.

With the above salary table, you can could write a view to restrict user access to only "their" rows like this:

create view salary_vew as
  select s.id, s.employee_name, s.salary
  from salary s join users u on s.user_id=u.id
  where u.username::text = "current_user"()::text;

Thus, when the user selects from the salary_view, they will only see the rows containing their user_id. Note that we don't include the user_id in the view as this is part of the security system, not the application data.

Now, to implement insert, update or delete actions security, you need to implement rules on the view. This means that your application will be able to perform insert/update/delete actions on the view just as it would a normal table, with the rules system in Postgres implementing the actions on the real table (salary) with the added security constraints.

At this point, it's worth noting that this security model is very simple. In reality, security models can be complex beasts. For example, most companies have teams of people, i.e. user groups, who are able to access the same data, so restricting access by user_id is too simple. The views, rules and triggers will need to be group-aware and perform group lookups, allowing someone in the same group as the row "owner" to access that row with the same rights as the row owner.

This point highlights the power of this technique. Because the underlying security model can be modified and maintained independently of the applications that use the database as well as allowing for an implicit interaction between applications without needing to integrate them. For example, the company's HR system, which maintains who is employed in the company and what team they work in could be updating the group and user information held in the database as well as creating or deleting database accounts, independently of the applications that allow users to log in and work with the data in that database. Reporting systems can be implemented that report on data in the database, etc.

So far we have seen how to implement select-based security. And here are some examples of CRUD security.

For inserts, you would create an insert rule:
create or replace rule salary_ins as
  on INSERT to SALARY_VIEW
  DO INSTEAD
  INSERT INTO salary (id,employee_name,salary,user_id)
  SELECT nextval(salary_id_seq'), NEW.employee_name,NEW.salary,u.id
  FROM users u
  WHERE u.username::text = "current_user"()::text;

The above will create a rule that populates the user_id correctly based on the user's login. It does this by selecting the correct row of the users table. Thus, even if someone attempted to insert into the salary_view passing the user_id as a parameter, it would be ignored by the rule and the correct user_id will be used for that user's login. This means that attempts to breach the security system by spoofing other users is foiled. For example, if Jane creates a row that Pete should not have access to, but Jane attempts to pass Pete's user_id into the view in order to grant Pete access to that row, the attempt will be blocked at a database level.

The update view is very similar:

create or replace rule salary_upd as
  on UPDATE to SALARY_VIEW
  DO INSTEAD
  UPDATE salary s
  USING users u
  SET employee_name=NEW.employee_name,
          salary=NEW.salary

  SELECT nextval(salary_id_seq'), NEW.employee_name,NEW.salary,u.id
  WHERE u.username::text = "current_user"()::text
        AND s.user_id=u.id
        AND s.id=NEW.id;


NOTE: The last line of the where clause (AND s.id=NEW.id) has to be included as this tells Postgres to append all qualifiers that the application may have added to the update. If you did not include that line, then Postgres's rules system would simply throw away any application qualifiers resulting in ALL the rows owned by the user being updated! A rather catastrophic bug!

For example if the application issued thsi:
update salary_view set salary=100 where employee_name = 'Joe Smith';

Then with the last row of the view added, Postgres includes the the "where employee_name = 'Joe Smith'" qualifier with the update specified by the rule, but without the last row in the rule, then every single salary record that the user maintains will have the salary set to 100!

The delete rule is equally as simple:

create or replace rule salary_del as
  on DELETE to SALARY_VIEW
  DO INSTEAD
  DELETE FROM salary s
  WHERE u.username::text = "current_user"()::text
        AND s.user_id=u.id
        AND s.id=OLD.id;


Note that the Postgres data identifier OLD is used, as this is a delete, not an insert. The same comment about the last row (AND s.id=OLD.id) and its implications apply to this rule as described for update above.


Quirk in Rails' use of sequences

The above works well in a Rails application, except for the sequence that Postgres maintains for the id column of the salary table. Rails very sensibly calls currval once it has inserted a row into Postgres to discover what the value for id is for the newly inserted row. However, because the table name from Rails' point of view is salary_view, it will attempt to select currval('salary_view_id_seq') which, of course doesn't exist because Postgres would have created the sequence on the salary table as salary_id_seq.

The simplest way around this is to use salary_view_id_seq within the rules and Postgres rather than try and change Rails' default sequence name construction. To do this, you simply declare the id column as type int not serial:

create table salary (
   id int not null primary key,
   employee_name text,
   salary float,
   user_id int references users(id));

And then you create the sequence:
  create sequence salary_view_id_seq;

and tell Postgres to use this for the id value in that table:
  alter table salary alter column id set default nextval('salary_view_id_seq');

You may ask "why bother specifying the sequence for the underlying table if the insert rule populates id in insert anyway?". The reason is to ensure that DBA operations such as bulk copies into the table and any other (legitimate) inserts into the underlying base table will remain consistent with the "normal" inserts via the insert rule.

Of course, this also means that your insert rule needs to use this sequence:

create or replace rule salary_ins as
  on INSERT to SALARY_VIEW
  DO INSTEAD
  INSERT INTO salary (id,employee_name,salary,user_id)

  SELECT nextval(salary_view_id_seq'), NEW.employee_name,NEW.salary,u.id
  FROM users u
  WHERE u.username::text = "current_user"()::text;



Now you have a working security system that enables you to explicitly grant access to users, tweak the security model without application changes, simplify your application development, reduce the number of bugs and the risk of security compromises introduced by bugs and keep it DRY across all the applications and the direct database access!


Of course, you need to make your Rails application log in as the user which you can do using the establish_connection command in your models.


As we use the auth_logic plugin, we establish and the globals $dbuser and $dbpass during application login (which is done via a very restricted general account that has just enough permissions to enable auth_logic to do its stuff),


In our database.yml we define an entry app which looks like this:
app:
      host: localhost
      adapter: postgresql
      database: enterTheDbHere
      username: filledInAtRuntime
      password: filledInAtRuntime
      port: 5432


We then define a model class that our other models can inherit from:


# This class extends the normal Active Record to enable user-login database accounts to be used in the Models that are based on it.
# I.e. It allows us to implement database security and use views and triggers that base permissions on the user's database login

class UserLoginTable  < ActiveRecord::Base
  config = ActiveRecord::Base.configurations['app']

  config['username']=$dbuser
  config['password']=$dbpass

  establish_connection(config)
end


Our models that are based on views are now simple based on the above, for example:


class SalaryView < UserLoginTable
  set_table_name 'salary_view'
end


Voila! Rails has been enabled with security at a database level. You simply continue to use Rails, define models and write your application as you would have done in the unprotected, DBA-account-using, insecure default manner, but now you have all the benefits mentioned above and many more.


The killer feature of this approach is that it makes your applications simpler, easier, faster to develop and enterprise-class.

Tuesday, 26 January 2010

GWT development mode and Rails embedded applications

GWT 2.0 has development mode which supports debugging by a cunning use of browser-based JavaScript communicating execution status back to the GWT server.

To enable this, GWT sends a debugging JavsScript package to the browser and relies on you setting the parameter gwt.codesvr. GWT helpfully tells your what the correct value for this should be in the development mode startup message. Usually it is 127.0.1.1:9997.

The GWT payload reads the parameters passed to the web page which poses a problem for embedded GWT applications in Rails with external frameworks such as when using smartGWT. The reason is that the Rails routing system means that embedding
      ?gwt.codesvr=127.0.1.1:9997
in URLs does fit well and in some cases will break the Rails parameter passing mechanism.

Likewise, attempting to set the parameter in the JavaScript load doesn't work:
   

Embedding the setting into the rendering and redirect sections of your controllers runs the risk of this code remaining in your system when you deploy. Not only that, but it's messy and requires you to change your code prior to deploying.

And easy solution is to let Rails do the heavy lifting for you. You only want the GWT debugger to be on in the development environment.

Rails 2:
In your environment.rb file, add this at the bottom of the file:
   # Setting for GWT
   if ENV['RAILS_ENV'] == 'development'
       $GWT_DEBUG="?gwt.codesvr=127.0.1.1:9997"
   else
       $GWT_DEBUG=""
   end

Rails 3 and 4:
Set:
       $GWT_DEBUG="?gwt.codesvr=127.0.1.1:9997"
in the file:
       config/environments/development.rb
and
       $GWT_DEBUG=""
in the files:
       config/environments/test.rb
       config/environments/production.rb

This will set the global $GWT_DEBUG which you can then append to the URLs that load up embedded Web 2 applications based on GWT. When you deploy live, no code changes are needed.

Now in your controllers you can simply create URLs like this:
   redirect_to '/myurl'+$GWT_DEBUG

Thursday, 14 January 2010

NetBeans, Ruby on Rails, smartGWT and eclipse can work together!

This post is all about RAD on steroids. Combining the awesome power of SmartGWT with Ruby on Rails is a compelling, powerful and extremely fast development approach for real world Web 2.0 applications.

One of the big problems with Ruby on Rails is that that is has limited Web 2.0 support. Yes, there is prototype built in, but the truth is that if you want to build proper Ajax applications, prototype is playing in a different field. It doesn't attempt to provide the sort of Web 2.0 features that YUI, smartGWT or jQuery provide.

In my opinion, the best Web 2.0 development system out there is Google's GWT. There are many frameworks, such as YUI and jQuery that provide exceptional features, however they require you to code in JavaScript and whilst these libraries themselves offer tested and debugged code that is highly portable across browsers, hand-coding JavaScript yourself quickly becomes a quagmire of browser compatibility issues and arcane debugging techniques.

Enter GWT which allows you to not only code and debug in Java, but has an extremely good (and continuously improving) Java to JavaScript translater. This produces browser-portable, optimised JavaScript. Moreover, as browser releases continue, GWT has the added advantage of keeping up to date with the latest releases and a quick recompile of your code is all that you need to ensure that your JavaScript works with the latest browsers in the most optimal manner.

SmartGWT is one of the best (many argue, the best) Web 2.0 frameworks available. It has a vast array of features and capabilities. Not only has it the breadth of service, it also has depth with each component being fully customisable and extensible. Because it's written in Java, you can take full advantage of Java programming techiques. My experience of SmartGWT is that it's the Web equivalent of programming in Swing except in many ways it's more feature rich and powerful than swing. Certainly the components look better designed and stylish!

If you use GWT, although it is possible to use other IDEs such as Sun's NetBeans, the only real player in town is Eclipse. There are many assumptions made in GWT and the supporting documentation that you are using Eclipse and the tide is such that you would be ill-advised to try use another IDE. Why waste the time? So for the Web 2.0 client-side development, your best choice is Eclipse, SmartGWT and GWT. It's stack that works extremely well.

 However, the best player in town for RAD is Rails. The reason is one word: ActiveRecord. Okay, there are many reasons why Rails puts the R in RAD, but ActiveRecord is so powerful, it is so quick to define the way your tables relate to each other and ActiveRecord does so much heavy lifting for you as well as makes your Ruby code so very readable and elegant that it has to be one of the best features in Rails. Not only is ActiveRecord a pleasure to work with, but because it is so well implemented and so quick to set up, marrying ActiveRecord to SmartGWT produces massive coding benefits and saves vast amounts of not just initial development time, but more crucially maintenance and debugging time.

Not only does ActiveRecord make Rails development a dream but bear in mind that few applications online are stand-alone. Most are embedded in web sites and those web sites are fully designed, subject to changes and have active lifecycles. This is what Rails excels at. It was designed to allow developers to work with designers and to minimise the impact of changes as well as to turn around sites very quickly. All these advantages (and many more) Rails delivers with ease. So given the context of Web 2.0 apps sitting in a web site's ecosystem, Rails becomes even more compelling as it handles both sides of the equation with ease. Moreover, it keeps your coding simple, it implements DRY (Don't Repeat Yourself) and it's a joy to work in. You write fewer lines of code and as a result make fewer mistakes and your code is easier to debug.

For a fully fledged IDE for Ruby on Rails that not only provides all the features that you need but also takes the headache out of deployment and will neatly package up your Rails app into a fully fledged, works-out-the-box JRuby WAR file, there is no other choice but Sun's NetBeans. That's not to say that there are other very good alternatives, textmate being the obvious contender. But NetBeans has something very special in the ease with which it allows switching between Ruby and JRuby and the way in which you can package the finished product up and deploy to an app server.

A point of disclosure is needed: I am heavily biased towards JRuby as I see it bringing not just the full catalog of Java libraries to the Ruby table but also implements proper multithreading (a Ruby bane) and tremendous performance advantages. Moreover, a tight integration between Ruby and Java is a very enterprise-ready direction. Given that so few greenfield sites exist in the enterprise, who integrates, wins is the rule of survival and JRuby is the golden goose in this department.

So now we have NetBeans running Rails as the back end and Eclipse running SmartGWT as the front end.

How to get them to talk to each other?

The issue that you will run into is SOP, Same Origin Policy. This is a security restriction that the JavaScript engines place on browsers that means that you cannot have javascript that you loaded from one domain access data from another domain. Given that Eclipse will run GWT (and hence SmartGWT) in development mode on port 8888 and your Ruby on Rails will run under NetBeans on port 3000, this is a problem. Your SmartGWT will not be able to access your ActiveRecord bindings in Rails.

Whilst there are solutions out there that implement various types of HTTP proxy, the veteran Apache server has a fully fledged, easy to implement and easy to maintain proxy server.

What does a proxy server do? It allows your web browser (where your SmartGWT application will be running) to load the SmartGWT application (i.e. the JavaScript that is subject to SOP restrictions) from the same domain as your Rails application (running on Netbeans) will respond to. Even though Eclipse and NerBeans could be running on different development machines as well as usuing different ports, the proxy server (apache) invisibly reroutes these requests. The browser thinks that it is only talking to Apache on the same port. Apache is able to take those requests and, with the aid of mappings that you specify, work out where each request actually routes to. I.e. It will send Rails requsts to NetBeans and GWT requests to Eclipse.

By using Apache as a proxy, you overcome the Same Origin Policy restrictions of JavaScript and your SmartGWT can now talk to Rails and vice versa.

There are only two small problems left in this cunning plan to get SmartGWT working with Rails.

The first is the issue of SmartGWT and REST. To be blunt, it's broken with Rails. SmartGWT doesn't implement dynamic URLs and as such, the Rails method of mapping REST resources simply doesn't work because URLs like /controller/action/id/ simply are not constructed by SmartGWT. Moreover, the action that SmartGWT intends to happen is embedded in a parameter called _operationType and the restrictions caused by SmartGWT's static data URLs are such that Rails will misinterpret the REST calls, mistaking an update, for example, for an insert.

Whilst it is possible to subclass the SmartGWT datasources and manully add URL manipulation to force SmartGWT to confirm to Rails' URL usage, this sits badly with SmartGWT as the parameters that it passes need to be interpreted by Rails in any case. Not only this, but your Rails controllers quickly begin to get bogged down with the extra coding needed to support SmartGWT's parameter passing. It all starts to get messy and complicated rather quickly and the whole point of using Railis is that it's so quick and easy to implement controllers, models and views. I.e. Data bindings.

The solution is to use the flexibility of the Ruby language and the awesome Rails design. We subclass the ApplicationController class to create a new class  for controllers, IscController. In this controller, we add helper methods that will cleanly build model view instances, understand the SmartGWT way of doing things and build SmartGWT-friendly responses.

This will then enable us to create SmartGWT-enabled controllers just as we would "normal" controllers by using:
     class MySmartGWTController < IscController
instead of the usual

     class MySmartGWTController

From then on, our controllers remain as simple and elegant as any other Rails controller, the power of ActiveRecord is at our disposal and the Rails application talks the same flavour of REST as the SmartGWT client code.

The second issue with the Rails <-> SmartGWT integration is Rails' authentication_token parameter. This is an anti-forgery device intended to stop spoofing of REST calls by hackers. It's a code that Rails automatically sets when a browser connects to the application and Rails maintains this code invisibly. However, SmartGWT's AJAX calls do not pass Rail's authentication_token. The solution is to create a JavaScript variable alongside the isomorphicDir variable and to explicity add this into the SmartGWT's DataSource URLs.

We will see how these are implemented in later blogs. For now, we have the principles of how to get the best of both the SmartGWT as well as the Ruby on Rails worlds, without compromise and at full power!