UE Auth Permissions: Code Perspective

What are Permissions Exactly

UE Auth is an identity and access management system which includes the ability to manage permissions.

As such, UE Auth uses its own features to manage access to itself.

Permissions are a simple coupling of a “target” to an “action” with or without resource ownership. Targets and actions can be anything required for the product in question.

Permissions are stored internally to UE Auth as an object but often utilized as an encoded magic string to reduce the amount of information being transferred. As an example, the below object would be coded as “users::update:own”.

  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "coded": "string",
    "product": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "createdAt": "2021-10-14T20:47:32.706Z",
    "createdBy": "string",
    "target": "users",
    "action": "update",
    "ownershipRequired": true,
    "description": "string"
  }

In the above example, if the ownership flag was false, the coding would simply be “users::update”.

This simple modeling of permissions allows for adaptive UIs. As an example, you could use this kind of detailed permissioning system to intelligently render only those components that a user has permission to see on the UI.

That being said, this documentation is specific to the backend and will discuss the concepts from a REST API perspective.

For UE Auth specifically, a number of targets and actions have been defined. Please note that this approach in no way defines how you might define targets and actions for a different product for which UE Auth is managing access.

For all established targets, 4 possible actions have been defined: read, update, create, and delete. Again, this is how we did it and is not prescriptive to your implementation.

For the purposes of UE Auth, these actions correspond with REST methods (GET, PUT/PATCH, POST, DELETE) to determine access to the API and then may be used further downstream in a request for additional data access controls.

This approach is an excellent way to allow for automated middleware access management based on permissions communicated through an access token.

UE Auth Targets and Actions

The following chart explains each target and how the ownership flag impacts the permission. All routes inside UE Auth that require security are secured using the following permissions which are automatically interpreted through the middleware.

The m.access() middleware function explicitly defines a target to couple to the endpoint.

When you see multiple arguments, those targets are processed in a pattern of first, then first-second, and so on. So the targets associated to a permission with m.access(‘user’, ‘organization’) are ‘user’ and then ‘user-organization’.

TargetAvailable Actions (CRUD)DetailsOwnership Impact
groupupdate, read, deleteCRUD operations on AuthGroups. Note that Create is an action reserved for the service admin (ROOT) or is simply opened to the public by setting the environment variable OPEN_GROUP_REG to true.Limits actions to groups to which the requesting party is a member.
group-keysreadThis is a field level permission allowing the holder to see the config.keys of an Auth GroupThis permission only exists with the ownership set to true. It must be your own Auth Group or you must be a “root” user.
accountscreate, update, read, deleteCRUD operation on accounts. Create permission is only required if the AuthGroup is locked. This permission also allows a user to see all organizations they have been added to, accept terms of access from organizations, or delete themselves from organizations.Ownership generally means the request can only be carried out by the account owner.
accounts-organizationupdate, read, deleteThis permission allows someone to take actions against an account that is part of an organization. Specifically, they can search for accounts in the AuthGroup to potentially add to the organization, add an account to the organization, read the account information of someone in the organization, see all accounts in an organization, or remove an account from an organization.Ownership means the person taking action must be part of the organization specified.
userAccessreadThis permission allows a user to query another user’s access (orgs, domains, roles, permission)Query would be limited to the requesting party
clientsread, deleteThese are not the OIDC /reg endpoints, but rather, limited side access to clients within an AuthGroup. The permission allows a user to see those clients or potentially delete one.Caller would have to be the client itself, i.e. a client with a client_credential token. Limited to reading.
operationscreateOperations are a general admin function using the POST (create) method. They allow things like the group rotating its OIDC keys, a user being asked to verify their account, or a client rotating its client_secret or registration_access_token.N/A
operations-reset-user-passwordcreateThe specific operation of being able to trigger a password reset for a user – the result is a notification to that user’s email.N/A
operations-usercreateThe specific operation against a user to verify_account, password_reset, or generate_password (replacing the old password)Caller must be the user in question.
operations-clientcreateThe specific operation against a client to rotate_secret or rotate_registration_access_tokenCaller must be the client in question.
operations-user-organizationcreateThe same as “operations-user” but within the context of an organization.Caller must belong to the organization but does not have to be the user in question.
initialAccessTokencreateAbility to create initialAccessTokens for a variety of reasons, most notably to create new Clients.N/A
organizationscreate, update, read, deleteThis permission allows interaction with organizations in general. All CRUD operations, defining access to a user in the organization, and viewing users in an organizationYou must belong to the organization specified.
organizations-limitedupdateA permission to ensure even if it is your organization, you cannot update certain fields such as the associatedProducts.You must belong to this organization – this target::action combo only comes with the ownership required.
orgUserProfilecreate, update, read, deleteA permission to create and manage organization owned profiles associated to accounts. These are not the same as secured profiles and are administrated by the organization in partnership with the account holder.You must belong to the organization when ownership is required.
domainscreate, update, read, deleteAll CRUD operations of domains within the context of an organization.You must belong to the organization the domain is associated to but do not have to be part of the specific domain.
domains-limitedupdate, read, deleteSame as “domains” but limits access to ensure you actually belong to the domain in question. This permission only exists with ownership enforced.You must belong to the domain to make the request.
productscreate, update, read, deleteAll CRUD operations for products within the context of an AuthGroup.You must be associated to the product by belonging to a domain that has the product associated.
notificationcreate, update, read, deleteAll CRUD operations for notifications which will be sent via the Notification Plugin to a user. This permission allows for all CRUD and the processing of existing unsent notifications.It must be a notification you created.
rolescreate, update, read, deleteAll CRUD operations for roles either solely in the context of the product, or “custom roles” in the context of both the product and an organization. Custom roles have their own API endpoints.You are limited to custom role endpoints that reference an organization and you must belong to the organization referenced.
permissionscreate, read, deletePermissions can be created, read or deleted. No updates are allowed. The “Permissions” permission allows you to manage them within the context of a product.You must be associated to the product these permissions are from by belonging to a domain that has the product associated.

