1
votes

I am having troubles wrapping my head around the concept of multi tenancy in combination with websecurity (webmatrix framework from microsoft). I am building a mutli tenant website with:

  • mvc4
  • entityframework6
  • websecurity (from webmatrix)

Authenticate

I can allow users to register & login using the WebSecurity methods. I can verify if a user is logged in / is authenticated via User.Identy.IsAuthenticated.

Determine Tenant

I determine the tenant via the url ([companyname].domain.com).

Register a new customer

A new customer can create a tenant via the registering form in my application. If a user registers (without having a companyname present in the url) he will have to give some account inputs as some company inputs. He will then create a new alias which is conform companyname.domain.com. So, long story short, a Tenant is always coupled to 1 or more user(s) (1-N).

Requirement

I need to guarantee that a user from Tenant 'abc' will never be able to login to Tenant 'xyz'. (Therefore I also don't like the WebSecurity framework too much, as it seems a shared database for all my tenants (or am I wrong?)).

My question

Could you guys share some insights in how to handle the check on "tenant" and "authenticated user" in real world multi tenant applications?

The hot topics for me:

  • Do you validate the tenant + authenticated user once, or in every action in every controller?
  • Is it safe to rely on the default websecurity class or would I be better of designing my own user tables or are customer MembershipProviders the better alternative?
  • Should I use cookies or is that a very bad choice.

I would be very much helped if you could share some documentation where I can read all about these questions. I have the strong desire to see some more in detail documentation about multi tenancy, that dives into the actual design (maybe even code examples).

I already read through most of the "general documentation" / "commericial presentations":

If needed I'll rephrase / add code / do whatever is needed to get help.

Many thanks in advance.

1

1 Answers

1
votes

Each solution you could get here would be dependent on what your app does and how it works with data, if you use repository pattern, if you use IoC etc. You might consider instantinating your repository by passing userid to repository class and doing filtering everytime application needs data, you can do that in your controller - this approach is used very often (even in VS SampleProjects - like "SinglePage Application" you might want to download some open source projects and just see how it's done there.

What I do in some of my projects where nothing "really fancy" is required and I don't expect a huge load is this: - I setup BaseController that every other controller needs to implement - in onActionExecuting event of the BaseController I do

public Employee CurrentEmployee { get; set; }

protected override void OnActionExecuting(ActionExecutingContext ctx)
{
    base.OnActionExecuting(ctx);
    string authenticatedUser = User.Identity.Name;
    CurrentEmployee = mortenDb.Employees.FirstOrDefault(e => e.Account.Login == authenticatedUser );
}

so in all other controllers I'm able to refer to an Employee object that belongs to currently logged in user. You could do the same with your Company object. So I assume you would query Employees like I do and retrieve the Company reference and pass it to public property on your BaseController. It's maybe not the best solution, but it's rather secure as long as you remember to pull out data via Company object navigation properties (eg. Employees, Tickets, Requests etc. whatever you have in your Model )