Fortinet white logo
Fortinet white logo

REST API Solution Guide

User groups (/usergroups/)

User groups (/usergroups/)

URL: https://[server_name]/api/[api_version]/usergroups/

This endpoint represents the user group resource. In the FortiAuthenticator GUI, this resource corresponds to Authentication à User Groups. This API is for use by third-party user provisioning systems.

Supported fields

Field Description Type Required Other restrictions
name Group name String Yes max length = 50
users List of local users in the group List No List of local users URI

Allowed methods

Allowed methods Resource URI Action
GET Get all groups and associated users.
POST Create a new user.
PUT Replaces all of the resources for the group. This is done by removing all existing items first before creating the new items. Data must follow the same format as the data returned by the GET parameter.
PATCH Add users to a user group.
DELETE Delete a specified group.

Allowed filters

Field Filters
name exact

View all user groups

JSON query

  • JSON specified via GET

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" https://192.168.0.122/api/v1/usergroups/?format=xml

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -H 'Accept: application/xml' https://192.168.0.122/api/v1/usergroups/

Response

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 11:46:34 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response>

<objects type="list"><object><users type="list"/>

<idtype="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object>

<object><users type="list"/>

<idtype="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object>

<object><users type="list"><value>/api/v1/localusers/4/</value></users>

<idtype="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects>

<meta type="hash"><next type="null"/><total_count type="integer">3</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>

The response above has been reformatted with carriage returns to make the results more clear.

The response shows that there are 3 groups already configured (in RED).

  • Test_RADIUS (in ID position 5)
  • Test_LDAP (in ID position 4)
  • Test_Local (in ID position 3)

Test_RADIUS and Test_LDAP groups do not contain any users, however, the Test_Local group contains 1 user, identified as local user with ID=4 (in GREEN). See the LocalUsers for identifying Usernames from user IDs.

The total number of configured and supported User Groups is also returned for troubleshooting purposes (in GOLD).

Create a user group

JSON query

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X POST -d '{"name":"Group999"}' -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/

Response

< HTTP/1.1 201 CREATED

< Date: Mon, 09 Jun 2014 12:02:33 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Location: https://192.168.0.122/api/v1/usergroups/6/

< Content-Length: 0

< Content-Type: text/html; charset=utf-8

Verify user group creation

Use API call documented in Allowed filters

Field Lookup expressions Values
username exact, iexact, contains, icontains, in
first_name exact, iexact, contains, icontains
last_name exact, iexact, contains, icontains
email exact, iexact, contains, icontains, in
active exact
city exact, iexact, contains, icontains
state exact, iexact, contains, icontains
country exact, iexact, contains, icontains
token_type ftk, ftm, email, sms
token_serial exact, iexact

Third-party Integration: FortiToken Mobile provisioning

