Endurance

SAML

Configuration

Get the SAML configuration and group mappings

GET /saml/config

curl
curl -X GET "https://appliance.example.com/api/v1/saml/config" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/config';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.get("https://appliance.example.com/api/v1/saml/config", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/config', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Get the SAML settings
  type: http
  seq: 1
}

get {
  url: https://{{node-0}}:{{port}}/api/v1/saml/config
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "SAML configuration",
  "data": []
}

Replace the SAML configuration and group mappings. The body is the whole section: a field it omits is stored at that field’s default rather than left as it was, so send the configuration back in full. Nothing here is required on its own, because one configuration drives two features that are switched on separately: enabled makes the trust fields required, scimEndpointEnabled and samlEndpointEnabled make their own FIP, port and certificate required. The SCIM token is the one thing a save cannot touch — it survives this call and only DELETE revokes it. Refused while a transaction is open. Commit or roll back the transaction first.

PUT /saml/config

This change is staged. Send PUT /services/apply to apply it.

Body parameters
enabled boolean

Whether SAML is offered as a login type. SCIM provisioning runs without it, so a SCIM-only deployment leaves this false.

spEntityId string

This appliance’s entity id, presented to the identity provider. Required when enabled.

idpEntityId string

Required when enabled.

idpSsoUrl string

Single sign-on URL, HTTP-Redirect binding. Required when enabled.

idpCertificate string

PEM signing certificate assertions are verified against. Required when enabled.

objectIdClaim string

The assertion claim carrying the identity provider’s immutable object id, which a provisioned user is keyed on.

groupsClaim string

The assertion claim the group membership is read from.

emailClaim string
firstNameClaim string
lastNameClaim string
fallbackGroupId string

Appliance group id assigned when no mapping matches. Empty for none.

mappings array of object

Claim value to appliance group rules. Replaced wholesale.

Fields
claimValue string

A value of groupsClaim to match on.

groupIds array of string

Appliance group ids granted to a user carrying that value.

samlEndpointEnabled boolean

Whether the dedicated FIP-bound SAML login endpoint is served.

samlFipId string

Floating IP the SAML endpoint binds. Required when samlEndpointEnabled.

samlPort integer

Port the SAML endpoint listens on. Must be free, and cannot be the SCIM endpoint’s port on the same floating IP.

samlCertId string

Certificate presented on the SAML endpoint, which must match samlEndpointHost. Required when samlEndpointEnabled.

samlEndpointHost string

The hostname the browser reaches the SAML endpoint on. The ACS URL and the service-provider metadata are composed from it and samlPort, so it is what decides the ACS URL registered at the identity provider. A bare hostname, no scheme or path. Required when enabled.

scimEndpointEnabled boolean

Whether the dedicated FIP-bound SCIM endpoint is served.

scimFipId string

Floating IP the SCIM endpoint binds. Required when scimEndpointEnabled.

scimPort integer

Port the SCIM endpoint listens on. Must be free, and cannot be the SAML endpoint’s port on the same floating IP.

scimCertId string

Certificate presented on the SCIM endpoint, which the identity provider must trust. Required when scimEndpointEnabled.

curl
curl -X PUT "https://appliance.example.com/api/v1/saml/config" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true,
  "spEntityId": "<spEntityId>",
  "idpEntityId": "<idpEntityId>",
  "idpSsoUrl": "<idpSsoUrl>",
  "idpCertificate": "<idpCertificate>",
  "objectIdClaim": "<objectIdClaim>",
  "groupsClaim": "<groupsClaim>",
  "emailClaim": "<emailClaim>",
  "firstNameClaim": "<firstNameClaim>",
  "lastNameClaim": "<lastNameClaim>",
  "fallbackGroupId": "<fallbackGroupId>",
  "mappings": [
    {
      "claimValue": "<claimValue>",
      "groupIds": [
        "<groupIds>"
      ]
    }
  ],
  "samlEndpointEnabled": true,
  "samlFipId": "<samlFipId>",
  "samlPort": 0,
  "samlCertId": "<samlCertId>",
  "samlEndpointHost": "<samlEndpointHost>",
  "scimEndpointEnabled": true,
  "scimFipId": "<scimFipId>",
  "scimPort": 0,
  "scimCertId": "<scimCertId>"
}'
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/config';
$headers = [
    'Authorization: Bearer ' . $token,
    'Content-Type: application/json',
];