Root Only Targets

The Root AuthGroup is the first AuthGroup created by the owner of the UE Auth service itself. For all SaaS implementations of UE Auth, the owner of the service and the Root AuthGroup is United Effects LLC and not accessible.

The Root AuthGroup has special privileges which extend beyond the normal AuthGroup permissions defined below. If you are setting up your own instance of this service, you will be the owner of your UE Auth Root AuthGroup.

In addition to the permissions above, there is a target called "Plugins" with available actions "Create, Read". Permissions for this target are not included in the product definition created for an authGroup and access is limited to those users in the Root AuthGroup (created when the service is first initialized).

This is also true of the permission "group::create" when the env config "OPEN_GROUP_REG" is false.

Auto Generated Roles and Permissions

Every time you create an AuthGroup, two products are auto generated and associated to that AuthGroup. As an example, let's assume we create an AuthGroup called “Sage Industries”. The two products are:

  • Sage Industries – AuthGroup Admin Portal
  • Sage Industries – Organization Admin Portal

The AuthGroup Admin Portal has all of the permissions mentioned above in the chart auto generated and associated to the portal.

The Organization Admin Portal has a subset generated that excludes things like group, some operations, and so on.

Each product then has roles auto generated with associated permissions as follows:

{
  "groupAdminPortal": [
      {
        "role": "Admin",
        "permissions": ["group::update:own", "group::read:own", "accounts::create", "accounts::update", "accounts::read", "accounts::delete", "accounts-organization::read", "clients::create", "clients::read", "clients::update", "clients::delete", "operations::create", "initialAccessToken::create", "notification::create", "notification::read", "notification::update", "notification::delete", "organizations::create", "organizations::delete", "organizations::update", "organizations::read", "products::create", "products::delete", "products::read", "products::update", "domains::create", "domains::delete", "domains::update", "domains::read", "roles::create", "roles::read", "roles::update", "roles::delete", "permissions::create", "permissions::delete", "permissions::read", "userAccess::create", "userAccess::update", "userAccess::read", "userAccess::delete" ]
      },
      {
        "role": "OrganizationAdmin",
        "permissions": ["accounts::create:own", "accounts::update:own", "accounts-organization::read:own", "accounts-organization::update:own", "accounts::delete:own", "notification::create", "notification::read:own", "notification::update:own", "notification::delete:own", "organizations-limited::update:own", "organizations::read:own", "products::read:own", "domains::create:own", "domains::delete:own", "domains::update:own", "domains::read:own", "roles::create:own", "roles::read:own", "roles::update:own", "roles::delete:own", "permissions::read:own", "userAccess::update:own", "accounts-organization::delete:own", "operations-user-organization::create:own" ]
      }
  ],
  "orgAdminPortal": [
      {
        "role": "OrganizationAdmin",
        "permissions": ["accounts::create:own", "accounts::update:own", "accounts-organization::read:own", "accounts-organization::update:own","accounts::delete:own", "notification::create", "notification::read:own", "notification::update:own", "notification::delete:own", "organizations-limited::update:own", "organizations::read:own", "products::read:own", "domains::create:own", "domains::delete:own", "domains::update:own", "domains::read:own", "roles::create:own", "roles::read:own", "roles::update:own", "roles::delete:own", "permissions::read:own", "userAccess::update:own", "accounts-organization::delete:own", "operations-user-organization::create:own" ]
      }
  ]
}

You can find the actual auto generation JSON here.

Finally, an internal access Organization is auto generated with an associated Domain. Both products are associated to the Organization and Domain.

  • Sage Industries – Organization
  • Sage Industries – Primary Domain

Once this is done, the AuthGroup owner (person creating the group) is associated to the “Sage Industries – Organization”, “Sage Industries – Primary Domain” and the “AuthGroup Admin Portal Admin Role”. This process is what allows the owner to control the AuthGroup.

The purpose of the Organization Admin Portal and associated OrganizationAdmin role is to empower users as administrators of an organization without any context, visibility, or access to the larger functionality of the AuthGroup.

For example, if Sage Industries brings on a customer called Acme Rockets, the Sage Industries AuthGroup Portal Admin would take the following steps:

  1. Create an Organization of type Customer called Acme Rockets
    • This will auto create a domain under Acme Rockets called “Acme Rockets – Administrative Domain”
  2. Associate the Organization Admin Portal product to Acme Rockets
    • This will auto associate the product to the Administrative Domain as well
  3. Create an organization user with a unique email address – [email protected]
  4. Apply the Administrative Domain and the Organization Admin Portal OrganizationAdmin Role to [email protected]

When Jane can now obtain tokens to UE Auth to manage her Organization’s users, but will not have access to anything other than those resources associated to her Organization.

Periodically, the core permissions for these products will change. A version file in the repo hard codes the current version. If the existing data does not match the current version, an update will be required but not auto initiated. Instead, each AuthGroup can check for and initiate the update on their own individually using the REST API. You’ll find these endpoints under the “General Functional” section of the API documentation.

Permissions in Tokens as Claims

When a user is provided access and assigned permissions through a role, those permissions can be requested to come along with the token issued to the user.

To request any access specific data with the token, use the following scopes:

  • access - all organizations, domains, products, roles and permissions attributed to the user
  • access:group - only the group information associated to the user, membership and/or ownership
  • access:organizations - only the organizations attributed to the user
  • access:domains - only the domains associated to the user
  • access:products - only the products associated to the user
  • access:roles - only the roles associated to the user
  • access:permissions - only the permissions associated to the user

In a token, the above scopes determine which of the below corresponding claims are populated:

  • x-access-group
  • x-access-organizations
  • x-access-domains
  • x-access-products
  • x-access-roles
  • x-access-permissions

Where the "access" scope alone will return all of those claims.

If the total data representing a user's access exceeds a limit set in the configuration (ACCESS_OBJECT_SIZE_LIMIT), currently defaulted to 4KB in the code and set to 8KB in the demo environment, the data is not populated and instead a new claim called "x-access-url" is added to the token with a URL link to the API to query the permissions. The token itself will allow that request.

At any point you can query the permissions of a user using their token here: https://docs.unitedeffects.com/reference/validatetoken

Example Token

Your token will be a JWT or Opaque and when decoded, provide the following information. Where you see nested UUID elements, those are organization IDs grouping the products, roles, and permissions. This is just an example:

active

true

sub

xxxxxxxx-yyyy-47cf-8158-zzzzzzzzzzzz

group

xAZkqJppILshpZxAJ4QBC

x-access-group

owner member

x-access-organizations

d2916c50-123c-4cf8-b546-5da44536b5db a496c989-1588-4623-9d7d-23a19483bfe9 52103bb1-8766-40dd-be8d-6592d370f06f 97c38185-49da-4125-837c-21ea67ed4294 e5edc9ee-8569-4dd2-b7d5-67d9e810bea6

x-access-domains

d2916c50-123c-4cf8-b546-5da44536b5db

"e72c6d22-f2e8-4405-b810-ad501815ae1c"

a496c989-1588-4623-9d7d-23a19483bfe9

"996be538-8fb8-4350-9d2d-97a40ecaf27d fc08a69c-4792-48e5-9aa7-156052327a31"

52103bb1-8766-40dd-be8d-6592d370f06f

"cdf155d9-6832-4e0a-936e-b653fd712514 e7f22d0a-bef9-4a25-9da5-1f62e50cecd5 77f11b42-b3ea-4d69-875b-b43a098d0003"

97c38185-49da-4125-837c-21ea67ed4294

"8e85adb9-9649-4cb5-8b5d-2d401be373b2"

e5edc9ee-8569-4dd2-b7d5-67d9e810bea6

"e8078604-f42b-4e1d-87ad-e50553845930 45038ba5-a257-4753-9629-905bc39a957d"

