Appmixer Virtual Users

This tutorial shows you how to create Appmixer virtual users that shadow your own user accounts in your own user management system. Moreover, we also show how to group users into teams and how to limit the set of components each team has access to.

Introduction

When you embed Appmixer functionality/UIs into your product, you need to create Appmixer virtual users. These user accounts are only internal, your end-users don't need to sign-up anywhere and won't even notice. The purpose of virtual user accounts in Appmixer is to associate Appmixer entities (flows, data stores, files, connected 3rd party accounts, logs) with your own user accounts.

Usually, you create Appmixer virtual user accounts automatically and on the fly, at the time your end-user requests to see a page where an Appmixer functionality is embedded. Therefore, not all your users need a shadow Appmixer virtual user account but only those that will interact with the embedded Appmixer widgets (Integrations, Workflow Designer, ...).

Creating Virtual User accounts using the SDK

The easiest way to create virtual user accounts is via the client-side Appmixer JavaScript SDK. The SDK provides methods to authenticate virtual users and to create new virtual users. You can find a full example in the SDK Getting Started guide. Let's say you have a page in your web application where you want to display the Appmixer FlowManager UI widget so that your end-users can see the flows they created and create new ones:

The first thing you need to do is to provide an HTML container element inside which you want to render the FlowManager:

...
<div id="my-am-flow-manager"></div>
...

Note that you also need to include the Appmixer SDK on your page:

<script src="https://my.YOURTENANT.appmixer.cloud/appmixer/appmixer.js"></script>

And then initialize the SDK by passing your Appmixer base URL (the Appmixer Engine location):

const appmixer = new Appmixer({ baseUrl: 'https://api.YOURTENANT.appmixer.cloud' });

At this point, you're ready to authenticate your user to Appmixer in the background or create a new virtual Appmixer user if your user account has not yet been associated with one. Let's assume that your client-side code has an information about your user profile stored in profile object that might look something like this:

const profile = {
   email: 'john@doe.com',
   name: 'John Doe'
};

If this is the first time your user is about to interact with Appmixer in your app, then your user profile does not have any Appmixer virtual user credentials stored. Therefore, you should generate a secret that we'll use as the user's password to Appmixer and create a new Appmixer virtual user. If your user profile already contains Appmixer virtual user credentials, you can simply authenticate the user to Appmixer and get a token back that you can use to initialize the SDK:

let auth;
if (!profile.appmixerUserName) {
   // First time the user interacts with Appmixer. -> Create a virtual 
   // Appmixer user on the fly.
   const appmixerUserPassword = Math.random().toString(36).slice(-8);
   auth = await appmixer.api.signupUser(profile.email, appmixerUserPassword);
   profile.appmixerUserName = profile.email;
   profile.appmixerUserPassword = appmixerUserPassword;
   // Update your user profile with the newly created Appmixer virtual user credentials.
   await callYourAPIToUpdateUser(profile);
} else {
   // We already have a shadow Appmixer virtual user for our user created. ->
   // Simply authenticate.
   auth = await appmixer.api.authenticateUser(profile.appmixerUserName, profile.appmixerUserPassword); 
}
appmixer.set('accessToken', auth.token);
// Now your SDK is initialized and Appmixer virtual user is ensured.
// We can render our FlowManager.
const flowManager = appmixer.ui.FlowManager({ el: '#my-am-flow-manager' });
flowManager.open();

This is it. Now your web app creates Appmixer virtual users as needed and your users can start interacting with Appmixer widgets.

One disadvantage of the client-side approach is that (for security reasons), you cannot change the user scope (a string that can be used to group users into teams in Appmixer and therefore set common rules e.g. for accessing different set of components for different teams). If you don't require this functionality, you're fine with the client-side approach. If you do, you need to create your virtual users from your backend application using the Appmixer REST API. The next section shows you how you can do that.

Creating Virtual User Account using the REST API

To create new or update existing virtual users using the REST API, use the User endpoints. Since some of the User endpoints cannot be called with a regular user Authentication Bearer token, the first step is to authenticate using any of your admin users and use the admin user token instead:

Authenticate with admin user to get admin access

curl -XPOST "https://api.YOURTENANT.appmixer.cloud/user/auth" -H "Content-type: application/json" -d \
'
{ "username": "myadminuser@example.com", "password": "abc123" }
'

The response contains the user object together with their token:

