Configure a SAML identity provider


Introduction and workflow tasks

An external identity provider configuration in PingOne to support a SAML identity provider allows users to authenticate and gain access to application resources using a SAML sign-on flow and credentials.

The SAML identity provider’s verification certificate ID and the signing key are properties that you define when creating the SAML protocol application connection. For more information about the SAML application settings data model, see Applications SAML settings data model. For more information about configuring a SAML application connection, see the SAML applications section of Add applications. For information about importing certificates, see Certificate management.

This scenario illustrates the following operations supported by the PingOne for Customers APIs:

  • Create an identity provider configuration
  • Create a sign-on policy
  • Create a sign-on policy action
  • Assign the sign-on policy to an application

Workflow order of operations

To create a sign-on policy that supports a SAML external identity provider, the following tasks must be completed successfully:

  1. Make a GET request to /environments/{environmentId}/applications to lookup the SAML application’s verification certificate ID and the signing key ID property values.

  2. Make a POST request to /environments/{environmentId}/identityProviders to create the SAML identity provider configuration.

  3. Make a POST request to /environments/{environmentId}/signOnPolicies to create a new sign-on policy.

  4. Make a POST request to /environments/{environmentId}/signOnPolicies/{policyId}/actions to create a new LOGIN sign-on policy action, which is associated with the new sign-on policy.

  5. Make a POST request to /environments/{environmentId}/applications/{applicationId}/signOnPolicyAssignments to associate this sign-on policy with the specified SAML application.

Step 1: Get the SAML application’s certificate ID and signing key ID

The GET /environments/{environmentId}/applications endpoint returns a list of all configured applications in the environment. You can scroll though the applications list to retrieve the SAML application’s spVerification.certificates[].id and idpSigning.key.id property values. You will need these values in Step 2 to create the external identity provider resource.

curl -X "POST" "https://api.pingone.com/v1/environments/{environmentId}/applications" \
-H 'Authorization: Bearer jwtToken'

The response data looks like this:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications"
        }
    },
    "_embedded": {
        "applications": [
            {
                "_links": {
                    "grants": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/cf12be70-c56d-45b6-b45a-956cfbf7fc6c/grants"
                    },
                    "environment": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006"
                    },
                    "self": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/cf12be70-c56d-45b6-b45a-956cfbf7fc6c"
                    },
                    "secret": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/cf12be70-c56d-45b6-b45a-956cfbf7fc6c/secret"
                    },
                    "roleAssignments": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/cf12be70-c56d-45b6-b45a-956cfbf7fc6c/roleAssignments"
                    }
                },
                "environment": {
                    "id": "88c23def-39c9-4646-8d41-aa91a14a1006"
                },
                "id": "cf12be70-c56d-45b6-b45a-956cfbf7fc6c",
                "name": "HR_APP",
                "description": "My HR application.",
                "enabled": true,
                "type": "WORKER",
                "loginPageUrl": "http://example.com",
                "protocol": "OPENID_CONNECT",
                "createdAt": "2019-03-15T17:32:26.817Z",
                "updatedAt": "2019-03-15T17:32:26.817Z",
                "responseTypes": [
                    "TOKEN"
                ],
                "grantTypes": [
                    "IMPLICIT"
                ],
                "tokenEndpointAuthMethod": "CLIENT_SECRET_BASIC",
                "postLogoutRedirectUris": [
                    "https://example.com"
                ],
                "redirectUris": [
                    "https://example.com:3000/code/response",
                    "https://example.com",
                    "https://example.com:3000/response"
                ]
            },
            {
                "_links": {
                    "self": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/37c7a13a-bfb4-4eff-9f4c-d7812d642714"
                    },
                    "environment": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006"
                    },
                    "attributes": {
                        "href": "https://api.pingone.com/v1/environments/88c23def-39c9-4646-8d41-aa91a14a1006/applications/37c7a13a-bfb4-4eff-9f4c-d7812d642714/attributes"
                    }
                },
                "environment": {
                    "id": "88c23def-39c9-4646-8d41-aa91a14a1006"
                },
                "id": "37c7a13a-bfb4-4eff-9f4c-d7812d642714",
                "name": "MySAMLApp",
                "description": "this is my SAML application",
                "enabled": true,
                "type": "WEB_APP",
                "protocol": "SAML",
                "createdAt": "2019-04-11T22:18:43.313Z",
                "updatedAt": "2019-04-11T22:18:43.313Z",
                "spEntityId": "test",
                "sloEndpoint": "https://example.com/slo",
                "sloResponseEndpoint": "https://example.com",
                "responseSigned": true,
                "sloBinding": "HTTP_POST",
                "acsUrls": [
                    "https://example.com"
                ],
                "assertionDuration": 60,
                "assertionSigned": true,
                "idpSigning": {
                  "key": {
                    "id": "a65318d7-eaa2-4070-bb73-ffe21a6fca06"
                  }
                },
                "spVerification": {
                  "cert": {
                    "id": "123f67f8-c56c-4903-9c9b-c4b162e22789"
                }
              }
            },
    "size": 2
}