x-access-products

d2916c50-123c-4cf8-b546-5da44536b5db

"dd3d8f04-ce9c-4329-8d06-03287ad73ef5,DhSyZyKiCs ba5d8bed-7699-4a8c-a156-7d4159ab7e38,AUm8cS2A0o 3a95bf2f-d66f-4900-a55e-418577b8ba7a 31e876b8-8277-44d1-970e-c03d94e57ee7,UD-019WTK7 0bd244cc-d94a-4691-9cb3-b4a349f4c4aa,u1MZIsUhY- 25f39f25-090e-472c-818e-5f56c81eb848,Hz71IwoXtZ"

a496c989-1588-4623-9d7d-23a19483bfe9

"1fc5a99d-7a81-4957-b401-b23b3c24449b,sufylvYOoz 3a95bf2f-d66f-4900-a55e-418577b8ba7a,6MFrpsIluP dd0bb2ec-ac1f-4d25-afd1-af6b2c46f8bc,6V4klhG-ku ba5d8bed-7699-4a8c-a156-7d4159ab7e38,AUm8cS2A0o 1fc5a99d-7a81-4957-b401-b23b3c24449b 3a95bf2f-d66f-4900-a55e-418577b8ba7a dd0bb2ec-ac1f-4d25-afd1-af6b2c46f8bc"

x-access-roles

d2916c50-123c-4cf8-b546-5da44536b5db

"DhSyZyKiCs::dHbJeHf6h_ AUm8cS2A0o::9bfAcej87l UD-019WTK7::5MfbzbLVNv u1MZIsUhY-::fHdvndijws Hz71IwoXtZ::D1HOpXlkU6"

a496c989-1588-4623-9d7d-23a19483bfe9

"sufylvYOoz::Sj2FA5nK9E AUm8cS2A0o::9bfAcej87l 6MFrpsIluP::zjhh2OJ5hJ 6V4klhG-ku::KiykJ4azQJ"

x-access-permissions

member

"xHZkqKppIHshpZxAJ9QBU-member:::accounts::update:own xHZkqKppIHshpZxAJ9QBU-member:::accounts::read:own xHZkqKppIHshpZxAJ9QBU-member:::accounts::delete:own xHZkqKppIHshpZxAJ9QBU-member:::useraccess::delete:own xHZkqKppIHshpZxAJ9QBU-member:::useraccess::read:own xHZkqKppIHshpZxAJ9QBU-member:::operations-reset-user-password::create xHZkqKppIHshpZxAJ9QBU-member:::operations-user::create:own xHZkqKppIHshpZxAJ9QBU-member:::operations-invite::create:own xHZkqKppIHshpZxAJ9QBU-member:::accounts-notification::read:own"

d2916c50-123c-4cf8-b546-5da44536b5db