$payload = [
    'enabled' => true,
    'spEntityId' => '<spEntityId>',
    'idpEntityId' => '<idpEntityId>',
    'idpSsoUrl' => '<idpSsoUrl>',
    'idpCertificate' => '<idpCertificate>',
    'objectIdClaim' => '<objectIdClaim>',
    'groupsClaim' => '<groupsClaim>',
    'emailClaim' => '<emailClaim>',
    'firstNameClaim' => '<firstNameClaim>',
    'lastNameClaim' => '<lastNameClaim>',
    'fallbackGroupId' => '<fallbackGroupId>',
    'mappings' => [
        [
            'claimValue' => '<claimValue>',
            'groupIds' => [
                '<groupIds>',
            ],
        ],
    ],
    'samlEndpointEnabled' => true,
    'samlFipId' => '<samlFipId>',
    'samlPort' => 0,
    'samlCertId' => '<samlCertId>',
    'samlEndpointHost' => '<samlEndpointHost>',
    'scimEndpointEnabled' => true,
    'scimFipId' => '<scimFipId>',
    'scimPort' => 0,
    'scimCertId' => '<scimCertId>',
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}
payload = {
    "enabled": true,
    "spEntityId": "<spEntityId>",
    "idpEntityId": "<idpEntityId>",
    "idpSsoUrl": "<idpSsoUrl>",
    "idpCertificate": "<idpCertificate>",
    "objectIdClaim": "<objectIdClaim>",
    "groupsClaim": "<groupsClaim>",
    "emailClaim": "<emailClaim>",
    "firstNameClaim": "<firstNameClaim>",
    "lastNameClaim": "<lastNameClaim>",
    "fallbackGroupId": "<fallbackGroupId>",
    "mappings": [
        {
            "claimValue": "<claimValue>",
            "groupIds": [
                "<groupIds>"
            ]
        }
    ],
    "samlEndpointEnabled": true,
    "samlFipId": "<samlFipId>",
    "samlPort": 0,
    "samlCertId": "<samlCertId>",
    "samlEndpointHost": "<samlEndpointHost>",
    "scimEndpointEnabled": true,
    "scimFipId": "<scimFipId>",
    "scimPort": 0,
    "scimCertId": "<scimCertId>"
}

response = requests.put("https://appliance.example.com/api/v1/saml/config", headers=headers, json=payload)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/config', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "enabled": true,
  "spEntityId": "<spEntityId>",
  "idpEntityId": "<idpEntityId>",
  "idpSsoUrl": "<idpSsoUrl>",
  "idpCertificate": "<idpCertificate>",
  "objectIdClaim": "<objectIdClaim>",
  "groupsClaim": "<groupsClaim>",
  "emailClaim": "<emailClaim>",
  "firstNameClaim": "<firstNameClaim>",
  "lastNameClaim": "<lastNameClaim>",
  "fallbackGroupId": "<fallbackGroupId>",
  "mappings": [
    {
      "claimValue": "<claimValue>",
      "groupIds": [
        "<groupIds>"
      ]
    }
  ],
  "samlEndpointEnabled": true,
  "samlFipId": "<samlFipId>",
  "samlPort": 0,
  "samlCertId": "<samlCertId>",
  "samlEndpointHost": "<samlEndpointHost>",
  "scimEndpointEnabled": true,
  "scimFipId": "<scimFipId>",
  "scimPort": 0,
  "scimCertId": "<scimCertId>"
}),
});

const data = await response.json();
Bruno
meta {
  name: Update the SAML settings
  type: http
  seq: 1
}

put {
  url: https://{{node-0}}:{{port}}/api/v1/saml/config
  body: json
  auth: bearer
}

headers {
  Content-Type: application/json
}

auth:bearer {
  token: {{token}}
}

