Our platform serves many organizations from one system. The most important thing it does is also the easiest to get wrong: making sure one organization can never reach another’s data.
The organization is part of every address
Every request for an organization’s data names that organization in its web address. Before any business code runs, a security check requires three things to agree: the address, a request header, and the organization named in the signed token. The person must also be an active member. If any of these disagree, the request stops there.
Controllers then check again, on purpose. If one layer is ever misconfigured, a single missed check shouldn’t mean a data leak.
Two tokens, not one
Signing in gives you a token that says who you are. To work in an organization, you exchange it for a second token that’s tied to that organization alone. A login token used on an organization’s address is refused, so you can’t accidentally act in an organization you haven’t entered.
Tokens carry no permissions
It’s common to put a person’s permissions inside their token. We don’t. Permissions are loaded on each request, so removing someone’s access takes effect straight away, not when their token expires.
Permissions only ever reach a person one way: person, then group, then role, then permission. There’s no shortcut for granting one permission to one person, which makes “who can do this?” a question you can answer.
Separate logins for each product’s data
Our separate products each have their own database, with their own login limited to what that product needs. A flaw in one product’s code can’t simply read another’s tables.
Where this has limits
- Access applies to a whole app across an organization. There’s no limiting access by branch, project or client inside one organization, so we suggest separate organizations when data must be kept fully apart.
- Loading permissions on each request costs a database lookup every time. We accept that in exchange for changes taking effect at once.
- All of this protects against the application’s own mistakes and misuse. It doesn’t replace securing the servers it runs on.