MonoRail does not provide a standard way to accomplish authentication nor authorization. This is intentional as MonoRail runs on top of Asp.Net infrastructure which provides standard way to handle both, like the FormsAuthentication and the configuration element.

That being said, you can also use Filters to implement authentication if you want. All you have to do is associate an authentication filter with the controllers that can only be accessed by authenticated users.

When using filters the options are wide. You can rely on the session, you can rely on cookies; you may want to provide an implementation of IPrincipal and supply the roles yourself to have a more fine-grained permission control.

The approach demonstrated here uses a custom implementation of IPrincipal on the User class and uses the session to persist the authentication among requests. Implementing a "remember me" feature would require a cookie. It was not implemented to keep the example as simple as possible.

Authentication control with filters is just a matter of associating an authentication filter with the controllers you do not want to be accessed by anonymous users. This only restricts access to controller's actions. If you want to protect files, you might use a mix of filters and FormsAuthentication or implementing the Authenticate_Request event.

In our example we want to prevent access to the HomeController. So we associate a BeforeAction filter with it:

The filter implementation can do a number of things to check if the current user is authenticated. We decided to check if an existing object exists in the session. The object implements IPrincipal but this is not required. The implementation will vary depending on the requirements and how you plan to handle authorization.

The LoginController will not be much different from the previous example:

using AuthenticationUsingFilters.Model;
using Castle.MonoRail.Framework;
[Layout("default")]
public class LoginController : SmartDispatcherController
{
public void Index()
{
}
public void LogIn(String username, String password, bool rememberme, string ReturnUrl)
{
// We should authenticate against a database table or something similar
// but here, everything is ok as long as the
// password and username are non-empty
if (IsValid(username, password))
{
CancelView();
// Ideally we would look up an user from the database
// The domain model that represents the user
// could implement IPrincipal or we could use an adapter
User user = new User(username, new string[0]);
Session["user"] = user;
Redirect(ReturnUrl);
}
else
{
// If we got here then something is wrong
// with the supplied username/password
Flash["error"] = "Invalid user name or password. Try again.";
RedirectToAction("Index", "ReturnUrl=" + ReturnUrl);
}
}
private bool IsValid(string username, string password)
{
return username != null && password != null;
}
}

If the authentication passes we just create the User and add it to the session, allowing the filter to get it for the subsequent requests.
The User class is just a simple implementation of IPrincipal. Real applications will use an adapter or change an existing class that represents a logged user, or system user to implement it as well.

If you have a custom implementation of IPrincipal or even if you use the GenericPrincipal but supply the roles, you would be able to use PrincipalPermission to prevent users from invoking methods or code branches.

Set on current thread too

In addition to setting the principal implementation on the HttpRequest (which is what context.CurrentUser does) you must also set the principal on the current thread by using System.Threading.Thread.CurrentPrincipal.

The PrincipalPermission and PrincipalPermissionAttribute belong to the .NET security infrastructure and demands that the executing principal has a specific role. This can be used as the last resource to secure your application.

For example, suppose your application is clever enough to not offer links to resources/actions the user does not have access to. However, this is commonly refered to as 'security by obscurity', as a user that knows how to get to the resource will be able to access them. To secure the application from this kind of access you might use PrincipalPermission. For example: