Activity - Configure an application


Introduction and workflow tasks

This activity shows you how to create an application, configure its connection settings, create a resource access grant, and initiate an authorization request. After an access token is generated, it is used by a user to update a user attribute.

The following operations are supported by the PingOne for Customers APIs:

  • Create an application
  • Create a resource access grant
  • Initiate an authorization_code authorization flow
  • Update a user attribute

Workflow order of operations

To configure an application and initiate an authorization code flow, the following tasks must be completed successfully:

  1. Make a POST request to /environments/{environmentId}/applications to add a new application to the specified environment.

  2. Make a GET request to /environments/{environmentId}/applications/{applicationId}/secret to return the new application’s secret attribute.

  3. Make a GET request to /environments/{environmentId}/resources to return a list of all resource entities associated with the specified environment to get the ID for the PingOne platform resource.

  4. Make a GET request to /environments/{environmentId}/resources/{resourceId}/scopes to list all scopes associated with a specified resource (the PingOne platform resource).

  5. Make a POST request to /environments/{environmentId}/applications/{applicationId}/grants to create a new resource access grant for the application.

  6. Make a POST request to /{environmentId}/as/authorize to obtain an authorization grant. This request starts the authorization flow.

  7. After the authorization flow completes and returns an auth code, make a POST request to /{environmentId}/as/token to exchange the auth code for an access token.

  8. Make a GET request to /environments/{environmentId}/users/{userId} to view the current property values associated with the specified user.

  9. Make a PATCH request to /environments/{environmentId}/users/{userId} to perform a partial update to the specified user attribute properties.

Step 1: Create an OpenID Connect (OIDC) application

You can use the POST /environments/{environmentId}/applications endpoint to create the new application. The application’s protocol property is required, and in this example it specifies an OPENID_CONNECT application. When creating an OIDC application, you must specify values for the following OIDC settings:

  • responseTypes
  • grantTypes
  • tokenEndpointAuthMethod
  • postLogoutRedirectUris
  • redirectUris
curl -X "POST" "https://api.pingone.com/v1/environments/{environmentId}/applications" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d $'{
  "name": "TestApp",
  "enabled": true,
  "type": "WEB_APP",
  "protocol": "OPENID_CONNECT",
  "responseTypes": [
    "code"
  ],
  "grantTypes": [
    "authorization_code"
  ],
  "tokenEndpointAuthMethod": "CLIENT_SECRET_BASIC",
  "postLogoutRedirectUris": [
    "https://example.com"
  ],
  "redirectUris": [
      "https://example.com",
    ]
}'

The response data returns information about the new application, including its id property, which identifies the UUID for this application resource. The application’s UUID (shown below) is required in the next step to get the application’s secret.

{

    "id": "76067e0d-decf-4423-a2a8-f16100301a0a"
}

Step 2: Get the application secret

You need the application id property value returned in Step 1 to retrieve the application’s secret property value. The GET /environments/{environmentId}/applications/{applicationId}/secret returns the secret property value for the application specified in the request URL.

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

The response data returns the secret value for the application:

{
    "secret": "61tO2tfqRWZ~DLZ1Dfi8rptBNgKzc5H...y"
}

The secret property value is needed in Step 7 to validate the request to exchange the authorization code for an access token.

Step 3: Get the list of resources

Resources are the protected endpoints that applications request access to using OAuth 2 authorization services. For this activity, the resource associated with the new application will be https://api.pingone.com, the PingOne for Customers platform APIs.

The GET /environments/{environmentId}/resources returns a list of all resource entities associated with the specified environment. The resource entity ID for https://api.pingone.com is needed in Step 5 when you create the application’s resource access grant.

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

The response data includes the resource ID for each defined resource entity associated with the specified environment.

