Modeling Organizations
A common use-case for B2B businesses is to model their customers and the employees of those customers. This concept isn’t limited just to SaaS businesses either as many companies sell products and services to other companies. The employees, contractors, and other types of users at these customers (i.e. other companies) need access to various applications to do their work.
An example of this is a CRM. Let’s say you are building a hot new CRM called AwesomeCRM. Your customers will be other businesses and let’s say one is called ClownShoes.com. ClownShoes employs 10 salespeople and they will all need access to your CRM. However, each one might have different permissions. To layer in even more complexity, ClownShoes uses an outsourced CRO service called Big Bucks CRO. Jane is a fractional CRO with Big Bucks and she will also need access to your CRM, but she might be working with 10 or more clients, including ClownShoes. You’ll need to ensure Jane can access all these accounts and has the correct permissions for each, which might be different for each of her clients.
As you can see, this structure introduces a lot of complexity. This is where FusionAuth’s Entity Management feature comes in handy. Entity Management allows you to create objects (i.e. Entities) and grant Users permissions to them. Users aren’t limited to having permissions to just one Entity; instead they can be granted different permissions to different Entities.
This feature is only available in paid plans. Please visit our pricing page to learn more.
This guide will walk you through implementing the use-case described above with Entity Management using the FusionAuth APIs, you can also see more in our core concepts for Entity Management.
Let’s get started.
Create An Entity Type
The first step is to create an Entity Type. Entity types define a class of entities along with the permissions that can be granted. You can create Entity Types using the API, but in most cases, Entity Types are only created once, so you can use the admin UI for that. If you prefer to use the APIs, you’ll find that API here.
Let’s create an Entity Type called Customers
. You can name it something else if you prefer since the name is just for display purposes. Here’s what this looks like:
You have defined 5 different permissions for your Customers
type and those are:
- Admin - this permission allows the User to do anything with the account
- Sales - this permission is for salespeople and allows them to do things like create contacts, companies, deals, etc.
- Billing- this permission allows the User to manage billing things like invoices, credit cards, etc.
- Reports - this permission allows the User to manage reports
- Viewer - this permission allows the User to view but not touch
The names for permissions are also arbitrary and mostly for display purposes, so feel free to name things whatever you want.
After you create the Entity Type, we need to copy its Id for the next step.
Creating Entities
Now that you have an entity type, we can start creating entities. The process of creating Entities is usually part of the signup process or some other type of on-boarding process. This will depend on how your business handles creating accounts for your customers. For AwesomeCRM, you’ll collect this information when the user signs up. During this signup process, you’ll create the Entity and then grant the newly created User permissions to that Entity. This will model the fact that the user who signs up is always the first Admin of the account.
To accomplish both of these tasks, you’ll call FusionAuth APIs. To create the Entity for this new customer, we’ll call the Create Entity API. Here’s what your JSON will look like:
{
"entity": {
"type": {
"id": "<entity-type-id>"
},
"name": "Pied Piper"
}
}
This JSON will create an Entity with the newly created Entity Type from above with the name Pied Piper
. Entity names are not unique, so you don’t need to worry about multiple users conflicting with respect to their company name.
You’ll need to parse the response to capture the Id of this newly created Entity. Here’s how the JSON response looks:
{
"entity": {
"clientId": "092dbded-30af-4149-9c61-b578f2c72f59",
"clientSecret": "+fcXet9Iu2kQi61yWD9Tu4ReZ113P6yEAkr32v6WKOQ=",
"id": "8174f72f-5ecd-4eae-8de8-7fef597b3473",
"insertInstant": 1595361142909,
"lastUpdateInstant": 1595361143101,
"name": "Pied Piper",
"tenantId": "30663132-6464-6665-3032-326466613934",
"type": {
"id": "4838d96a-4e7b-42c6-a4a1-ebc64952e1c8",
"insertInstant": 1518962408732,
"jwtConfiguration": {
"enabled": false,
"timeToLiveInSeconds": 60
},
"lastUpdateInstant": 1518962408732,
"name": "Customers"
}
}
}
Extract the id
from this JSON and store it in a variable.
Create Entity Grants
The final step during the signup process will be to assign the correct permissions for the user to their entity. To accomplish this, you will call the Grant API. In order to call this API, you will need the entity and user Ids. Here’s how the JSON will look for the grant request:
{
"grant": {
"permissions": [
"Admin"
],
"userId": "<user-id>"
}
}
You’ll notice that the JSON only includes the User Id. The Entity Id is added to the URL when calling this API like this:
POST /api/entity/<user-id>/grant
It’s important to note that the User Id can be determined in a number of different ways, depending on how your registration process is set up. If you are using FusionAuth for registration, you can extract the User Id from the JWT access token that FusionAuth provides at the end of the OAuth workflow. The user Id is stored in the sub
claim. Or you can use the User Info or Introspect APIs with the access token to retrieve the user details. All of these places will contain the user Id.
Now you have constructed all the necessary pieces to model the customers of AwesomeCRM and the users that have access to the customer accounts.
Login
Now that your data model is prepared, you need to handle login events. When a user logs in, your application needs to know what organization they belong to. Generally, this information is stored in a cookie or in a server-side session, such that it is available on each request to the application.
To get this information from FusionAuth, you will call the Search Grants API. This API allows you to retrieve all of the grants that a specific user has to any Entities. This API doesn’t take a JSON body, but we will supply the User Id on the URL. The URL looks like this:
GET /api/entity/grant/search?userId={userId}
You will replace the userId
parameter with the Id of the user that is currently logged in. In the same manner as above, this information can be retrieved from the access token JWT or the User Info or Introspect APIs.
The response from this API looks like this:
{
"grants": [
{
"entity": {
"clientId": "092dbded-30af-4149-9c61-b578f2c72f59",
"clientSecret": "+fcXet9Iu2kQi61yWD9Tu4ReZ113P6yEAkr32v6WKOQ=",
"data": {
"companyType": "Legal"
},
"id": "8174f72f-5ecd-4eae-8de8-7fef597b3473",
"insertInstant": 1595361142909,
"lastUpdateInstant": 1595361143101,
"name": "Raviga",
"tenantId": "30663132-6464-6665-3032-326466613934",
"type": {
"id": "4838d96a-4e7b-42c6-a4a1-ebc64952e1c8",
"insertInstant": 1518962408732,
"jwtConfiguration": {
"enabled": false,
"timeToLiveInSeconds": 60
},
"lastUpdateInstant": 1518962408732,
"name": "Customers"
}
},
"id": "8174f72f-5ecd-4eae-8de8-6fef597b3473",
"insertInstant": 1595361142929,
"lastUpdateInstant": 1595361143121,
"permissions": [
"Admin"
],
"userId": "7174f72f-5ecd-4eae-8de8-7fef597b3473"
}
],
"total": 1
}
You can see that the permissions are available in the response. You can extract the permissions and use them to authorize actions that the user takes or APIs they are calling. In this example, the User has the Admin
permissions, which means they are likely allowed to do anything they wish.
The grant
object, or some portion of it, can be stored in any number of locations for easy access. You could store it in a cookie (encrypted is preferred), a server-side session, or a database. The Search Grants API is designed to be queried repeatedly and returned quickly, so depending on the scale of the application and where FusionAuth is deployed, you could also query this API for each request. This has the benefit of ensuring that the User’s permissions are always the most current version.
Multiple Organizations
The final component that will be covered in this guide is handling multiple organizations for a single user. AwesomeCRM works with many partners and often these partners work with many clients. This means that a user at a partner company might be working with multiple organizations at the same time. To handle this scenario, you need to ensure you can handle multiple results from the Retrieve Grants API.
Here’s an example of the response from the Retrieve Grants API when a user has multiple organizations (many properties have been trimmed for brevity):
{
"grants": [
{
"entity": {
"name": "Pied Piper",
...
},
"permissions": [
"Admin"
],
...
},
{
"entity": {
"name": "Hooli",
...
},
"permissions": [
"Sales"
],
...
},
{
"entity": {
"name": "Aviato",
...
},
"permissions": [
"Billing",
"Reports"
],
...
}
],
"total": 3
}
This response indicates that the User belongs to 3 organizations and has various permissions for each. To manage this in your AwesomeCRM application, you can present an option to the user when they log in, to select the company they’d like to work on initially. This option screen might look like this:
Managing Users
Often applications provide the ability for users to manage other users on their account. This is accomplished in much the same way as described above. To add a user to an organization, you can use the Grant API. To remove a user from an organization, you can use the Delete a Grant API. If you need to adjust the permissions a user has to an organization, you can use the same Grant API from above. The Grant API is an upsert, which means that if a grant already exists, it will update its attributes.
Changing An Organization
Beyond managing users, some applications provide the ability to rename or modify a user’s organization. To update an Entity, you can use the Update an Entity API. This allows any attribute of the Entity to be updated, including custom data.
Custom Data And Search
Custom data on an entity can be used to store additional information about the Entity, such as various ids (Stripe, QuickBooks, NetSuite, etc), organization attributes (locations, parent company, etc), or just about anything that is needed. Custom data on an Entity is indexed within FusionAuth, which means it is also searchable using the Entity Search API.
Let’s say that your organizations have a custom attribute for the address like this:
{
"entity": {
"data": {
"address": {
"city": "Denver"
}
},
"type": {
"id": "<entity-type-id>"
},
"name": "Pied Piper"
}
}
You can search for this attribute using this request:
GET /api/entity/search?queryString=data.address.city:denver
This uses the Elasticsearch query string query syntax.
Conclusion
This is just one of the nearly infinite uses for FusionAuth’s Entity Management feature. It allows applications to easily implement a data model for organizations and permissions and grant the permissions to users. Some other uses for Entities include IOT (permissions to devices), machine-to-machine clients (OAuth Client Credentials), SCIM clients, and many more.
Enjoy and happy coding!