{
  "user": {
    "id": "583c06511afb7b0016ef120b",
    "username": "myadmin@example.com",
    "isActive": true,
    "email": "myadmin@example.com",
    "plan": "free",
    "vendor": [
      "appmixer"
    ]
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6...."
}

Create a virtual Appmixer user

To create a new virtual user, initiate a POST request to the /user endpoint:

curl -XPOST "https://api.YOURTENANT.appmixer.cloud/user" -H "Content-type: application/json" -d \
'
{
   "username": "john@doe.com",
   "email": "john@doe.com",
   "password": "test123" 
}
'

The response contains the newly created user token:

{
    token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZC..."
}    

Use the token to request the user profile:

curl -XGET "https://api.YOURTENANT.appmixer.cloud/user" -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZC...'

The response contains the user object together with the user ID:

{
  "id": "583c06511afb7b0016ef120b",
  "username": "john@doe.com",
  "isActive": true,
  "email": "john@doe.com",
  "scope": [
    "user"
  ],
  "plan": "free"
}

You can also manually validate that a user has been created in the Appmixer Backoffice interface:

Change the user scope

As you can see, all newly created users have the default user scope. This scope can be replaced by any other string (e.g. ID or slug of a team that you want to group users under). Having a custom scope grouping multiple users allows you to define rules that e.g. limit the particular scope to only a selected set of modules/components (see below). To change the user scope, call the following endpoint passing a list of scopes that you want the user to have. Note that you need to use the admin user token to change a user's scope (for security reasons so that regular users can't change their own scope). You also need to use the user ID that we retrieved from the user profile endpoint in the previous step:

curl -XPUT "https://api.YOURTENANT.appmixer.cloud/users/583c06511afb7b0016ef120b" -H "Content-type: application/json" -H 'Authorization: Bearer ADMIN_USER_TOKEN' -d \
'
{
    "scope": ["acme1"]
}
'

Again, you can validate in the Appmixer Backoffice that the user's scope has indeed changed:

Note that since we created a brand new scope and it's the only one that our new user has, we also need to configure ACL rules for this user so that they are able to create and read flows and access some modules in order to use them in their flows. See the next section on how to set this up. But before we jump into ACL rules, let's just quickly review how you can search for users using the REST API. To find all users with a certain scope, you can call the Users endpoint and filter by scope:

curl -XGET "https://api.YOURTENANT.appmixer.cloud/users?filter=scope:acme1&sort=created:-1&limit=30&offset=0" -H 'Authorization: Bearer ADMIN_USER_TOKEN'Configure ACL rules for a scope

Or you can search users by their username or part of it using the pattern query parameter:

curl -XGET "https://api.YOURTENANT.appmixer.cloud/users?pattern=doe&sort=created:-1&limit=30&offset=0" -H 'Authorization: Bearer ADMIN_USER_TOKEN'

Configure ACL rules for a scope

By default, Appmixer ships with a set of ACL rules that apply for the admin and user scopes. If you don't need to create new scopes to group users, you're usually fine with the default setting. However, since we create a brand new scope acme1, users with this scope won't be able to read and create flows and won't have access to any modules/components.

ACL rules in Appmixer are divided into two categories: routes and components. You can see the two categories when you visit the ACL page of your Appmixer Backoffice interface:

The routes category defines ACL rules that apply to the routes of the Appmixer Engine API (the endpoints). By default, all users with the admin and user scope have access to all the endpoints:

In order for users with our new scope acme1 to be able to access all the endpoints as regular users can, we need to add a new rule. This can be done either via the Backoffice interface ("Add" button):

Or programatically via the Appmixer REST API. A common practice is to first get the existing set of ACL rules for the routes category and if the newly created scope is not in the list, just add it (note again that you need admin user token to manipulate ACL rules):

curl -XGET "https://api.YOURTENANT.appmixer.cloud/acl/routes" -H 'Authorization: Bearer ADMIN_USER_TOKEN'

The response looks something like this:

[
  {
    "role": "admin",
    "resource": "flows",
    "action": [
      "*"
    ],
    "attributes": [
      "*"
    ]
  },
  {
    "role": "user",
    "resource": "flows",
    "action": [
      "*"
    ],
    "attributes": [
      "*"
    ]
  }
]

Since our acme1 scope is not in this list (look for the role attribute), we can add a new rule that allows users with this scope to access their flows:

