Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Overview of Fortified ID Forms
Forms is an application for digitizing process flows. Examples can be creating users (e.g. employees, consultants, partners), editing users or listing "my users" or "my groups". With Forms you get access to a tool to create web-based flows to delegate the administration to the users responsible for certain information in a simple way.
With Forms, you can also build self-service flows and self-registration of users. In case of self-registration, a user proves himself with e.g. BankID where information is extracted and used to allow the user to create their own account.
We have a number of movies on how to work with forms in different scenarios. (note. All movies are in Swedish.)
Forms is a comprehensive Identity and Access Management (IAM) solution designed to streamline and adapt to the specific workflows of your organisation.
The modern landscape of IAM requires a balance between automation and control, and Forms offers both in a way that aligns with your internal processes. IAM solutions today need to be flexible enough to manage the complexity of access control across an organisation, especially as digital environments become more intricate and regulated. Forms IAM addresses this by providing customisable workflows that can be fully automated or augmented with manual checkpoints, ensuring both efficiency and accuracy. This flexibility is crucial in industries with stringent compliance requirements, where every access decision needs to be carefully monitored and validated. Forms IAM is available both on-premises and in the cloud, giving you the flexibility to deploy the solution in the environment that best suits your infrastructure and security requirements. Whether you are looking to maintain full control over your data in an on-prem deployment or leverage the scalability and convenience of the cloud, Forms IAM adapts to your strategy.
Additionally, Forms IAM integrates seamlessly with a wide range of common identity providers and data sources, including Entra ID (formerly Azure Active Directory), Google Cloud Identity, Microsoft Azure, Active Directory, and other leading platforms. This ensures that you can easily manage and centralise access controls across your existing ecosystems, without the need for complex custom integrations. The system allows administrators to configure workflows to match existing processes within the company. Whether it’s handling new employee onboarding, access revocation, or ongoing entitlement reviews, each flow can be automated for speed or include manual approval steps for sensitive actions. This adaptability ensures that the solution integrates seamlessly with your organisation’s existing protocols, rather than forcing a rigid, predefined process onto your teams. With scalable operations, capable of managing identity and access across both small businesses and large enterprises, Forms IAM can evolve alongside your organisation as it grows or its requirements change. In today’s rapidly evolving security environment, having a robust yet flexible IAM system like Forms ensures that your organisation can handle access control efficiently while maintaining the level of precision and oversight necessary for security and compliance.
Other products from Fortified ID related to Forms
Automation provides the ability to read data from one or more systems, change or influence the data and then write it to one or more source systems. Examples could be reading data from an HR system and looking for newly created users, reading in these users and creating them in, for example, Active Directory, Google or Microsoft Entra ID. All without the influence of an administration or user.
Attest adds for Forms and Automation the ability to bring in approval flows. Instead of a user being created/changed directly, one or more users must approve this change.
An example could be requesting access to a group that protects a resource where, for example, a group administrator/owner must approve who gets access to the resource.
The solution can be installed locally, in the cloud or as a hybrid solution. The ability to easily move the solution between test and production environments has been made extremely easy. Read more about automation in our technical documentation.
Password Reset from Fortified ID simplifies the management of secure password reset for your organization.
Users can easily and securely create a new password through self-service without having to contact their employer's IT support.
Users with personnel responsibility (manager, teacher, partner/consultant manager) can reset passwords on behalf of another user.
Your organization becomes more efficient as the time that the end user does not have access can be greatly shortened. In addition, IT personnel can also devote themselves to more constructive and proactive work.
This section how to do a new installation or an upgrade of a Fortified ID product.
Supported target plattforms are:
Container (docker, kubernetes etc.)
Linux 64-bit
Windows 64-bit
Access to media is provided by Fortified ID support. Credentials consist of a username and an access token which are used when downloading the artefacts.
After successful installation, verify access to http://<installation_host>:8080.
A simple welcome page should be displayed.
Basic controls are comparable to simple HTML inputs, such as checkboxes.
Check the release notes to discover the latest updates and improvements in this version.
If there are any breaking changes included in this release, carefully review them before upgrading to understand how they may impact your installation and to prepare for any necessary adjustments before or after the upgrade.
The Forms module is, apart from delivering it's functionality, also a HTTP modul which means it inherits much configuration from basic HTTP module.
Generic HTTP module configuration is found here https://docs.fortifiedid.se/modules/configuration
Forms module handles loading of multiple Flow. Multiple instances of Forms module can be deployed.
Advanced controls are more like mini-applications with specific goals. For example, they could display a list of Entra-ID users or groups as the first step in a Flow.
Any form can be configured for attestation. In essence just send the collected form data to attestation persistence and let one ore more persons verify and reject or accept.
Certain operations or flows may be deemed sensitive or require additional oversight before proceeding. This is where attestation might come in handy.
Attestation lets you define manual oversight be one ore persons before any kind of automation is performed.
Attestation is a flow and defined using built in functionality.
Attestors are notified via email, with the relevant data for verification packaged in a PDF file. Each PDF is tailored specifically for its respective flow, making the information clear, accessible, and easy to review. After a flow is successfully attested, the PDF document can be sent to an external archiving system for secure, long-term storage. This process ensures that all documentation is systematically preserved and readily available for future reference or audits.
This will describe how to configure a flow using attestation
WorkOrder module deployed.
Create a flow used for attestation (accept/reject) using Attestor control.
Configure last PIPE sending data to work order database and possible notifying user.
Configure one accept pipe to be executed once the work order is attested
Configure one reject pipe to be executed if order is rejected
Instead of performing updates directly, data used must be send to work-order database. Two thing are required for this:
A PDF file used to visualise what is about to happen if accepted. Either use Html2Pdf valve for dynamic creation or use a static PDF file.
In the last PIPE in the flow use
Once all attesters accepted the work order, accept pipe will be executed. Any flow data from order creation is present along with additional static data.
Accessing data sent from "work flow accept" is done using pattern {{request.xxx}}
Note that the accept pipe is executed in system context. No session with user data will be present.
It only takes one attester to reject for the order to be rejected. Once rejected the reject pipe is executed. Here you can configure notification if desired.
An input field control, similar to an HTML input.
Below is a screenshot of the control. This is from a create step where an admin has added Clarke and Kent in two input controls. Email and Mobile number has no value yet.
Scenarions when the control can be used:
Like above when an admin creates a new object and needs to add data about the object. You can add data controllers to an inout control to verify correct syntax, an @ for email adress, no characters for an mobile number.
You like to display data about an object. You search an LDAP directory and display a user with data about the user. The input control can be in edit or read-only mode.
Edit Entra ID group, update group members
Use this control to manage users for a selected group. Note. To select the user, which often is done in a previous step, use the control EntraGroupSelect.
An Entra ID module deployed with matching name as defined in "namespace".
An Entra ID identifier, "selected_entra_id", located in either session or flow. Data is taken from session first and flow second. selected_entra_id must reference a Entra ID group.
Use to select one option from a list that is populated from the result of an LDAP query.
Below is a screenshot of the control. This is from a create step where an admin like to choose a manager for a user to be created.
A value picker component, that lets the user select a given value from a list.
The ValuePicker is often used as a drop-down list for admins to select predefined values from. See example below.
Please refer to the common configuration of for information on how to change the look and feel of Forms.
.
Properties for Input control
Update group membership for a selected user.
Use this control to manage groups for a selected user. Note. To select the user, which often is done in a previous step, use the control Selector.
Find an Entra ID group based on search data
Use to find objects in data store, e.g. Active Directory. It performs searches using pipes and stores a selected value for next steps to consume.
Find an Entra ID user based on search data
type
Control implementation, must be Markdown
N/A
data
Text to display
N/A
{
"id": "top_text_label_and_description",
"type": "Markdown",
"data": "# Create an Active Directory user \nEnter information about the user you want to create."
}
type
Control implementation
N/A
id
Unique ID within the flow
N/A
config.required
Must have a value when leaving the step. true/false
false
config.readonly
Open to edit by enduser. true/false
false
config.always_include
Should data be sent to pipe regardless if it is changed or not
false
{
"id": "givenName",
"type": "Input",
"data": "{{{flow.givenName}}}",
"config": {
"type": "string",
"required": true
}
}
The smallest building block in a flow. Typically a Control is represented by some kind of visual component together with data from some data source.
Two categories of controls are available:
Basic
Advanced.
Basic controls are comparable to simple HTML inputs, such as checkboxes.
Advanced controls are more like mini-applications with specific goals. For example, they could display a list of Entra-ID users or groups as the first step in a Flow.
Both types are implemented on the front-end using react-jsonschema-form.
All controls follow the same structure:
{
"type": "<controlType>",
"id": "<controlId>",
"config": {
"required": true,
"read_only": false
},
"data": "<data>",
"ui": {},
"schema": {}
}
type: Defines what control to be used.
id: Unique identifier to the current flow. In subsequent pipe calls the id is sent to the pipe along with value(s) from the control and accessed in the piped using {{request.<id>}}
config: Block of control-specific configuration. Se each control for appropriate values.
data: Value to be injected in control.
ui: Any additional ui-related data sent to frontend, unfiltered. See https://rjsf-team.github.io/react-jsonschema-form/ UISchema for more information. Typically this is used for layout management.
schema: Any additional control-related data not available in current control implementation.
Data binding is typically done using "data" configuration for a control. Most likely date is set by using some template {{flow.givenName}}.
Use to find objects in data store, e.g. Active Directory. It performs searches using pipes and stores a selected value for next steps to consume.
type
Must be Selector
N/A
pipe_id
Id of pipe searching for objects
Same as control id
columns
What columns to be displayed in UI.
N/A
submit_on_change
Should selection of an item move to next step. true/false
true
search
Should user be able to enter custom search data.
false
{
"id": "selector",
"type": "Selector",
"config": {
"search": true,
"columns": ["displayName","mail","givenName"],
"pipe_id": "find_my_groups"
}
}
To populate list of items in UI a pipe must be executed. List of items returned should at least contain properties defined in columns.
Data sent to pipe is:
search - containing user input if config -> search is set to true
columns - comma separated string of defined columns
Return data must be in a form of a list of items.
When pressing Select, data exposed to flow is found using key if control id. Value is item id returned from pipe
To install on Linux, click the following link: https://docs.fortifiedid.se/installation/linux
When installation is completed, verify the following:
Start the service by running <installation_path>/FortifiedID/forms/customer/bin/start.sh
Verify by accessing http://localhost:8080/forms/demo1 or http://localhost:8080/forms/demo2
Stop the service by running <installation_path>/FortifiedID/forms/customer/bin/stop.sh
By default accessing a Flow requires authentication. Any authentication is expected to be handled by a trusted SAML IDP. Once authenticated, authorisation is based on the incoming SAML assertion.
In order for authentication to work, a SAML SP authenticator needs to be configured. Also, SAML SP need to share first part of URI in with Forms module.
Forms module has "http_context" configured to "/forms". The SAML must have it's "http_context" set to "/forms/xxx" ("/forms/auth" is a good pattern).
Typically the properties regarding authentication in Forms module will look something like this:
"http_context": "/forms",
"http_auth_redirect_url": "/forms/authn/login",
On the SAML SP side configuration will look like this:
"http_context": "/forms/authn",
"success_location": "/forms/",
Once the user is authenticated data from incoming assertion vill be transfered to the session.
NameID vill be the users login identifier. Other attributes will be put in the session where multivalued attributes is merged into a comma separated list.
Once authenticated all users by default can access a Flow. Restricting is based on roles attribute in the incoming assertion. By using the "requires_role" configuration parameter on the Flow restriction control is performed comparing the incoming "roles" in the assertion and data in "requires_role" for the Flow.
One value of "role" must match "requires_role" in order for user getting access.
When using forms there are som valves only included in Forms
To install on Windows, click the following link: https://docs.fortifiedid.se/installation/windows
When installation is completed, verify the following:
In Windows Services, verify that Fortified ID <product name> service exists
In file system, verify that drive:\..\FortifiedID\<product name> exits
Note. Starting, stopping, and restarting the service are handled by Windows Services.
A number of modules are included but may not be required in all scenarios.
AuthN, version 2024.93 - details is found here https://docs.fortifiedid.se/authn
Pipes, version 2024.115 - details are found here https://docs.fortifiedid.se/pipes/
Http client, version 2024.72 - details is found here https://docs.fortifiedid.se/httpclient/
JDBC client, version 2024.72 - details are found here https://docs.fortifiedid.se/jdbcclient/
Ldap client, version 2024.72 - details are found here https://docs.fortifiedid.se/ldapclient/
CEF module, version 2024.72 - details is found here https://docs.fortifiedid.se/cef/
Node module, version 2024.72 - details is found here https://docs.fortifiedid.se/node/
SMTP module, version 2024.72 - details are found here https://docs.fortifiedid.se/smtp/
Entra ID module, version 2024.35 - details are found here https://docs.fortifiedid.se/entraid
Workflow module, version 2024.58 - details are found here https://docs.fortifiedid.se/workorders
Only Node is started by default. Modules have to be added in the configuration in order to be started.
The key components and how they relate to each other.
On a high level, Forms delivers well defined "apps" with the soul purpose simplifying a process related to an "IAM-problem". Each app is called a Flow. A Flow have a set of basic properties. For example who may access, is it public, how do it consume authentication.
Flow consists of a number of Steps. Each Step aims to guide the end user through the process. A simple Step could just consists of read only data about a user or a group.
Every Step includes a number of Controls. A Control is some kind graphical entity used to let users read or write data. Just like a Flow or a Step a Control has a number of properties that will define it's behaviour.
By combining Flow, Step & Control small well-defined IAM apps can be built fast with instant added value.
When a user wants to do something in the UI, such as retrieve or write data to a data source or process data, a pipe can be used. A pipe consists of a number of valves that can retrieve, write or process data. Pipes and valves are something that is found in all Fortified ID products and are shared between the products, so if you have knowledge of this from one of our other products, it works the same in Forms.
Forms comes with ha default layout. It places controls from left to right.
All steps and summary pages use a layout grid with a base column width of 12. All controls, or children, can be specified to have different sizes and multiple breakpoints for different screen sizes.
All controls (or children of the grid) have a base width of 12, meaning that they fill the entire width of the grid. A child with the width of 6 will occupies half of the grid, a child with the width of 8 will occupy 2/3s of the grid.
The grid will fill its columns from left to right and fit up to 12 columns in each "row".
Sizes for the controls can be set in the ui [SKRIV HÄR, måste kanske ändra en grej i hur man konfar kommer jag på nu.]
All controls will be rendered into the layout according to the order that they are defined.
Each breakpoint (a key) matches with a fixed screen width (a value):
xs, extra-small: 0px
sm, small: 600px
md, medium: 900px
lg, large: 1200px
xl, extra-large: 1536px
For more advanced layout options you can also configure a "ui:grid"
property on the ui for the step.
Using the "ui:grid"
all other rendering will be bypassed, and only items found in the "ui:grid"
will be rendered.
With "ui:grid"
it is also possible to nest grids.
"ui": {
"ui:grid": {
"spacing": 3,
"items": [
{
"size": 12,
"spacing": 2,
"items": [
{
"size": { "xs": 12, "sm": 6 },
"spacing": 3,
"items": [{ "item": "firstName" }, { "item": "lastName" }]
},
{
"size": { "xs": 12, "sm": 6 },
"items": [{ "item": "helpText" }]
}
]
},
{
"items": [
{ "size": 8, "item": "address" },
{ "size": 4, "item": "postalCode" }
]
}
]
}
}
Use to display text from a text file. Markdown is supported as well as templating: {{flow.xxxx}} etc. Currently translation is not supported
Example markdown:
# A Big Heading
Here’s some **bold text** to highlight something important and *italic text* to emphasize something else.
We can also *combine* **multiple styles** if we want to be extra clear.
## A Smaller Heading
1. **Item One**: A significant point.
2. *Item Two*: A slightly less important point.
3. ~~Item Three~~: An invalid point.
### An Even Smaller Heading
Here’s a code block to show an example of code:
```javascript
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet('World');
Edit Entra ID user, update group membership.
This control works in conjunction with EntraID module. It must be installed.
Object array, "entra_pending_remove" - contains data on what groups to remove from user.
Object array, "entra_pending_add" - contains data on what groups add to user.
Array data will ha the syntax:
[{"id":"1234567","displayName":"Group 1"}]
Markdown is a lightweight markup language that you can use to add formatting elements to a step.
Add one or several labels and/or descriptions text elements to a step. Example below shows a markdowns example, one label and one description.
The example can be added as one markdown or two separate markdowns.
Note. When using several markdowns in one step, make sure the id is unique.
Click following link for a number of examples on how to use markdown in a step.
Use to display text from a text file. Markdown is supported as well as templating: {{flow.xxxx}} etc. Currently translation is not supported
type
Must be EntraUserEditGroupMember.
N/A
namespace
Identifier of EntraID module to use
default
columns
List array with columns to display
["displayName","description"]
change_is_required
Force admin to update user, true/false
false
{
"id": "entraGroupSelector",
"type": "EntraGroupSelector",
"config": {
"namespace": "tenant1",
"columns": [
"displayName",
"description"
]
}
}
type
Backend implementation
N/A
config.file_template
File to load
N/A
ui.ui:widget
What frontend widget to use. Use "MarkdownWithBackendWidget"
MarkdownWithBackendWidget
{
"id": "textarea1",
"type": "TextArea",
"config": {
"file_template": "<relative_or_absolute_path>/template.txt"
}
}
A value picker component, that lets the user select a given value from a list.
type
Control implementation
N/A
id
Unique ID within the flow
N/A
config.required
Must have a value when leaving the step. true/false
false
config.readonly
Open to edit by enduser. true/false
false
config.default_value
This value is selected per default
config.options
Select options (list of objects)
N/A
config.options.title
An option title
N/A
config.options.value
An option value
N/A
{
"id": "identificationMethod",
"type": "ValuePicker",
"config": {
"required": true,
"default_value": "{{ flow.preferred_auth }}"
"options": [
{
"title": "Username/Password",
"value": "uidpwd"
},
{
"title": "BankID",
"value": "bankid"
}
]
}
}
{
"id": "chooseRole",
"type": "ValuePicker",
"ui": {
"ui:size": {
"md": 6
}
},
"config": {
"required": false,
"options": [
{
"title": "Human Resources",
"value": "hr"
},
{
"title": "Sale",
"value": "sale"
},
{
"title": "IT",
"value": "it"
},
{
"title": "Engineering",
"value": "engineering"
}
]
}
}
Manage group members for a selected Active Directory group.
An LdapClient module deployed with matching name as defined in "namespace".
type
Must be
ActiveDirectoryGroupEditGroupMember
N/A
namespace
Identifier of LdapClient module to use
"default"
columns
List array with columns to display
["displayName", "mail", "mobile"]
base_dn
Search base DN.
"DC=company,DC=local"
scope
Search scope.
"SUB"
current_filter
Search filter. Used to fetch current members of the group.
N/A
available_filter
Search filter. Used to fetch available members of the group.
N/A
{
"id": "adGroupMember",
"type": "ActiveDirectoryGroupEditGroupMember",
"config": {
"namespace": "ldap_client_1",
"base_dn": "DC=company,DC=local",
"scope": "SUB",
"current_filter": "memberOf={{{flow.findMyActiveDirectoryGroups}}}",
"available_filter": "(&(|(objectClass=user)(objectClass=group))(!(memberOf={{{flow.findMyActiveDirectoryGroups}}})))",
"columns": [
"displayName",
"mail",
"sAMAccountName",
"mobile"
]
}
}
This control works in conjunction with LdapClient module. It must be installed.
Object array, "ad_pending_remove" - contains data on what members to remove from group.
Object array, "ad_pending_add" - contains data on what members to add to group.
Example data in finalize pipe:
...
"ad_pending_add" : [
{
"id" : "CN=Felix Andreasson,OU=Demo,DC=company,DC=local",
"displayName" : "Felix Andreasson"
},
{
"id" : "CN=Eva Ek,OU=Demo,DC=company,DC=local",
"displayName" : "Eva Ek"
}
],
"ad_pending_remove" : [
{
"id" : "CN=Lance Armsson,OU=Demo,DC=company,DC=local",
"displayName" : "Lance Armsson"
},
{
"id" : "CN=Britt Thomasson,OU=Demo,DC=company,DC=local",
"displayName" : "Britt Thomasson"
}
]
...
ActiveDirectoryAddGroupToMembers
Used to add group members to a specified group
ActiveDirectoryRemoveGroupFromMembers
Used to remove group members from a specified group
Find an Entra ID user based on search data
type
Must be EntraGroupSelect.
N/A
namespace
Identifier of EntraID module to use
default
columns
List array with columns to display
["displayName", "mail", "mobilePhone", "companyName", "department"]
search_attributes
List array with columns used for searching. Search is done using "starts with".
["displayName","mail"]
ui.ui:search
Should search input be visible for end user, true/false
true
owned_users_only_attribute
If set, users will be filtered based on the attribute.
N/A
{
"id": "entraUserSelect",
"type": "EntraUserSelect",
"config": {
"namespace": "tenant1",
"columns": [
"displayName",
"description"
]
},
"ui": {
"ui:search": false
}
}
This control works in conjunction with EntraID module. It must be installed.
Set owned_users_only_attribute will cause control match the data from owned_users_only_attribute. Matching is done using data from owned_users_only_attribute and entra_identifier.
entra_identifier is read from session or flow. Session read first then flow.
Settings "owned_users_only_attribute":"manager", will match value from entra_identifier with id in "manager". Only showing users where user is set to owner.
"selected_entra_id" - id of selected group
"selected_entra_displayName" - display name of selected group.
Creates a work order for later acceptance or dismissal. To each work order there is a pdf file containing details about the order.
namespace
Namspace of Workorders module
default
order_type
Arbitrary type of the order. Use a-z and "_". This is used for selection later on.
N/A
display_name
Used in UI for presentation.
N/A
description
Used in UI for presentation.
N/A
body
Any data one might need for later when processing the work order. It can use both static and expanded data. See example below
N/A
properties
Meta data about the order. Example is name & description.
N/A
order_file_name
Just the name of the PDF file describing the order. Location of the order file is handled by the work orders module
N/A
attestors
Json array of identifiers that can accept or dismiss the order.
N/A
originator
Identifier who created the order.
N/A
approval_policy
Allowed value is one of: ATTESTED_ANY or ATTESTED_ALL
ATTESTED_ALL
accept_pipe
Pipe to execute on accept
N/A
reject_pipe
Pipe to execute on reject
N/A
{
"name": "WorkOrderCreate",
"config": {
"namespace": "default",
"order_type": "CreateAccount",
"display_name": "Create account",
"description": "Account creation requested",
"order_file_name": "{{item.pdf_file}}",
"specification_name": "",
"approval_policy": "ATTESTED_ANY",
"body": {
"data": "for",
"some": "pipe"
},
"attestors": [
"jack",
"jill"
],
"originator": "lord_hemlet",
"accept_pipe": "order_accepted_pipe",
"reject_pipe": "order_rejected_pipe"
}
}
Data used for the accept/reject pipe is stored in the body property. It is stored as a Json object and will be available att process time for the order.
Default data in the body is everything available in the request when calling pipes for work order creation.
Excluded data are properties starting with "__".
When creating an order the body is logged and visible if set in debug.
Custom pattern for just work order valves is fortified.flow.api.pipes
this can be used only to enable debug for work order.
Contains details of the order and is mandatory. Location of the file should not be a part of order_file_name. It must be located in pre configured location.
Work orders module must be enabled for valve to function:
Find an Entra ID group based on search data
type
Must be EntraGroupSelect.
N/A
namespace
Identifier of EntraID module to use
default
columns
List array with columns to display
["displayName","description"]
search_attributes
List array with columns used for searching. Search is done using "starts with".
["displayName","mail"]
ui.ui:search
Should search input be visible for end user, true/false
true
owned_groups_only_attribute
If set, groups will filtered based on the attribute.
N/A
{
"id": "entraGroupSelect",
"type": "EntraGroupSelect",
"config": {
"namespace": "tenant1",
"columns": [
"displayName",
"description"
]
},
"ui": {
"ui:search": false
}
}
This control works in conjunction with EntraID module. It must be installed.
Set owned_groups_only_attribute will cause control match the data from owned_groups_only_attribute. Matching is done using data from owned_groups_only_attribute and entra_identifier.
entra_identifier is read from session or flow. Session read first then flow.
Settings "owned_groups_only_attribute":"owners", will match value from entra_identifier with id in "owners". Only showing groups where user is set to owner.
"selected_entra_id" - id of selected group
"selected_entra_displayName" - display name of selected group.
Use to select one option from a list that is populated from the result of an LDAP query.
type
Must be ActiveDirectorySelectOneValue
N/A
config.required
Must have a value when leaving the step. true/false
false
config.readonly
Open to edit by enduser. true/false
false
config.base_dn
Search base DN
config.scope
Search scope
config.attributes
Query these attributes
config.pre_filter
Display current value if present
config.filter
Query filter
config.display_key
This attribute is displayed to the user
config.value_key
This attribute is the selected value.
{
"id": "selectedManager",
"type": "ActiveDirectorySingleSelect",
"config": {
"attributes": [
"displayName",
"sAMAccountName"
],
"base_dn": "OU=Product_Testing,DC=company,DC=local",
"scope": "SUB",
"pre_filter": "(distinguishedName={{flow.manager}})",
"filter": "(&(|(givenName={{search_query}})(sn={{search_query}}))(!(sAMAccountName={{flow.selectedUser}})))",
"display_key": "cn",
"value_key": "distinguishedName"
}
}
The search filter is a template that has access to all data that is available in the flow. Additionally, the template can use the parameter search_query
, that contains the user input.
The attributes defined by display_key
and value_key
are always queried.
{
"id": "top_text_label_description",
"type": "Markdown",
"data": "# Create an Active Directory user \nEnter information about the user you want to create."
}
{
"id": "top_text_label",
"type": "Markdown",
"data": "# Create an Active Directory user"
},
{
"id": "top_text_description",
"type": "Markdown",
"data": "Enter information about the user you want to create."
}
Update group membership for a selected user.
An LdapClient module deployed with matching name as defined in "namespace".
This control works in conjunction with LdapClient module. It must be installed.
Object array, "ad_pending_remove" - contains data on what groups to remove from user.
Object array, "ad_pending_add" - contains data on what groups to add to user.
Array data will have the syntax:
Valves used in finalize pipe
ActiveDirectoryAddMemberToGroups
Used to add a single group member to groups
ActiveDirectoryRemoveMemberFromGroups
Used to remove a single group member from groups
This section includes the main parameters for the Forms module.
type
Must be ActiveDirectoryUserEditGroupMember
N/A
namespace
Identifier of LdapClient module to use
default
columns
List array with columns to display
["cn","description"]
change_is_required
Force admin to update user, true/false
false
base_dn
Search base DN.
"DC=company,DC=local"
scope
Search scope.
"SUB"
current_filter
Search filter. Used to fetch all groups the the user is a member of.
N/A
available_filter
Search filter. Used to fetch available groups.
N/A
"ad_pending_add": [
{
"id": "CN=AWS administrator,OU=access_review,OU=Governance,OU=IdM_demo,OU=Product_Testing,DC=company,DC=local",
"description": "Test",
"cn": "AWS administrator",
"sAMAccountName": "AWS administrator"
},
{
"id": "CN=Cert Publishers,CN=Users,DC=company,DC=local",
"description": "Members of this group are permitted to publish certificates to the directory",
"cn": "Cert Publishers",
"sAMAccountName": "Cert Publishers"
}
],
"ad_pending_remove": [
{
"id": "CN=Access Control Assistance Operators,CN=Builtin,DC=company,DC=local",
"cn": "Access Control Assistance Operators",
"sAMAccountName": "Access Control Assistance Operators",
"description": "Members of this group can remotely query authorization attributes and permissions for resources on this computer."
}
]
{
"id": "adUserGroupMember",
"type": "ActiveDirectoryUserEditGroupMember",
"config": {
"namespace": "ldap_client_1",
"base_dn": "DC=company,DC=local",
"current_filter": "(&(objectClass=group)(member={{{flow.findMyActiveDirectoryUsers}}}))",
"available_filter": "(&(objectClass=group)(!(member={{{flow.findMyActiveDirectoryUsers}}})))",
"columns": [
"cn",
"sAMAccountName"
]
}
}
name
Must be Forms
N/A
http_context
What context is application served under.
/forms
webroot_dir
Where to load web resources from.
web
http_auth_redirect_url
Where to send the user for authentication
/forms/authn/login
overlay_dir
Where to load the overlayed resources from.
N/A
flows
An array with file path to flows to be loaded. Recommended is using @include directive.
N/A
verbose_logs
Array with string values. Possible values are
"flow","session","controls"
[]
{
"name": "Forms",
"config": {
"http_port": "8090",
"overlay_dir": "/config/resources_external/overlays",
}
}
{
"name": "Forms",
"config": {
"flows": "@include:flows/*/*/flow.json",
"http_listener": "default",
"logout_endpoint_url": "${globals.logout_endpoint_url}",
"overlay_dirs": [
"${system.customer_home}/overlay/"
],
"verbose_logs": [
"flow",
"session"
]
}
}
Steps are comparable to pages in a form, where each step includes sections that focus on a specific area. By linking steps, one can create highly customizable IAM solutions.
A step is represented by a json object. Steps can be loaded from one json file or multiple files. Recommended setup is to keep each step in a single file. This will simplify configuration and overview.
Text shown in browser tab. Overrides overlay.
Forms - Fortified ID
Sort order of step. Omitting will result in undetermined execute order.
N/A
Used as a robot mitigator. How long before a step is allowed to be posted back to the server. Format conforms to
0
Favicon for this step.
Internal FortifiedID icon
Same as Flow but can override in a step
Empty array[]
List if controls for this step
N/A
Pipe to be executed moving to next step.
N/A
Same as for flow but can override in a step.
See Flow
Example step to create a user.
{
"controls": [
{
"id": "top_text_label",
"type": "Markdown",
"data": "# Create an Active Directory user \nEnter information about the user you want to create."
},
{
"id": "givenName",
"type": "Input",
"ui": {
"ui:size": {
"md": 6
}
},
"schema": {
"format": "strict"
},
"config": {
"type": "string",
"required": true
}
},
{
"id": "sn",
"type": "Input",
"ui": {
"ui:size": {
"md": 6
}
},
"schema": {
"format": "strict"
},
"config": {
"type": "string",
"required": true
}
},
{
"id": "mail",
"type": "Input",
"ui": {
"ui:size": {
"md": 6
}
},
"schema": {
"format": "email"
},
"config": {
"type": "string",
"required": true
}
},
{
"id": "mobile",
"type": "Input",
"ui": {
"ui:size": {
"md": 6
}
},
"schema": {
"format": "phone"
},
"config": {
"type": "string"
}
},
{
"id": "chooseRole",
"type": "ValuePicker",
"ui": {
"ui:size": {
"md": 6
}
},
"config": {
"required": false,
"options": [
{
"title": "Human Resources",
"value": "hr"
},
{
"title": "Sale",
"value": "sale"
},
{
"title": "IT",
"value": "it"
},
{
"title": "Engineering",
"value": "engineering"
}
]
}
},
{
"id": "adUserFindManager",
"type": "ActiveDirectorySingleSelect",
"ui": {
"ui:size": {
"md": 6
}
},
"config": {
"attributes": [
"cn"
],
"namespace": "${globals.ldap1_name}",
"base_dn": "${globals.ldap1_flows_search_user_dn}",
"scope": "SUB",
"pre_filter": "(distinguishedName={{flow.manager}})",
"filter": "(cn={{search_query}})",
"value_key": "distinguishedName",
"display_key": "cn"
}
}
]
}
Example step to edit and find users.
{
"controls": [
{
"id": "top_text_label",
"type": "Markdown",
"data": "# Change user\nSelect the user you want to modify"
},
{
"id": "findActiveDirectoryUser",
"type": "Selector",
"config": {
"columns": ["displayName","sAMAccountName","url","manager"],
"pipe_id": "active_directory_edit_user_step01_widget"
}
}
],
"pipe": "active_directory_edit_user_step01"
}
Example with all main properties.
{
"document_title": "flow00.step01.document_title",
"favicon": "favicon.ico",
"order": 1,
"verbose_logs": [
"flow",
"session"
],
"time_lock": "PT3S",
"controls": [],
"pipe": "forms.flow00.step01",
"buttons": {
"next_button": {
"enabled": true,
"text": "flow00.step01.next_button"
},
"save_button": {
"enabled": true,
"text": "flow00.step01.create_button"
},
"restart_button": {
"enabled": true,
"text": "flow00.step01.restart_button"
}
}
}
If configured, execution of a pipe is done with all data available to the step. This means data will vary depending on what step is executed.
Data from all previous executed steps will be sent to pipe and accessed in pipes using {{request. pattern.
In order to be able to access any data returned from a pipe, return a single item in a pipe.
Data will available using {{flow.xxx}} pattern.
document_title
order
time_lock
favicon
verbose_logs
controls
pipe
buttons.xxx
This will highlight the most important items. For in depth detail contact Fortified ID.
"always_include":true
To install on Container/Docker, click the following link: https://docs.fortifiedid.se/installation
When installation is completed, verify the following:
Replace <container_display_name> with the container name and replace <product_name>:<version> with the image product name and version.
docker run -p 8080:8080 --detach --name forms fortifiedid.jfrog.io/docker/fortifiedid/forms:<version> -c Node config/config.json
Parameter explanation:
-c
Direct system output to stdout
.
Node
Start the Node
module.
config/config.json
Use the given configuration file. Path is relative to SERVER_HOME
inside the container.
Check the log to ensure that the server was successfully bootstrapped:
docker logs -f forms
Finally, check that the server is up and running by pointing your browser at http://localhost:8080/forms/demo1 or
2
Note. Starting, stopping, and restarting the service are handled by Docker commands.
Here we address changes that may cause previously working configurations to stop working after the update, if they are not adjusted to handle the changes below.
Data changed by user will be sent to pipe.
As of 3.1.1 default encryption has been changed. This will only affect systems where encryption is enabled.
To keep previous implementation ensure environment setting:
FORTIFIED_SECRETS_IMPL = local
The Pipe module refer to the pipes used for each flow.
This section includes the main parameters for the Pipe module.
pipes
Location if pipes for each flow
N/A
{
"name": "Pipes",
"config": {
"pipes": "@include:flows/*/*/pipes/*.json"
}
}
Edit Entra ID user, update group membership.
Use this control to manage groups for a selected user. Note. To select the user, which often is done in a previous step, use the control EntraUserSelect.
An Entra ID module deployed with matching name as defined in "namespace".
An Entra ID identifier, "selected_entra_id", located in either session or flow. Data is taken from session first and flow second. selected_entra_id must reference a Entra ID user.
Edit Entra ID group, update group members
type
Must be EntraGroupEditGroupMember.
N/A
namespace
Identifier of EntraID module to use
default
columns
List array with columns to display
["displayName", "mail", "mobilePhone", "companyName", "department"]
change_is_required
Force admin to update user, true/false
false
exclude_id
Typically the id of current user. ID will not be visible. Configured value is taken from session or flow. First session, flow second.
N/A ("")
{
"id": "entraGroupEditGroupMember",
"type": "EntraGroupEditGroupMember",
"config": {
"namespace": "tenant1",
"columns": [
"displayName",
"mail",
"mobilePhone",
"companyName",
"department"
]
}
}
This control works in conjunction with Entra ID module. It must be installed.
Object array, "entra_pending_remove" - contains data on what groups to remove from user.
Object array, "entra_pending_add" - contains data on what groups add to user.
Array data will ha the syntax:
[{"id":"1234567","displayName":"Group 1"}]
See a Flow as an app. It defines things like number of steps, path of access and if it is public or protected by authentication. A Flows aims to guide end-users performing a well defined IAM task.
The Flow is defined by a JSON file. Name of the file can be anything, but flow.json is a recommended name. Format of the data inside must be either JSON or JSONC. The flow.json file will be picked up, loaded and exposed by the Forms module.
Last part of the URL how to access the flow. Must be unique within the forms module.
N/A
If flow can be accessed without any authentication (true/false).
false
Array of named roles user must have in order to access the flow, "one of"
Empty array: []
Should progress bar be visible (true/false).
true
Should user menu be visible (true/false).
true
Additional logging options. Note. This can be added to forms module and will then be available in all flows.
Empty array []
Steps to include for the flow. Recommendation is using @include directive for better overview.
Empty array []
Pipe executed before first step.
N/A
Pipe to execute when last step is complete.
N/A
Step used after last regular step is executed with success. Used for user notification etc. Do not out any logic here.
N/A
Step used after last regular step is executed with with failure. Used for user notification etc. Do not out any logic here.
N/A
Should next button be enabled (true/false).
true
Text on "Next" button
Next
Should save button be enabled (true/false).
true
Text on "Save" button
Save
Should restart button be enabled (true/false).
true
Text on "Restart" button
Restart
{
"name": "demo",
"public": false,
"require_roles": [
"role00"
],
"enable_progressbar": false,
"show_user_menu": true,
"verbose_logs": [
"flow",
"session"
],
"buttons": {
"next_button": {
"enabled": true,
"text": "flow00.next_button"
},
"save_button": {
"enabled": true,
"text": "flow00.create_button"
},
"restart_button": {
"enabled": true,
"text": "flow00.restart_button"
}
},
"steps": "@include:steps/*.json",
"pre_pipe": "forms.flow00.pre_pipe",
"pipe": "forms.flow00.finalize",
"incomplete": "@include:incomplete.json",
"summary": "@include:steps/summary.json"
}
Sometimes it is necessary to perform some kind of logic before first step is rendered. Typically used for validation and or collecting data reqired in step 1.
For case like this use pre_pipe.
In order to consume data in subsequent steps, make sure the pipe returns one item. Data in this item will be accessible using {{flow.xxx}}
name
public
require_roles
enable_progressbar
show_user_menu
verbose_logs
"flow",
"session"
steps
pre_pipe
pipe
summary
incomplete
buttons.
next_button
.enabled
buttons.
next_button.
text
buttons.
save_button.
enabled
buttons.
save_button.
text
buttons.
restart_button.
enabled
buttons.
restart_button.
text