---
title: User profile self-service in JavaScript apps
description: Learn how to add user profile self-service to your JavaScript apps, allowing users to manage their own profile information.
component: orchsdks
page_id: orchsdks:journey:use-cases/user-self-service/javascript-user-self-service
canonical_url: https://developer.pingidentity.com/orchsdks/journey/use-cases/user-self-service/javascript-user-self-service.html
revdate: Fri, 20 Feb 2026 16:09:20 +0100
keywords: ["PingOne Advanced Identity Cloud", "PingAM", "Journeys", "JavaScript", "User Profile", "Self-Service", "Profile Management", "SDK"]
section_ids:
  step_1_starting_additional_journeys: Step 1. Starting additional journeys
  step_2_handling_callbacks_from_a_self_service_journey: Step 2. Handling callbacks from a self-service journey
---

# User profile self-service in JavaScript apps

[icon: circle-check, set=far]PingOne Advanced Identity Cloud [icon: circle-check, set=far]PingAM [icon: js, set=fab]JavaScript

You can run additional authentication journeys with the Orchestration SDKs in the same way as the initial journey that authenticates the user.

The only difference is that the Orchestration SDK automatically attaches the existing session to subsequent outgoing calls.

Your app should iterate through the callbacks in the journey in the same way as it would for the initial authentication journey.

## Step 1. Starting additional journeys

Use the `start()` method to start additional journeys after initial authentication:

Starting a user profile self-service journey on JavaScript

```javascript
let step = await journeyClient.start({
  journey: 'sdkProfileManagement',
  query: {
    forceAuth: true,
    noSession: true,
  },
});
```

When launching additional journeys, you can optionally add parameters to control how the journey runs:

* *forceAuth*

  Set this parameter to `true` to force traversal of an authentication journey, even if the user already has a valid session.

* *noSession*

  Set this parameter to `true` to prevent the authentication journey from issuing a new session token upon successful completion.

  If you don't set this parameter, the Orchestration SDK replaces the initial session token with the new one from the additional journey.

  Replacing the session also resets its time-to-live values.

## Step 2. Handling callbacks from a self-service journey

The self-service journey returns one or more callbacks to display and update the user's profile.

Common callbacks you might encounter in a user profile self-service journey include the following:

**Common user profile self-service callbacks**