Step 2: Create the new identity provider resource

You can use the POST /environments/{environmentId}/identityProviders endpoint to create the SAML identity provider configuration. This request automatically creates the core attribute mapping to associate the PingOne username attribute with the SAML samlAssertion.​subject attribute. To verify the mapping, you can use the ?expand=attributes query filter to show the core attribute mapping details in the POST response.

curl -X "POST" "https://api.pingone.com/v1/environments/{environmentId}/identityProviders?expand=attributes" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d '{
  "name": "SAMLIdP",
  "description": "My SAML IdP",  
  "type": "SAML",
  "enabled": false,
  "spEntityId": "sp-{$timestamp}",
  "idpEntityId": "idp-{$timestamp}",
  "ssoBinding": "HTTP_POST",
  "ssoEndpoint": "https://idp.com/sso",
  "authnRequestSigned": "false",
  "idpVerification": {
    "certificates": [
      {
        "id": "123f67f8-c56c-4903-9c9b-c4b162e22789"
      }
    ]
  },
  "spSigning": {
  	"key": {
  		"id": "a65318d7-eaa2-4070-bb73-ffe21a6fca06"
  	}
  }
}'

In the request, the name property for the new identity provider is required and must be unique within the environment. The enabled property is required and should be set to true, and the type property is required and must specify SAML as the identity provider type.

The idpVerification.certificates[].id is required. This is the UUID of the spVerification.certificates[].id that you retrieved in Step 1. The spSigning.key.id property value is the UUID of the idpSigning.key.id value that you retrieved in Step 1.

The response shows the configuration data for the new identity provider.

{
    "_links": {
        "self": {
            "href": "https://api-staging.pingone.com/v1/environments/c9900572-0d85-40b6-a228-f51ac7b67bc7/identityProviders/a9e4e181-f520-4e6e-af30-d3559781ad1b"
        },
        "environment": {
            "href": "https://api-staging.pingone.com/v1/environments/c9900572-0d85-40b6-a228-f51ac7b67bc7"
        },
        "attributes": {
            "href": "https://api-staging.pingone.com/v1/environments/c9900572-0d85-40b6-a228-f51ac7b67bc7/identityProviders/a9e4e181-f520-4e6e-af30-d3559781ad1b/attributes"
        }
    },
    "id": "a9e4e181-f520-4e6e-af30-d3559781ad1b",
    "type": "SAML",
    "name": "SAMLIdP",
    "description": "My SAML IdP",
    "enabled": false,
    "environment": {
        "id": "c9900572-0d85-40b6-a228-f51ac7b67bc7"
    },
    "createdAt": "2019-06-17T17:20:12.294Z",
    "updatedAt": "2019-06-17T17:20:12.294Z",
    "_embedded": {
        "attributes": [
            {
                "name": "username",
                "value": "${samlAssertion.subject}",
                "update": "EMPTY_ONLY",
                "id": "51a036c6-41ed-44f7-bd1d-eacaa2a1feab",
                "mappingType": "CORE",
                "environment": {
                    "id": "c9900572-0d85-40b6-a228-f51ac7b67bc7"
                },
                "identityProvider": {
                    "id": "a9e4e181-f520-4e6e-af30-d3559781ad1b"
                },
                "createdAt": "2019-06-17T17:20:12.294Z",
                "updatedAt": "2019-06-17T17:20:12.294Z"
            }
        ]
    },
    "authnRequestSigned": false,
    "ssoEndpoint": "https://idp.com/sso",
    "ssoBinding": "HTTP_POST",
    "idpVerification": {
      "certificates": [
        {
          "id": "123f67f8-c56c-4903-9c9b-c4b162e22789"
        }
      ]
    },
    "spEntityId": "sp-1560792011",
    "spSigning": {
        "key": {
            "id": "a65318d7-eaa2-4070-bb73-ffe21a6fca06"
        }
    },
    "idpEntityId": "idp-1560792011"
}

Step 3: Create the new sign-on policy

You can use the POST /environments/{environmentId}/signOnPolicies endpoint to create the new sign-on policy.

curl -X "POST" "https://api.pingone.com/v1/environments/{environmentId}/signOnPolicies" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d '{
  "name": "SAMLPolicy",
  "default": "true",
  "description": "A sign-on policy for a SAML identity provider."
}'

In the request, the name property is required and must be unique within the environment. The description property is optional, but recommended. The default property is optional, and should be set only if you want this sign-on policy to be the default policy for all applications in the environment. If this property is not set in the request, its value is set automatically to false.

The response shows the property data for the new sign-on policy.