For integration with a third-party authentication server which needs to manage token validation, it is possible for the FortiAuthenticator to return FortiToken Mobile (FTM) seed during provisioning. However, certain conditions must be met:

  • Seed may only be returned when creating a new local user via POST method and when provisioning an FTM to an existing user via PATCH method.
  • A GET URL parameter (returnseed=1) needs to be specified to explicitly tell FortiAuthenticator to return an encrypted seed for the token (e.g. https://[server_name]/api/v1/localusers/2/?returnseed=1).
  • A seed encryption passphrase must be specified in FortiGuard settings.

The seed is encrypted and returned as a PSKC XML file string according to RFC 6030. The key is derived from the configured passphrase using the PBKDF2 key derivation function (32 byte key length, 1000 iterations), encrypted with AES 256 CBC encryption, and signed with a SHA256 HMAC.

Whenever an FTM is provisioned, its activation code will be returned as well.

List all local users above

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 12:18:19 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response><objects type="list"><object><users type="list"/><id type="integer">6</id> <name>Group999</name><resource_uri>/api/v1/usergroups/6/</resource_uri></object><object><users type="list"/><id type="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object><object><users type="list"/><id type="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object><object><users type="list"><value>/api/v1/localusers/4/</value></users><id type="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects><meta type="hash"><next type="null"/><total_count type="integer">4</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>

Attempt to create a user group with the same name

< HTTP/1.1 400 BAD REQUEST

< Date: Mon, 09 Jun 2014 12:04:06 GMT

< Server: Apache

< Vary: Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Connection: close

< Transfer-Encoding: chunked

< Content-Type: application/json

<

* Closing connection #0

{"usergroups": {"name": ["A user group with that name already exists."]}}

Add a user to a group

Note, the required users should be elucidated by querying the /localusers/ list as documented in the Local users (/localusers/) section. In this example:

test_user = /api/v1/localusers/5/
test_user2 = /api/v1/localusers/5/

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X PATCH -d '{"users":["/api/v1/localusers/5/","/api/v1/localusers/4/"]}' -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/9/

This command is not additive i.e. adding a single user entry will not increment the list it will overwrite. Using {"users":[ ]} for example will clear the users list.

Delete a user group

JSON query

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X DELETE -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/6/

Response

< HTTP/1.1 204 NO CONTENT

< Date: Mon, 09 Jun 2014 12:25:18 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Content-Length: 0

< Content-Type: text/html; charset=utf-8

<

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

Note that 204 NO CONTENT shows that the group has been successfully deleted. A subsequent listing confirms this as Group999 no longer exists:

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 12:26:05 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response><objects type="list"><object><users type="list"/><id type="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object><object><users type="list"/><id type="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object><object><users type="list"><value>/api/v1/localusers/4/</value></users><id type="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects><meta type="hash"><next type="null"/><total_count type="integer">3</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>[Carl@CentOS ~]$

The Delete command will delete the group even if the group contains users or if it is in use e.g. in a RADIUS Client configuration. Checks should be made prior to executing this command.

View a specific user group

JSON query

  • JSON specified via GET

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" “https://192.168.0.122/api/v1/usergroups/?format=json&name=/api/v1/usergroups/8/”

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -H 'Accept: application/json'“https://192.168.0.122/api/v1/usergroups/?format=json&name=Group999”

The filter used in this situation is the group “name” not the URL or ID.
The URL requires additional quoting in this case otherwise the Unix CLI treats the “&” as an instruction to place the cURL command into the background.
Querying a non-existent group will return a successful 200 OK response with empty object data. This is by design as this is not necessarily an error situation.

Response

< HTTP/1.1 200 OK

< Date: Tue, 10 Jun 2014 10:11:47 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/json

<

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

{"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1}, "objects": [{"id": 9, "name": "Group999", "resource_uri": "/api/v1/usergroups/9/", "users": ["/api/v1/localusers/5/"]}]}

User groups (/usergroups/)

User groups (/usergroups/)

URL: https://[server_name]/api/[api_version]/usergroups/

This endpoint represents the user group resource. In the FortiAuthenticator GUI, this resource corresponds to Authentication à User Groups. This API is for use by third-party user provisioning systems.

Supported fields

Field Description Type Required Other restrictions
name Group name String Yes max length = 50
users List of local users in the group List No List of local users URI

Allowed methods

Allowed methods Resource URI Action
GET Get all groups and associated users.
POST Create a new user.
PUT Replaces all of the resources for the group. This is done by removing all existing items first before creating the new items. Data must follow the same format as the data returned by the GET parameter.
PATCH Add users to a user group.
DELETE Delete a specified group.

Allowed filters

Field Filters
name exact

View all user groups

JSON query

  • JSON specified via GET

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" https://192.168.0.122/api/v1/usergroups/?format=xml

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -H 'Accept: application/xml' https://192.168.0.122/api/v1/usergroups/

Response

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 11:46:34 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response>

<objects type="list"><object><users type="list"/>

<idtype="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object>

<object><users type="list"/>

<idtype="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object>

<object><users type="list"><value>/api/v1/localusers/4/</value></users>

<idtype="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects>

<meta type="hash"><next type="null"/><total_count type="integer">3</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>

The response above has been reformatted with carriage returns to make the results more clear.

The response shows that there are 3 groups already configured (in RED).

  • Test_RADIUS (in ID position 5)
  • Test_LDAP (in ID position 4)
  • Test_Local (in ID position 3)

Test_RADIUS and Test_LDAP groups do not contain any users, however, the Test_Local group contains 1 user, identified as local user with ID=4 (in GREEN). See the LocalUsers for identifying Usernames from user IDs.

The total number of configured and supported User Groups is also returned for troubleshooting purposes (in GOLD).

Create a user group

JSON query

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X POST -d '{"name":"Group999"}' -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/

Response

< HTTP/1.1 201 CREATED

< Date: Mon, 09 Jun 2014 12:02:33 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Location: https://192.168.0.122/api/v1/usergroups/6/

< Content-Length: 0

< Content-Type: text/html; charset=utf-8

Verify user group creation

Use API call documented in Allowed filters

Field Lookup expressions Values
username exact, iexact, contains, icontains, in
first_name exact, iexact, contains, icontains
last_name exact, iexact, contains, icontains
email exact, iexact, contains, icontains, in
active exact
city exact, iexact, contains, icontains
state exact, iexact, contains, icontains
country exact, iexact, contains, icontains
token_type ftk, ftm, email, sms
token_serial exact, iexact

Third-party Integration: FortiToken Mobile provisioning

For integration with a third-party authentication server which needs to manage token validation, it is possible for the FortiAuthenticator to return FortiToken Mobile (FTM) seed during provisioning. However, certain conditions must be met:

  • Seed may only be returned when creating a new local user via POST method and when provisioning an FTM to an existing user via PATCH method.
  • A GET URL parameter (returnseed=1) needs to be specified to explicitly tell FortiAuthenticator to return an encrypted seed for the token (e.g. https://[server_name]/api/v1/localusers/2/?returnseed=1).
  • A seed encryption passphrase must be specified in FortiGuard settings.

The seed is encrypted and returned as a PSKC XML file string according to RFC 6030. The key is derived from the configured passphrase using the PBKDF2 key derivation function (32 byte key length, 1000 iterations), encrypted with AES 256 CBC encryption, and signed with a SHA256 HMAC.

Whenever an FTM is provisioned, its activation code will be returned as well.

List all local users above

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 12:18:19 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response><objects type="list"><object><users type="list"/><id type="integer">6</id> <name>Group999</name><resource_uri>/api/v1/usergroups/6/</resource_uri></object><object><users type="list"/><id type="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object><object><users type="list"/><id type="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object><object><users type="list"><value>/api/v1/localusers/4/</value></users><id type="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects><meta type="hash"><next type="null"/><total_count type="integer">4</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>

Attempt to create a user group with the same name

< HTTP/1.1 400 BAD REQUEST

< Date: Mon, 09 Jun 2014 12:04:06 GMT

< Server: Apache

< Vary: Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Connection: close

< Transfer-Encoding: chunked

< Content-Type: application/json

<

* Closing connection #0

{"usergroups": {"name": ["A user group with that name already exists."]}}

Add a user to a group

Note, the required users should be elucidated by querying the /localusers/ list as documented in the Local users (/localusers/) section. In this example:

test_user = /api/v1/localusers/5/
test_user2 = /api/v1/localusers/5/

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X PATCH -d '{"users":["/api/v1/localusers/5/","/api/v1/localusers/4/"]}' -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/9/

This command is not additive i.e. adding a single user entry will not increment the list it will overwrite. Using {"users":[ ]} for example will clear the users list.

Delete a user group

JSON query

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -X DELETE -H 'Content-Type: application/json' https://192.168.0.122/api/v1/usergroups/6/

Response

< HTTP/1.1 204 NO CONTENT

< Date: Mon, 09 Jun 2014 12:25:18 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Content-Length: 0

< Content-Type: text/html; charset=utf-8

<

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

Note that 204 NO CONTENT shows that the group has been successfully deleted. A subsequent listing confirms this as Group999 no longer exists:

< HTTP/1.1 200 OK

< Date: Mon, 09 Jun 2014 12:26:05 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/xml; charset=utf-8

<

<?xml version='1.0' encoding='utf-8'?>

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

<response><objects type="list"><object><users type="list"/><id type="integer">5</id><name>REST_RADIUS</name><resource_uri>/api/v1/usergroups/5/</resource_uri></object><object><users type="list"/><id type="integer">4</id><name>Test_LDAP</name><resource_uri>/api/v1/usergroups/4/</resource_uri></object><object><users type="list"><value>/api/v1/localusers/4/</value></users><id type="integer">3</id><name>Test_Local</name><resource_uri>/api/v1/usergroups/3/</resource_uri></object></objects><meta type="hash"><next type="null"/><total_count type="integer">3</total_count><previous type="null"/><limit type="integer">20</limit><offset type="integer">0</offset></meta></response>[Carl@CentOS ~]$

The Delete command will delete the group even if the group contains users or if it is in use e.g. in a RADIUS Client configuration. Checks should be made prior to executing this command.

View a specific user group

JSON query

  • JSON specified via GET

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" “https://192.168.0.122/api/v1/usergroups/?format=json&name=/api/v1/usergroups/8/”

  • JSON specified via Accept Header

curl -k -v -u "admin:zeyDZXmP6GbKcerqdWWEYNTnH2TaOCz5HTp2dAVS" -H 'Accept: application/json'“https://192.168.0.122/api/v1/usergroups/?format=json&name=Group999”

The filter used in this situation is the group “name” not the URL or ID.
The URL requires additional quoting in this case otherwise the Unix CLI treats the “&” as an instruction to place the cURL command into the background.
Querying a non-existent group will return a successful 200 OK response with empty object data. This is by design as this is not necessarily an error situation.

Response

< HTTP/1.1 200 OK

< Date: Tue, 10 Jun 2014 10:11:47 GMT

< Server: Apache

< Vary: Accept,Accept-Language,Cookie

< X-Frame-Options: SAMEORIGIN

< Content-Language: en

< Cache-Control: no-cache

< Transfer-Encoding: chunked

< Content-Type: application/json

<

* Connection #0 to host 192.168.0.122 left intact

* Closing connection #0

{"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1}, "objects": [{"id": 9, "name": "Group999", "resource_uri": "/api/v1/usergroups/9/", "users": ["/api/v1/localusers/5/"]}]}