body:json {
  {
    "enabled": true,
    "spEntityId": "<spEntityId>",
    "idpEntityId": "<idpEntityId>",
    "idpSsoUrl": "<idpSsoUrl>",
    "idpCertificate": "<idpCertificate>",
    "objectIdClaim": "<objectIdClaim>",
    "groupsClaim": "<groupsClaim>",
    "emailClaim": "<emailClaim>",
    "firstNameClaim": "<firstNameClaim>",
    "lastNameClaim": "<lastNameClaim>",
    "fallbackGroupId": "<fallbackGroupId>",
    "mappings": [
      {
        "claimValue": "<claimValue>",
        "groupIds": [
          "<groupIds>"
        ]
      }
    ],
    "samlEndpointEnabled": true,
    "samlFipId": "<samlFipId>",
    "samlPort": 0,
    "samlCertId": "<samlCertId>",
    "samlEndpointHost": "<samlEndpointHost>",
    "scimEndpointEnabled": true,
    "scimFipId": "<scimFipId>",
    "scimPort": 0,
    "scimCertId": "<scimCertId>"
  }
}
Response
{
  "status": "success",
  "message": "SAML configuration updated",
  "data": []
}

Return the SAML configuration to its shipped state: disabled, with no identity provider trust details. One configuration drives both features, so this clears the SCIM endpoint settings too and revokes the SCIM token — a new token must be rotated before SCIM provisioning can resume. The SCIM endpoint stops when the pending changes are applied. The provisioned SAML users and SCIM groups are not affected. Refused while a transaction is open. Commit or roll back the transaction first.

DELETE /saml/config

This change is staged. Send PUT /services/apply to apply it.

curl
curl -X DELETE "https://appliance.example.com/api/v1/saml/config" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/config';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.delete("https://appliance.example.com/api/v1/saml/config", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/config', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Clear the SAML settings
  type: http
  seq: 1
}

delete {
  url: https://{{node-0}}:{{port}}/api/v1/saml/config
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "SAML configuration cleared",
  "data": []
}

Ingest SAML metadata

Parse pasted identity-provider federation metadata Refused while a transaction is open. Commit or roll back the transaction first.

POST /saml/config/metadata

This change is staged. Send PUT /services/apply to apply it.

curl
curl -X POST "https://appliance.example.com/api/v1/saml/config/metadata" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/config/metadata';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.post("https://appliance.example.com/api/v1/saml/config/metadata", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/config/metadata', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Ingest SAML metadata
  type: http
  seq: 1
}

post {
  url: https://{{node-0}}:{{port}}/api/v1/saml/config/metadata
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "Identity-provider metadata parsed",
  "data": []
}

Get the SAML service provider metadata

Get the service-provider metadata XML to register with the identity provider

GET /saml/metadata

curl
curl -X GET "https://appliance.example.com/api/v1/saml/metadata" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/metadata';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.get("https://appliance.example.com/api/v1/saml/metadata", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/metadata', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Get the SAML service provider metadata
  type: http
  seq: 1
}

get {
  url: https://{{node-0}}:{{port}}/api/v1/saml/metadata
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "Service-provider metadata",
  "data": []
}

Rotate the SCIM bearer token

Generate/rotate the SCIM bearer token (shown once) Refused while a transaction is open. Commit or roll back the transaction first.

POST /saml/scim/token

This change is staged. Send PUT /services/apply to apply it.

curl
curl -X POST "https://appliance.example.com/api/v1/saml/scim/token" \
  -H "Authorization: Bearer $TOKEN"
PHP
<?php

$url = 'https://appliance.example.com/api/v1/saml/scim/token';
$headers = [
    'Authorization: Bearer ' . $token,
];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Python
import requests

headers = {"Authorization": f"Bearer {token}"}

response = requests.post("https://appliance.example.com/api/v1/saml/scim/token", headers=headers)
response.raise_for_status()
print(response.json())
JavaScript
const response = await fetch('https://appliance.example.com/api/v1/saml/scim/token', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();
Bruno
meta {
  name: Rotate the SCIM bearer token
  type: http
  seq: 1
}

post {
  url: https://{{node-0}}:{{port}}/api/v1/saml/scim/token
  body: none
  auth: bearer
}

auth:bearer {
  token: {{token}}
}
Response
{
  "status": "success",
  "message": "SCIM bearer token generated — copy it now; it will not be shown again",
  "data": {
    "token": "<token>"
  }
}