"DhSyZyKiCs:::group::update:own DhSyZyKiCs:::group::read:own DhSyZyKiCs:::group-keys::read:own DhSyZyKiCs:::accounts::create DhSyZyKiCs:::accounts::update DhSyZyKiCs:::accounts::read DhSyZyKiCs:::accounts::delete DhSyZyKiCs:::accounts-organization::read DhSyZyKiCs:::clients::create DhSyZyKiCs:::clients::read DhSyZyKiCs:::clients::update DhSyZyKiCs:::clients::delete DhSyZyKiCs:::operations::create DhSyZyKiCs:::initialaccesstoken::create DhSyZyKiCs:::notification::create DhSyZyKiCs:::notification::read DhSyZyKiCs:::notification::update DhSyZyKiCs:::notification::delete DhSyZyKiCs:::organizations::create DhSyZyKiCs:::organizations::delete DhSyZyKiCs:::organizations::update DhSyZyKiCs:::organizations::read DhSyZyKiCs:::products::create DhSyZyKiCs:::products::delete DhSyZyKiCs:::products::read DhSyZyKiCs:::products::update DhSyZyKiCs:::domains::create DhSyZyKiCs:::domains::delete DhSyZyKiCs:::domains::update DhSyZyKiCs:::domains::read DhSyZyKiCs:::roles::create DhSyZyKiCs:::roles::read DhSyZyKiCs:::roles::update DhSyZyKiCs:::roles::delete DhSyZyKiCs:::permissions::create DhSyZyKiCs:::permissions::delete DhSyZyKiCs:::permissions::read DhSyZyKiCs:::useraccess::read DhSyZyKiCs:::clientaccess::read DhSyZyKiCs:::clientaccess::update DhSyZyKiCs:::clientaccess::delete DhSyZyKiCs:::orguserprofile::create DhSyZyKiCs:::orguserprofile::read DhSyZyKiCs:::orguserprofile::update DhSyZyKiCs:::orguserprofile::delete AUm8cS2A0o:::accounts::create:own AUm8cS2A0o:::accounts::update:own AUm8cS2A0o:::accounts-organization::read:own AUm8cS2A0o:::accounts-organization::update:own AUm8cS2A0o:::accounts::delete:own AUm8cS2A0o:::notification::create AUm8cS2A0o:::notification::read:own AUm8cS2A0o:::notification::update:own AUm8cS2A0o:::notification::delete:own AUm8cS2A0o:::organizations-limited::update:own AUm8cS2A0o:::organizations::read:own AUm8cS2A0o:::products::read:own AUm8cS2A0o:::domains::create:own AUm8cS2A0o:::domains::delete:own AUm8cS2A0o:::domains::update:own AUm8cS2A0o:::domains::read:own AUm8cS2A0o:::roles::create:own AUm8cS2A0o:::roles::read:own AUm8cS2A0o:::roles::update:own AUm8cS2A0o:::roles::delete:own AUm8cS2A0o:::permissions::read:own AUm8cS2A0o:::useraccess::read:own AUm8cS2A0o:::accounts-organization::delete:own AUm8cS2A0o:::operations-user-organization::create:own AUm8cS2A0o:::orguserprofile::create:own AUm8cS2A0o:::orguserprofile::read:own AUm8cS2A0o:::orguserprofile::update:own AUm8cS2A0o:::orguserprofile::delete:own UD-019WTK7:::subject::read UD-019WTK7:::subject::update UD-019WTK7:::subject::delete UD-019WTK7:::subject::create UD-019WTK7:::subject-operation::request UD-019WTK7:::stream::read UD-019WTK7:::stream::create UD-019WTK7:::stream::delete UD-019WTK7:::stream::update UD-019WTK7:::stream-operation::request UD-019WTK7:::access::read:own UD-019WTK7:::access::update:own UD-019WTK7:::access::delete:own UD-019WTK7:::access::create UD-019WTK7:::access::read UD-019WTK7:::access::update UD-019WTK7:::access::delete UD-019WTK7:::access-operations::request UD-019WTK7:::access-operations::request:own UD-019WTK7:::stream-consumer::read UD-019WTK7:::stream-consumer::delete UD-019WTK7:::destructive-operation::request UD-019WTK7:::config::update u1MZIsUhY-:::audit::read u1MZIsUhY-:::audit::delete Hz71IwoXtZ:::webhook::read Hz71IwoXtZ:::webhook::create Hz71IwoXtZ:::webhook::delete"

a496c989-1588-4623-9d7d-23a19483bfe9

"sufylvYOoz:::invoices::read sufylvYOoz:::invoices::updated sufylvYOoz:::invoices::delete:own AUm8cS2A0o:::accounts::create:own AUm8cS2A0o:::accounts::update:own AUm8cS2A0o:::accounts-organization::read:own AUm8cS2A0o:::accounts-organization::update:own AUm8cS2A0o:::accounts::delete:own AUm8cS2A0o:::notification::create AUm8cS2A0o:::notification::read:own AUm8cS2A0o:::notification::update:own AUm8cS2A0o:::notification::delete:own AUm8cS2A0o:::organizations-limited::update:own AUm8cS2A0o:::organizations::read:own AUm8cS2A0o:::products::read:own AUm8cS2A0o:::domains::create:own AUm8cS2A0o:::domains::delete:own AUm8cS2A0o:::domains::update:own AUm8cS2A0o:::domains::read:own AUm8cS2A0o:::roles::create:own AUm8cS2A0o:::roles::read:own AUm8cS2A0o:::roles::update:own AUm8cS2A0o:::roles::delete:own AUm8cS2A0o:::permissions::read:own AUm8cS2A0o:::useraccess::read:own AUm8cS2A0o:::accounts-organization::delete:own AUm8cS2A0o:::operations-user-organization::create:own AUm8cS2A0o:::orguserprofile::create:own AUm8cS2A0o:::orguserprofile::read:own AUm8cS2A0o:::orguserprofile::update:own AUm8cS2A0o:::orguserprofile::delete:own 6MFrpsIluP:::user::read 6MFrpsIluP:::user::update 6MFrpsIluP:::user::delete 6V4klhG-ku:::users::read"

client_id

7ccd1d8b-7eb6-46f0-bfe6-20d6bf67bcea

exp

1686784342

iat

1686780742

iss

https://auth.unitedeffects.com/xAZkqJppILshpZxAJ4QBC

scope

openid access email username

token_type

Bearer