{
  "_links" : {
    "self" : {
      "href" : "https://api.pingone.com/v1/environments/{environmentId}/resources"
    }
  },
  "_embedded" : {
    "items" : [ {
      "_links" : {
        "self" : {
          "href" : "https://api.pingone.com/v1/environments/{environmentId}/resources/607d2326-5d08-475d-aab3-8e8df5237c18"
        },
        "environment" : {
          "href" : "https://api.pingone.com/v1/environments/{environmentId}"
        }
      },
      "id" : "607d2326-5d08-475d-aab3-8e8df5237c18",
      "name" : "https://api.pingone.com",
      "description" : "APIs to manage all aspects of the PingOne platform."
    }, {
      "_links" : {
        "self" : {
          "href" : "https://api.pingone.com/v1/environments/{environmentId}/resources/79d29353-1508-4276-b0fa-2bffd5566aed"
        },
        "environment" : {
          "href" : "https://api.pingone.com/v1/environments/{environmentId}"
        }
      },
      "id" : "79d29353-1508-4276-b0fa-2bffd5566aed",
      "name" : "openid",
      "description" : "OpenID Connect scopes can be used to request that specific sets of information be made available as Claim Values in the ID token and the userinfo endpoint."
    } ]
  },
  "count" : 2,
  "size" : 2
}

Step 4: Get all scopes

In this step, you get a list of all scopes, and from that list you must make a note of the scope IDs that you want to apply to the resource access grant in Step 5. The GET /environments/{environmentId}/resources/{resourceId}/scopes operation returns information about the scopes associated with the resource entity ID specified in the request URL. The value for the {resourceId} parameter is the resource ID for the https://api.pingone.com resource you retrieved in Step 4.

curl -X GET "https://api.pingone.com/v1/environments/{environmentId}/resources/{resourceId}/scopes" \
-H "Authorization: Bearer jwtToken"

The response data shows the scopes and their IDs. At a minimum, the resource application grant for this activity must have the p1:read:user and p1:update:user scopes to enable a user to read and update user information.

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}/resources/3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2/scopes/a0a346fb-3866-4100-89d9-cb9e88bc9638"
        },
        "resource": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}/resources/3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}"
        }
    },
    "id": "a0a346fb-3866-4100-89d9-cb9e88bc9638",
    "environment": {
        "id": "{environmentId}"
    },
    "name": "p1:read:user",
    "description": "Ability for the user to retrieve their own user identity and all attributes",
    "resource": {
        "id": "3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
    }
  },
{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}/resources/3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2/scopes/7d84fcfb-0646-4ebb-bd51-31b3e8ab610a"
        },
        "resource": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}/resources/3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/{environmentId}"
        }
    },
    "id": "7d84fcfb-0646-4ebb-bd51-31b3e8ab610a",
    "environment": {
        "id": "{environmentId}"
    },
    "name": "p1:update:user",
    "description": "Ability for the user to modify the attributes of their own user identity",
    "resource": {
        "id": "3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
    }
  },
}

Step 5: Create the application’s resource access grant

After retrieving the platform resource ID in Step 3 and the scope IDs in Step 4, you can use the POST /environments/{environmentId}/applications/{applicationId}/grants operation to create a new resource access grant for the application specified by its ID in the request URL.

The body of the request specifies the ID for the resource property (https://api.pingone.com) and the IDs for the scopes that you assign to the application resource grant. Remember, for this activity, you must provide scope IDs for the p1:read:user and p1:update:user scopes, which are required permissions for a user to perform a self-update operation.

curl -X POST "https://api.pingone.com/v1/environments/{environmentId}/applications/{applicationId}/grants" \
-H "Content-type: application/json" \
-H "Authorization: Bearer jwtToken" \
-d "{
  "resource": {
    "id": "3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2",
  },
  "scopes": [
        {
        	"id": "a0a346fb-3866-4100-89d9-cb9e88bc9638"
        },
        {
        	"id": "7d84fcfb-0646-4ebb-bd51-31b3e8ab610a"
        }
    ]
}"

The response data shows the resource grant ID and the scopes associated with the grant:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/applications/76067e0d-decf-4423-a2a8-f16100301a0a/grants/860c1be9-6000-441b-85f8-f6414b546d71"
        },
        "application": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/applications/76067e0d-decf-4423-a2a8-f16100301a0a"
        },
        "resource": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/resources/3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
        }
    },
    "id": "860c1be9-6000-441b-85f8-f6414b546d71",
    "environment": {
        "id": "5da98f13-ad62-4234-ba04-2b6e2e85c8ca"
    },
    "resource": {
        "id": "3dd4ac35-f06a-4569-90b7-a5e3dba6b4d2"
    },
    "application": {
        "id": "76067e0d-decf-4423-a2a8-f16100301a0a"
    },
    "scopes": [
        {
            "id": "7d84fcfb-0646-4ebb-bd51-31b3e8ab610a"
        },
        {
            "id": "a0a346fb-3866-4100-89d9-cb9e88bc9638"
        }
    ],
    "createdAt": "2019-01-08T19:57:14.568Z",
    "updatedAt": "2019-01-08T19:57:14.568Z"
}

