Overview
Terminology: In this documentation, a user means a 'user or the api', which maps to the user credential passed through api. For example, when using the -u admin:password
in most of our cURL examples, the user is admin
and its password is password
.
Assumptions: We assume the reader went through the Getting started documentation and has a running system (both killbill and kaui) running on IP=127.0.0.1
.
Shiro
Each api request to Kill Bill requires authentication. The authentication phase verifies that the user exists in the system and that its credentials are correct. Once the credentials have been validated, the roles associated to the user are then extracted, and then the set of permissions associated to each role are also retrieved. The full list of available permissions can be found here.
The credentials are passed in the request using http basic authentication mechanism and Kill Bill relies on shiro for the backend implementation. Shiro supports multiple backend implementations, and we integrated a few of them including:
-
Simple configuration file (
shiro.ini
file) -
Database configuration
-
LDAP integration
-
Okta/Auth0 integration
For simple deployments where only few static users/roles need to be assigned, the shiro.ini
file is the simplest and the best option. By default both Kill Bill (shiro.ini
) and Kaui ship with an admin
user (and its password password
) that has all the permissions. One can immediatly log-in to Kaui using such user, and start configuring tenants as needed.
Changing such user (e.g to use superadmin
) or its password to something else than password
would require editing shiro.ini
configuration file on the Kill Bill side to make sure this initial user can log-in to Kaui (see below).
For production deployments, we recommend not using the default admin
(and its default password password
).
Tenant Access
Note that the authentication/authorization is orthogonal to the tenant access: The set of permissions associated to a given user is the same for all tenants (for which he has the keys). So, a potential superuser with all the permissions and with access to the api_key
/api_secret
for all tenants would have full control of the entire system. It is common practice to create a cross-tenant admin with the ability to only manage tenants and nothing else, and then have one superadmin per tenant.
This documentation is only specific to users
, roles
and associated permissions
, which are cross tenants configurations.
User Management APIs
For a large entreprise solution, an LDAP or Okta/Auth0 integration is probably the most flexible, but it is also the most complex, and so for those that require the flexibility of an RBAC systems without the associated complexity, Kill Bill offers apis to manage the users/roles/permissions, where new user/roles/permissions will be stored in a database.
This solution relies on a mixed solution between the shiro.ini
file and the database backend: An initial user must be configured in the shiro.ini
with at least enough permissions to use the User Management APIs:
-
The
shiro.ini
file is used to configure the initial user (could be a superadmin with all permissions or an admin with just enough permissions to manage the user/roles). For simplicity, we will call itsuperadmin
and will assign one role containing all permissions. -
Once deployed, the 'superadmin' is now able to make api calls to configure new users/roles.
Kill Bill setup
The shiro.ini
file will look like the following:
[users]
superadmin = superadmin13, root
[roles]
root = *:*
You can use the property org.killbill.security.shiroResourcePath
to specify the location of this file. When using Docker, you can bind mount the file, e.g. specify -v /path/to/shiro.ini:/var/lib/killbill/shiro.ini -e KILLBILL_SECURITY_SHIRO_RESOURCE_PATH=file:/var/lib/killbill/shiro.ini
.
Role and User Setup
Let’s create a new role customer_support
:
curl -v \
-u "superadmin:superadmin123" \
-H "X-Killbill-CreatedBy: stephane" \
-H "Content-Type: application/json" \
-X POST \
--data-binary '{ "role": "customer_support", "permissions": ["account:create", "account:update", "entitlement:change_plan", "entitlement:pause_resume", "entitlement:cancel", "entitlement:transfer", "invoice:credit", "invoice:item_adjust", "tag:create_tag_definition", "tag:delete_tag_definition", "tag:add", "tag:delete"] }' \
'http://127.0.0.1:8080/1.0/kb/security/roles'
Let’s create a cs
username that will have only one role customer_support
:
curl -v \
-u 'superadmin:superadmin123' \
-H "X-Killbill-CreatedBy: stephane" \
-H "Content-Type: application/json" \
-X POST \
--data-binary '{ "username": "cs", "password": "cs123", "roles": ["customer_support"] }' \
'http://127.0.0.1:8080/1.0/kb/security/users'
Let’s assume we want to add more permissions to that user. We could create another role customer_support_manager
(same step as before with the desired set of permissions), and then update our user to now have this new role:
curl -v \
-u 'superadmin:superadmin123' \
-H "X-Killbill-CreatedBy: stephane" \
-H "Content-Type: application/json" \
-X PUT \
--data-binary '{ "username": "cs", "password": "cs123", "roles": ["customer_support_manager"] }' \
'http://127.0.0.1:8080/1.0/kb/security/users/cs/roles'
Tenant Setup
Since we did not give access for all the tenant management to our new CS
account, let’s have our superadmin create a first tenant:
curl -v \
-X POST \
-u superadmin:superadmin123 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-CreatedBy: admin' \
-d '{"apiKey": "bob", "apiSecret": "lazar"}' \
"http://127.0.0.1:8080/1.0/kb/tenants"
Validation
Assuming our cs
user knows about the api_key
and api_secret
of the tenant, he should now be able to make any api calls against that tenant (with the limitation of his permission set).
So for instance, creating a new account in that tenant would work because his role customer_support
includes the permission account:create
:
curl -v \
-u cs:cs123 \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "Content-Type: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-X POST \
--data-binary '{"name":"John Doe","email":"[email protected]","externalKey":"john-doe-1234","currency":"USD"}' \
"http://127.0.0.1:8080/1.0/kb/accounts"
But the following curl to refund a payment would fail because his role customer_support
does not include the permission payment:refund
:
curl -v \
-u cs:cs123 \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "Content-Type: application/json" \
-H "X-Killbill-CreatedBy: demo" \
-X POST \
--data-binary '{"amount":"12.4"}' \
"http://127.0.0.1:8080/1.0/kb/invoicePayments/288983f2-5143-47e4-b967-b8962fc699d1/refunds"
LDAP configuration
To enable LDAP, Kill Bill needs to be launched with the following properties (note that the values here are just examples and might need to be updated depending on your LDAP configuration):
org.killbill.security.ldap.dnSearchTemplate=uid={0},ou=users,dc=mycompany,dc=com
org.killbill.security.ldap.searchBase=ou=groups,dc=mycompany,dc=com
org.killbill.security.ldap.groupSearchFilter=memberOf=uid={0},ou=users,dc=mycompany,dc=com
org.killbill.security.ldap.groupNameId=cn
org.killbill.security.ldap.url=ldap://ldap:389
org.killbill.security.ldap.disableSSLCheck=true
org.killbill.security.ldap.systemUsername=cn=root
org.killbill.security.ldap.systemPassword=password
org.killbill.security.ldap.authenticationMechanism=simple
org.killbill.security.ldap.permissionsByGroup=support-group: entitlement:*\nfinance-group: invoice:*, payment:*\nops-group: *:*
The following System Property should also be set:
-Dkillbill.server.ldap=true
Notes:
-
If no groups are defined in LDAP, all users will only have read-only permissions
-
Before an LDAP user can use Kaui, an admin needs to associate his login to the right tenants (see below)
-
If you have trouble connecting to your LDAP system, enable DEBUG logging of the package
org.apache.shiro
in yourlogback.xml
and check the logs
<logger name="org.apache.shiro" level="DEBUG"/>
Okta configuration
Kill Bill integrates with Okta machine-to-machine authentication APIs.
To enable this, Kill Bill needs to be launched with the following properties:
org.killbill.security.okta.url=https://XXX.okta.com
org.killbill.security.okta.apiToken=YYYY
org.killbill.security.okta.permissionsByGroup=support-group: entitlement:*\nfinance-group: invoice:*, payment:*\nops-group: *:*
The following Java System Property should also be set:
-Dkillbill.server.okta=true
Notes:
-
The url must match your customer url
-
The
apiToken
can be created at https://XXX-admin.okta.com/admin/access/api/tokens -
The groups must match the ones defined in Okta (https://XXX-admin.okta.com/admin/groups). If permission by group is not needed, remove the
org.killbill.security.okta.permissionsByGroup
property. -
If no groups are defined in Okta, all users will only have read-only permissions
-
Before an Okta user can use Kaui, an admin needs to associate his login to the right tenants (see below)
-
If you have trouble connecting to Okta, enable DEBUG logging of the package
org.apache.shiro
in yourlogback.xml
and check the logs
<logger name="org.apache.shiro" level="DEBUG"/>
Auth0 configuration
Kill Bill integrates with both Auth0 Machine to Machine authentication APIs and Auth0 JWT.
Machine to Machine authentication APIs
To integrate Auth0 with Kill Bill:
-
Create a
killbill
Machine to Machine application, and write down theDomain
,Client ID
, andClient Secret
. In Advanced Settings, make sure to enable theClient Credentials
andPassword
grant types. -
Create a
killbill
API, and write down theIdentifier
(e.g.https://killbill/1.0/kb/security
). Authorize thekillbill
application and configure the permissions (e.g.invoice:*
). Authorize theAuth0 Management API
application and make sure theread:users
permission is granted. -
Assign permissions to your users.
-
Write down the
Database connection name
Kill Bill should be authenticating against (e.g. the default one isUsername-Password-Authentication
).
Configure Kill Bill as such:
org.killbill.security.auth0.url=https://XXXX.us.auth0.com
org.killbill.security.auth0.clientId=YYYY
org.killbill.security.auth0.clientSecret=ZZZZ
org.killbill.security.auth0.apiIdentifier=https://killbill/1.0/kb/security
org.killbill.security.auth0.databaseConnectionName=Username-Password-Authentication
The following System Property should also be set:
-Dkillbill.server.auth0=true
Notes:
-
If no permissions are defined in Auth0, users will only have read-only permissions
-
Before an Auth0 user can use Kaui, an admin needs to associate his login to the right tenants (see below)
-
If you have trouble connecting to Auth0, enable DEBUG logging of the package
org.apache.shiro
in yourlogback.xml
and check the logs
<logger name="org.apache.shiro" level="DEBUG"/>
JWT
Kill Bill can also support authentication and authorization via JWT (useful to integrate with https://github.com/oauth2-proxy/oauth2-proxy for instance).
By default, the subject is decoded from the JWT and permissions looked up in Auth0. However, if the Add Permissions in the Access Token
setting is turned on in Auth0, the JWT will contain the permissions, and Kill Bill will trust these without calling Auth0.
The username in Kill Bill maps to the sub
claim by default. You can change this by setting org.killbill.security.auth0.usernameClaim
(e.g. you could set it to email
for instance, if the email
is a claim in the token).
If you are changing this, make sure to update the matching setting in Kaui (-Dkaui.jwt.username_claim
System Property or KAUI_USERNAME_CLAIM
environment variable).
KAUI
KAUI has been extended to understand all the user/role/permission management and will manage the corresponding sessions. Some of those implementation details were covered in our previous blog post.
Users
To configure users allowed to use Kaui, go to /admin_allowed_users
:
Fields to populate will depend on which back-end realm is configured.
Database
If you are storing roles, usernames and passwords in the Kill Bill database, leave the "Managed externally" checkbox unchecked and fill-in all details. Kaui will create these users locally and in Kill Bill (if they don’t exist on the server already).
Roles can be created by going to /role_definitions/new
.
LDAP, Okta, and Auth0
If you are delegating roles and users management to a third-party system, Kaui only needs to know the login of the users. Password and roles being managed outside of Kill Bill, you need to access your third-party system to set and update these.
Note that there is no auto-discovery of logins: you need to enter all logins from your system manually in Kaui before such users can access the UI (check the box "Managed externally" when adding these users). At the time of creating the user is Kaui, the username must match the one used in the authenticating system.
When adding the user, the password field will be greyed out. Kaui does not require a password, as authentication will be handled by one of the above systems.
At the time of login, the user will visit the Kaui login page and enter the username and password created in the authenticating system. Since Kaui is already aware of the username, a request will be sent to Kill Bill, which will then redirect the authentication request to the authenticating system. Upon receiving a successful response from the authenticating system, Kaui will log in the user.
Users and tenants
Kaui needs to be told about the relationship between user and tenants (this mapping is specific to the UI). The idea, is that a super admin would first configure the allowed users for each specific tenant on the KAUI side, in such a way that later on, when a specific user logs in, he only sees the tenants he has access to.
This mapping can be configured by going to each user page (e.g. /admin_allowed_users/1
).
As far as tenant configuration goes, it is possible to create tenants directly from Kaui. If you already have created a tenant in Kill Bill using APIs, you can safely re-create it from Kaui, which will discover it on the server side and simply sync it locally.
Super user
Kaui has the concept of a super user (root) for critical, cross-tenants, operations. By default, it assumes that the admin
user is the super user, but you can change this by setting the system property kaui.root_username
(KAUI_ROOT_USERNAME
Docker environment variable). The password doesn’t need to be specified as it is stored on the server side (shiro.ini
, etc.).
Summary
-
User, roles, permissions need to be configured on the server side (
shiro.ini
, database, LDAP, Okta/Auth0, …) -
Tenants can then be created (using a user whole role’s permissions allow such operation)
-
Mapping between tenant and allowed users need to be defined in Kaui