| Callback                                                                                                                                             | Nodes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Description                                                                                                                                |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| [BooleanAttributeInputCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#BooleanAttributeInputCallback) | * [Attribute Collector node](https://docs.pingidentity.com/auth-node-ref/latest/attribute-collector.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Collects a boolean-style confirmation, such as yes/no or true/false.                                                                       |
| [ChoiceCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#ChoiceCallback)                               | - [Choice Collector node](https://docs.pingidentity.com/auth-node-ref/latest/choice-collector.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Provides a list of choices and collects the selected choice.                                                                               |
| [ConfirmationCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#ConfirmationCallback)                   | * [LDAP Decision node](https://docs.pingidentity.com/auth-node-ref/latest/ldap-decision.html)

* [Message node](https://docs.pingidentity.com/auth-node-ref/latest/message.html)

* [MFA Registration Options node](https://docs.pingidentity.com/auth-node-ref/latest/mfa-registration-options.html)

* [OATH Token Verifier node](https://docs.pingidentity.com/auth-node-ref/latest/oath-token-verifier.html)

* [Polling Wait node](https://docs.pingidentity.com/auth-node-ref/latest/polling-wait.html)

* [Push Wait node](https://docs.pingidentity.com/auth-node-ref/latest/push-wait.html)

* [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/latest/webauthn-authentication.html)

* [OATH Registration node](https://docs.pingidentity.com/auth-node-ref/latest/oath-registration.html) | Collects a boolean-style confirmation, such as yes/no or true/false with an optional "Cancel" choice.                                      |
| [ConsentMappingCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#ConsentMappingCallback)               | - [Consent Collector node](https://docs.pingidentity.com/auth-node-ref/latest/consent-collector.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Provides profile attributes that require user consent and collects consent from the user.                                                  |
| [KbaCreateCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#KbaCreateCallback)                         | * [KBA Definition node](https://docs.pingidentity.com/auth-node-ref/latest/kba-definition.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Collects knowledge-based authentication (KBA) answers to questions defined in the user profile, or user-defined question and answer pairs. |
| [NumberAttributeInputCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#NumberAttributeInputCallback)   | - [Attribute Collector node](https://docs.pingidentity.com/auth-node-ref/latest/attribute-collector.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Collects a numeric attribute, such as size or age.                                                                                         |
| [StringAttributeInputCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#StringAttributeInputCallback)   | * [Attribute Collector node](https://docs.pingidentity.com/auth-node-ref/latest/attribute-collector.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Collects string attributes, such as city names, telephone numbers, and postcodes.                                                          |
| [TermsAndConditionsCallback](https://docs.pingidentity.com/pingoneaic/am-authentication/callbacks-interactive.html#TermsAndConditionsCallback)       | - [Accept Terms and Conditions node](https://docs.pingidentity.com/auth-node-ref/latest/accept-terms-and-conditions.html)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Displays the current terms and conditions and collects the user's agreement to them.                                                       |

You can access these with `step.callbacks`. Your app should iterate through the received callbacks and display the appropriate user interface to the user to update the values.

For example, you could call a component to display the UI for each callback:

Handling user profile self-service callbacks

```typescript
// Start the user profile self-service flow
let step = await journeyClient.start({
  journey: "sdkProfileManagement",
  query: {
    forceAuth: true,
    noSession: true,
  },
});

while (step.type === "Step") {
  const callbacks = step.callbacks;
  // Iterate through callbacks
  callbacks.forEach((callback, idx) => {
    // Check the callback type
    switch (callback.getType()) {
      case "BooleanAttributeInputCallback":
      case "NumberAttributeInputCallback":
      case "StringAttributeInputCallback":
        attributeInputComponent(
          journeyEl,
          callback as AttributeInputCallback<string | number | boolean>,
          idx,
        );
        break;
      case "ChoiceCallback":
        choiceComponent(journeyEl, callback as ChoiceCallback, idx);
        break;
      case "ConfirmationCallback":
        confirmationComponent(journeyEl, callback as ConfirmationCallback, idx);
        break;
      case "KbaCreateCallback":
        kbaCreateComponent(journeyEl, callback as KbaCreateCallback, idx);
        break;
      case "TermsAndConditionsCallback":
        termsAndConditionsComponent(
          journeyEl,
          callback as TermsAndConditionsCallback,
          idx,
        );
        break;
      default:
        console.warn(`Unknown callback type: ${callback.getType()}`);
        break;
    }
  });
}
```

Attribute collector callbacks will usually have a `prompt` property to describe the field, and a `value` field containing the current or default value.

Example component for Boolean, String, and Number attribute callbacks

```typescript
import type { AttributeInputCallback } from '@forgerock/journey-client/types';

export default function attributeInputComponent(
  journeyEl: HTMLDivElement,
  callback: AttributeInputCallback<string | number | boolean>,
  idx: number,
) {
  const collectorKey = callback?.payload?.input?.[0].name || `collector-${idx}`;
  const label = document.createElement('label');
  const input = document.createElement('input');

  label.htmlFor = collectorKey;
  label.innerText = callback.getPrompt();

  // Determine input type based on attribute type
  const attributeType = callback.getType();
  if (attributeType === 'BooleanAttributeInputCallback') {
    input.type = 'checkbox';
    input.checked = (callback.getInputValue() as boolean) || false;
  } else if (attributeType === 'NumberAttributeInputCallback') {
    input.type = 'number';
    input.value = String(callback.getInputValue() || '');
  } else {
    input.type = 'text';
    input.value = String(callback.getInputValue() || '');
  }

  input.id = collectorKey;
  input.name = collectorKey;
  input.required = callback.isRequired();

  journeyEl?.appendChild(label);
  journeyEl?.appendChild(input);

  journeyEl?.querySelector(`$#{collectorKey}`)?.addEventListener('input', (event) => {
    const target = event.target as HTMLInputElement;
    if (attributeType === 'BooleanAttributeInputCallback') {
      callback.setInputValue(target.checked);
    } else if (attributeType === 'NumberAttributeInputCallback') {
      callback.setInputValue(Number(target.value));
    } else {
      callback.setInputValue(target.value);
    }
  });
}
```