{
  "_links": {
    "self": {
      "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/signOnPolicies/ff11048e-c74f-4bda-86d1-851ec721e25d"
    },
    "environment": {
      "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
    },
    "actions": {
      "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/signOnPolicies/ff11048e-c74f-4bda-86d1-851ec721e25d/actions"
    }
  },
  "id": "ff11048e-c74f-4bda-86d1-851ec721e25d",
  "environment": {
    "id": "9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
  },
  "name": "SAMLPolicy",
  "description": "A sign-on policy for a SAML identity provider.",
  "default": true
}

The response includes an actions HAL link to the sign-on policy actions endpoint, which is used to assign an action to the new sign-on policy. The policy must have at least one associated action before it can be assigned to an application.

Step 4: Create the sign-on policy action

This step associates a sign-on policy action with the new sign-on policy you created in Step 3. The POST /environments/{environmentId}/signOnPolicies/{policyId}/actions operation creates the sign-on policy action resource, which is associated with the sign-on policy ({policyId}) specified in the request URL.

PingOne supports the following two sign-on policy action types:

  • LOGIN

    Basic authentication that prompts for a username and password.

  • MULTI_FACTOR_AUTHENTICATION

    A multi-factor action that can return multiple status conditions, which result in more than one operation to complete.

To establish a SAML username/password login flow, the type property for the action resource associated with the sign-on policy is set to LOGIN.

For a sign-on action that supports SAML, the sign-on policy action must include the socialProviders.​id property to specify the SAML identity provider ID {providerId} that you created in Step 2.

In addition, it is recommended that a sign-on policy that supports a SAML external identity provider also include the registration property to allow automatic account creation and account linking between the user’s identity provider account and the PingOne account. For details about the registration sign-on action and how it relates to account linking, see External identity provider login flow states.

curl -X "POST" "https://api.pingone.com/v1/environments/{environmentID}/signOnPolicies/{policyId}/actions" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d '{
    "environment": {
        "id": "{environmentId}"
    },
    "signOnPolicy": {
        "id": "{policyId}"
    },
    "priority": 1,
    "type": "LOGIN",
    "socialProviders.​id": "{providerId}",
    "registration" : {
      "enabled" : true,
      "population" : {
        "id" : "{populationID}"
      }
    },
    "recovery" : {
      "enabled" : true
    }
}'

In this sample, the priority property is set to 1, which designates this policy as the first sign-on policy executed, if there is more than one sign-on policy associated with the application. In addition, this action includes the recovery property to enable the password.recover authentication flow, allowing users to recover a forgotten password.

The response data looks like this:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/signOnPolicies/5edef002-3f1f-4e00-a4db-130807f41234/actions/a256b35d-4b14-4ee5-85da-d8450c1aefd2"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
        },
        "signOnPolicy": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/signOnPolicies/5edef002-3f1f-4e00-a4db-130807f41234"
        }
    },
    "id": "a256b35d-4b14-4ee5-85da-d8450c1aefd2",
    "environment": {
        "id": "9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
    },
    "signOnPolicy": {
        "id": "5edef002-3f1f-4e00-a4db-130807f41234"
    },
    "priority": 1,
    "type": "LOGIN",
    "socialProviders.​id": "65fb47be-c71e-45b6-9c4c-e3deed8df116",
    "registration" : {
      "enabled" : true,
      "population" : {
        "id" : "fb526776-dc9b-4c35-af89-d9c98d8d723b"
      }
    },
    "recovery" : {
      "enabled" : true
    }
}

Step 5: Assign the sign-on policy to an application

To use the new sign-on policy, the POST /environments/{environmentId}/applications/{applicationId}/signOnPolicyAssignments operation assigns the new sign-on policy to the application designated by its ID in the request URL. The request body requires the sign-on policy property id and an integer value for the priority property.

curl -X "POST" "https://api.pingone.com/v1/environments/{environmentId}/applications/{applicationId}/signOnPolicyAssignments" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d '{
    "signOnPolicy": {
      "id": "5edef002-3f1f-4e00-a4db-130807f41234"
    },
    "priority": 1
}'

The response data looks like this:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/applications/37c7a13a-bfb4-4eff-9f4c-d7812d642714/signOnPolicyAssignments/ede42c6c-a97a-4c2c-aaeb-9cb38f13bb13"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
        },
        "application": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/applications/37c7a13a-bfb4-4eff-9f4c-d7812d642714"
        },
        "signOnPolicy": {
            "href": "https://api.pingone.com/v1/environments/9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7/signOnPolicies/5edef002-3f1f-4e00-a4db-130807f41234"
        }
    },
    "id": "ede42c6c-a97a-4c2c-aaeb-9cb38f13bb13",
    "environment": {
        "id": "9ad15e9e-3ac6-43f7-a053-d46b87d6c4a7"
    },
    "application": {
        "id": "37c7a13a-bfb4-4eff-9f4c-d7812d642714"
    },
    "signOnPolicy": {
        "id": "54f11a8b-0e09-4f76-8cdc-2efa2c9c499e"
    },
    "priority": 1
}