curl -XPOST "https://api.YOURTENANT.appmixer.cloud/acl/routes" -H "Content-type: application/json" -H "Content-type: application/json" -H 'Authorization: Bearer ADMIN_USER_TOKEN' -d@routes-acl.json

Where our routes-acl.json file looks like this (the Appmixer API currently allows replacing all the rules at once, therefore, for convenience, we stored our rules in a file to make our curl command a little bit more readable):

[
  {
    "role": "admin",
    "resource": "flows",
    "action": [
      "*"
    ],
    "attributes": [
      "*"
    ]
  },
  {
    "role": "user",
    "resource": "flows",
    "action": [
      "*"
    ],
    "attributes": [
      "*"
    ]
  },
  {
    "role": "acme1",
    "resource": "flows",
    "action": [
      "*"
    ],
    "attributes": [
      "*"
    ]
  }
]

At this point, you can even try to sign-in on behalf of this user to the Appmixer Studio interface (https://my.YOURTENANT.appmixer.cloud) to validate that the user is indeed created and that they can use Appmixer:

Note that the user can technically access the Appmixer Studio but since our goal is to embed Appmixer to your own product, your virtual users won't be visiting the Appmixer Studio at all. Instead, they'll be interacting with the embedded Appmixer widgets only. The purpose of the above test is to quickly validate (especially the first time you're creating virtual users programatically) what the user has access to.

Also notice that if you try to create a new flow on behalf of the user by clicking on the "Create flow" button, the list of available modules will be empty:

This is because we haven't yet granted users with the acme1 scope access to any modules/components. To add ACL rules for components, we can follow a similar approach as we did for the ACL routes category but this time we'll do that for the components category. Therefore, we can again do it manually in the Appmixer Backoffice by adding a new rule to the components category. Let's say we'd like to give the user access only to the modules in the appmixer.utils and appmixer.twilio namespaces. We can add two new rules in the Backoffice:

Note the wildcard (* ) character after the module namespace. If we didn't do that, although the user will have access to the module itself, they won't be able to see any components within that module (e.g. appmixer.twilio.sms.SendSMS). The wildcard character makes sure all the components within the appmixer.twilio namespace are matched. If you don't use the wildcard, you can give users access to only a particular set of components within modules instead of the entire module.

Once you save those two rules and create a flow on behalf of the user in the Appmixer studio, you should see the utility and twilio modules displayed:

To add the components rules programatically via the Appmixer REST API, again, first request the current set of modules:

curl -XGET "https://api.YOURTENANT.appmixer.cloud/acl/components" -H 'Authorization: Bearer ADMIN_USER_TOKEN'

where the response looks something like this:

[
  {
    "role": "admin",
    "resource": "*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  },
  {
    "role": "user",
    "resource": "*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  }
]  

And add a new rule to the list so that users in our acme1 scope can access utilities and twilio modules:

[
  {
    "role": "admin",
    "resource": "*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  },
  {
    "role": "user",
    "resource": "*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  },
  {
    "role": "acme1",
    "resource": "appmixer.utils*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  },
  {
    "role": "acme1",
    "resource": "appmixer.twilio*",
    "action": [
      "*"
    ],
    "attributes": [
      "non-private"
    ]
  }
]  

Replace the components ACL rules with the above list:

curl -XPOST "https://api.YOURTENANT.appmixer.cloud/acl/components" -H "Content-type: application/json" -H "Content-type: application/json" -H 'Authorization: Bearer ADMIN_USER_TOKEN' -d@components-acl.json

Sharing Integration Templates with users with a custom scope

Now that we have created a new virtual user, defined and configured a custom scope, we can take advantage of this new scope not only to limit the set of available components for users in this scope but we can also share Integration templates with only users under a certain scope. By default, integration templates are shared with the user scope. This happens when you publish a new integration template in the Wizard builder:

Once you Publish an integration template and visit the Sharing dialog:

You'll notice your integration template has been shared with users under the user scope by default:

To share the Integration template with your custom scope, just change "user" to your own scope instead and click on the Update button:

Now users in the acme1 custom scope will be able to use your integration template:

Summary

In this tutorial, we learned how to create virtual users both using the simple method via the client-side Appmixer JavaScript SDK and also using the more advanced and flexible method via the Appmixer REST API. We learned how to group users, set different access rights for these group of users, especially access to different set of components and integration templates. You should now be ready to embed Appmixer into your own product and create shadow virtual users for your own user accounts.

Last updated