Step 6: Obtain an authorization grant

The PingOne authorization endpoint /{environmentId}/as/authorize is used to interact with the resource owner (https://api.pingone.com) and obtain an authorization grant. The authorization request must include values for the following properties:

  • client_id

    A string that specifies the application’s UUID, which was returned in Step 1.

  • response_type

    A string that specifies the code or token type returned by an authorization request. For this activity, the value is code.

  • redirect_uri

    A string that specifies the URL that specifies the return entry point of the application. The redirect_uri property value defined in Step 1 is https://example.com.

  • scope

    A string that specifies permissions that determine the resources that the application can access. This activity must specify the p1:read:user and p1:update:user scopes.

The response_type parameter specifies a value of code, which designates that this authorization request returns an authorization code that can be exchanged for an access token.

curl -X POST \
  "https://auth.pingone.com/{environmentId}/as/authorize" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "response_type=code&client_id=%7B%7BappID%7D%7D&redirect_uri=https%3A%2F%2Fexample.com&scope=read%3Aself%3Auser%20p1%3Aupdate%3Aself%3Auser"

The authentication flow presents appropriate forms to an end user and submits data provided by the user for all required steps (such as a for to get username and password values). It also redirects to the resume URL when the authentication flow is complete. For detailed information about authentication flows, see Activity - Using PingOne authentication flows.

When the flow finishes, it returns an authorization code. The authorization code is used in Step 7 to create the access token.

Step 7: Generate the access token

The token endpoint is used by the client to obtain an access token by presenting its authorization grant. For authorization_code grants, the application calls the POST /{environmentId}/as/token endpoint to acquire the access token. The request body must include values for the following properties:

  • grant_type

    A string that specifies the grant type of the token request. In this example, the value is authorization_code.

  • code

    A string that specifies the authorization code value returned by the authorization request.

  • redirect_uri

    A string that specifies the URL that specifies the return entry point of the application.

The request requires basic authentication in which the application ID from Step 1 and the application secret from Step 2 are used as the username and password values, respectively, in the --user parameter to satisfy the basic authentication requirement.

curl -X POST \
  "https://auth.pingone.com/{environmentId}/as/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --user "{appID}:{appSecret}" \
  -d "grant_type=authorization_code&code={authCode}&redirect_uri=https%3A%2F%2Fexample.com"

The response data contains the access token.

{
  “access_token”: “eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3QifQ.eyJzY29wZSI6IiIsImNsaWVudF9pZCI6ImlkZW50aXR5LWRpcmVjdG9yeS1zeW50aGV0aWMtdGVzdGluZyIsImlzcyI6ImF1dGgtc3RhZ2luZy5waW5nb25lLmNvbSIsImF1ZCI6ImFwaS1zdGFnaW5nLnBpbmdvbmUuY29tIiwiYWNjIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwiZW52aXJvbm1lbnRfaWQiOiIiLCJvcmciOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiLCJvcmdhbml6YXRpb25faWQiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiLCJlbnYiOiIiLCJleHAiOjE1MzAxMTc1Nzl9.OTGQethw-flgnf0oslpQOmW9YdExf6ZpsqpmRtBTeD5gpKGFmaSeHguFMVpR94GSjb27OEPzCY8qpU_OkoaQGH9FiysdgvFFVNVzHOb80e0MgP47ean1Rtk3lHmIWHg1ihp3Kt7vq9fO0OwekmfshejyaLYLX2g4seWFZKbs7ICIaSufYuGTsLLQFixiK7b0tM-lcjZUmLglPlzdGEYQgg13ZWho02rFVjwRrfOVkQRCLuhkk2Pz2eeblQgWBlzMi_zbHnRhqRnrHyX2PwoPZ9qHh3aqz6yNgGinUwSrE3J1slnx8uPeP88obYcX4QXTXOCf7su2rinbexOsNu4Puw“,
  "token_type": "Bearer",
  "expires_in" : 3600,
  "scope" : "p1:read:user p1:update:user"
}

Step 8: Get user information

This activity assumes that you already have a user resource defined. If you do not have a user resource defined, see Create users for information on creating new users.

The GET /environments/{environmentId}/users/{userId} endpoint returns information about the user whose properties you want to update.

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

The data returned for the specified user looks like this:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca"
        },
        "population": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/populations/a6c45799-8cec-4f69-8be9-e38c7bbdd7e4"
        },
        "devices": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/devices"
        },
        "roleAssignments": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/roleAssignments"
        },
        "password": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.reset": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.set": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.check": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.recover": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "account.sendVerificationCode": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af"
        }
    },
    "id": "c3042000-188f-4bc7-a269-dee1602cf7af",
    "environment": {
        "id": "5da98f13-ad62-4234-ba04-2b6e2e85c8ca"
    },
    "population": {
        "id": "a701eb22-849d-4168-b756-6c20fc087c2f"
    },
    "createdAt": "2019-01-08T20:18:31.264Z",
    "email": "gracejones@example.com",
    "enabled": true,
    "lifecycle": {
        "status": "ACCOUNT_OK"
    },
    "mfaEnabled": false,
    "name": {
        "given": "Grace",
        "family": "Jones"
    },
    "updatedAt": "2019-01-08T20:18:31.264Z",
    "username": "gracejones"
}

