Kill Bill has been designed from the beginning as a multi-tenant system; that is, on one physical Kill Bill deployment, we can have multiple (tenant) instances of Billing/Payment solutions, completely independant with one another. Each of those tenants will have its own catalog and internationalization translations, and will only have access to its own data.
In addition to the multi-tenancy, Kill Bill also requires authentication and implements authorization validation on each request. Logically , the multi-tenancy feature and the authentication/authorization are two separate concepts: a given user has access to a (some) specific tenant(s) and that user has some specific set of permissions. The current implementation keeps those two orthogonal, but in the future we may offer the ability to configure the set of permissions associated to a specific user on a per-tenant basis.
When making API calls against Kill Bill, each request needs to pass:
- The credentials or the
sessionIdrequired for the authentication (through HTTP basic authentication),
- The apiKey (X-Killbill-ApiKey) and apiSecret (X-Killbill-ApiSecret) for the tenant
On each request, Kill Bill will validate the credentials are correct (or if there is a
sessionId, the validity of that session), The
apiSecret will be used to retrieve the tenantId and validate the user has access to that tenant. So in the end, only a valid user with the right set of permissions will be able to perform an API call against a tenant she has access to.
Now, let’s look at what happens, when the user is interacting with Kill Bill using KAUI (Kill Bill admin UI):
User first needs to login, either by specifically hitting the sign-in endpoint or because KAUI detects an unsigned user and redirects to the login screen. KAUI will interact with Kill Bill to verify the credentials and return the permissions associated with the user.
On the Kill Bill side, we are relying on shiro to validate the credentials and return the permissions; shiro supports different backends such as static configuration files, LDAP, … Shiro will create a
sessionId that is returned as part of the authorization, and that can be used in subsequent requests.
On the KAUI side, we are using Devise (on top of Warden) to manage the authentication; Devise will manage the
sessionId returned by Kill Bill (shiro) and keep track of the mapping between the current user and the
sessionId. KAUI will then return a cookie to the browser that will allow to retrieve the
sessionId on each request and pass it back to Kill Bill.
Once a user has logged-in, he needs to specify the tenant he wants to access. Note that most users will probably have access to only one tenant, but we also want to support the case when a user can access multiple tenants (for instance to support hierarchical tenants configurations) or the case of a super-user that has access to multiple/ALL tenants.
KAUI will need to be able to know the tenants that are available for a specific user. Ideally, in the same way, the authorization went through Kill Bill (Shiro module), we would like KAUI to also rely on Kill Bill to return the list of available tenants for a specific user. The current implementation in KAUI is to statically configure which tenants are available on a per user basis, but in the future we could envision to also use LDAP configuration to describe not only the users with their set of permissions but also the list of tenants they have access to.
In order to support these requirements but also to make the user experience as simple as possible, we implemented multiple paths:
- If the user does not have access to any tenant, nothing is displayed; a variation of that path exists for debugging and test purpose where we allow to specify the tenant apiKey and apiSecret (and therefore specifying which tenant to use).
- If the user has access to only one tenant, the user is NOT prompted for any choice. Any subsequent request will be made against that tenant. Since we envision most users to have access to only one tenant, this simplifies the user experience.
- If the user has access to several tenants, the user is prompted to choose its tenant through an extra screen where available tenants are displayed. The tenant information will be stored in the cookie, and so the user can change its tenant at any time by either clearing its cookie or explicitly going back to the tenant screen.
Any UI (user facing UI, analytics UI, …) connecting to Kill Bill will have to offer similar mechanisms to handle both the authentication/authorization and multi-tenancy. Fortunately KAUI has been implemented as a mountable rails engine, and so any Rails App could mount KAUI to leverage the work around authentication/authorization and multi-tenancy.