From the response data, you can view the current property values and determine the properties that you want to update in Step 9.

User properties that do not have a set value are not listed in the response data for a GET /environments/{environmentId}/users/{userId} request. However, these properties, although not listed, can be updated in a PUT or PATCH request. For example, the following properties were not listed for the user specified in Step 8 because no initial value was set when the user was created. Any of these properties, as well as those listed above, can be updated:

{
  "accountId": "string",
  "address": {
    "countryCode": "string",
    "locality": "string",
    "postalCode": "string",
    "region": "string",
    "streetAddress": "string"
  },
  "externalId": "string",
  "id": "string",
  "locale": "string",
  "mobilePhone": "string",
  "name": {
    "formatted": "string",
    "honorificPrefix": "string",
    "honorificSuffix": "string",
    "middle": "string"
  },
  "nickname": "string",
  "photo": {
    "href": "string"
  },
  "preferredLanguage": "string",
  "primaryPhone": "string",
  "timezone": "string",
  "title": "string",
  "type": "string",
}

Step 9: Update user information

The /environments/{environmentId}/users/{userId} endpoint supports both PUT and PATCH operations to update user property values. The PUT operation is a complete update; any existing property values omitted from the request body are removed. The PATCH operation is a partial update; only the property values specified in the request body are changed and all property values omitted from the request remain unchanged.

The following sample shows the PATCH /environments/{environmentId}/users/{userId} operation to update the specified existing property values. Property values omitted from the request body are not updated.

curl -X "PATCH" "https://api.pingone.com/v1/environments/{environmentId}/users/{userId}" \
-H 'Content-type: application/json' \
-H 'Authorization: Bearer jwtToken' \
-d '{
    "nickname": "Gracie",
    "title": "Professor",
    "timezone": "America/New_York"
}'

The response data shows the updated user property values:

{
    "_links": {
        "self": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af"
        },
        "environment": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca"
        },
        "population": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/populations/a701eb22-849d-4168-b756-6c20fc087c2f"
        },
        "password": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.reset": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.set": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.validate": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "password.recover": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af/password"
        },
        "account.sendVerificationCode": {
            "href": "https://api.pingone.com/v1/environments/5da98f13-ad62-4234-ba04-2b6e2e85c8ca/users/c3042000-188f-4bc7-a269-dee1602cf7af"
        }
    },
    "id": "c3042000-188f-4bc7-a269-dee1602cf7af",
    "environment": {
        "id": "5da98f13-ad62-4234-ba04-2b6e2e85c8ca"
    },
    "population": {
        "id": "a701eb22-849d-4168-b756-6c20fc087c2f"
    },
    "createdAt": "2019-01-08T20:18:31.264Z",
    "email": "gracejones@example.com",
    "enabled": true,
    "lifecycle": {
        "status": "ACCOUNT_OK"
    },
    "mfaEnabled": false,
    "name": {
        "given": "Grace",
        "family": "Jones"
    },
    "nickname": "Gracie",
    "timezone": "America/New_York",
    "title": "Professor",
    "updatedAt": "2019-01-08T20:59:56.871Z",
    "username": "gracejones"
}