ReactJS Authentication with Ping Orchestration JavaScript SDK (DaVinci)
Scaffold a complete authentication flow in a ReactJS single-page application using the Ping Orchestration JavaScript SDK (DaVinci).
Metadata
| Field | Value |
|---|---|
| Language | JavaScript (JSX) |
| Framework | React 18+, React Router 6+, Vite |
| SDK | Ping Identity DaVinci Client (@forgerock/davinci-client) |
| Pattern | Functional Components, Custom Hooks, Context API |
| Node.js | >= 18.12.0 |
Overview
This skill adds a complete authentication flow to a ReactJS single-page application. It uses the Ping Identity DaVinci Client (@forgerock/davinci-client) to authenticate users against PingOne DaVinci.
DaVinci vs Journey: DaVinci uses PingOne as the orchestration server (not PingAM/AIC). It uses the
@forgerock/davinci-clientpackage (not@forgerock/journey-client). DaVinci uses Collectors instead of Callbacks, and node status values (continue,success,error) instead of step types.
The implementation covers:
- DaVinci client initialization with OIDC configuration
- Custom React hook (
useDavinci) for managing the step-by-step authentication flow - Dynamic collector rendering with dedicated React components for each collector type
- Collector categories:
SingleValueCollector,ActionCollector,ObjectValueCollector,MultiValueCollector,NoValueCollector - Flow navigation via
FlowCollectorand form submission viaSubmitCollector - Protected route handling with React Router
- Context-based authentication state management
- Login and logout flows
- User profile display via OIDC userinfo
- Success, error, and failure handling
Use Cases
- Sample Application — Build a complete, themed ReactJS app from scratch to demonstrate how the DaVinci SDK works with PingOne DaVinci. This includes all SDK integration files plus a full UI with navigation, styled views, a user profile page, and protected content.
- Existing Application Integration — Integrate the DaVinci SDK into an existing ReactJS SPA to add authentication. The agent should generate only the SDK integration files (constants, context, hook, form, collectors) and guide the user on wiring them into their existing router and layout.
Prerequisites
1. npm Dependencies
Install the following packages in your React project:
npm install @forgerock/davinci-client react react-dom react-router-dom
Optional dependencies for additional features:
# PingOne Protect integration
npm install @forgerock/protect
# OIDC client for token management post-authentication
npm install @forgerock/oidc-client
See package.json template for a complete example.
2. Vite Configuration
This skill uses Vite as the build tool. See vite.config.js template for the recommended configuration.
npm install --save-dev vite @vitejs/plugin-react
3. Environment Variables
Create a .env file in your project root. See .env template.
Also add a .gitignore to keep secrets and build artifacts out of version control. See .gitignore template.
VITE_CLIENT_ID=your-client-id
VITE_DISCOVERY_ENDPOINT=https://auth.pingone.com/<envId>/as/.well-known/openid-configuration
VITE_REDIRECT_URI=http://localhost:5173/callback
VITE_SCOPE=openid email profile
Required Configuration
Agent instruction: Before generating any file, collect the values below from the user. Ask for all
requiredparameters up front in a single prompt. For optional parameters, show the default and ask whether the user wants to override it. Do not proceed to Step 1 until every required parameter has a non-empty value.
Parameters to collect
| Parameter | Required | Default | Description |
|---|---|---|---|
clientId |
Yes | — | OAuth 2.0 Client ID registered in PingOne for this web app |
serverConfig.wellknown |
Yes | — | Full OIDC discovery endpoint URL from PingOne |
scope |
Yes | openid email profile |
Space-separated OAuth 2.0 scopes |
redirectUri |
Yes | http://localhost:5173/callback |
OAuth 2.0 redirect URI |
Suggested prompts
Before I generate the files, I need a few details about your PingOne DaVinci setup:
1. Client ID — What is the OAuth 2.0 Client ID for this web app?
(From your PingOne OIDC Web App configuration)
2. Well-Known URL — What is the OIDC discovery endpoint?
e.g. https://auth.pingone.com/<envId>/as/.well-known/openid-configuration
3. Scopes — Which OAuth 2.0 scopes? (default: openid email profile)
4. Redirect URI — What is the redirect URI? (default: http://localhost:5173/callback)
Validation rules
serverConfig.wellknownmust end with/.well-known/openid-configuration.clientIdmust be non-empty.redirectUrimust be a valid URL.- If
scopedoes not includeopenid, prepend it automatically and warn the user.
Implementation Steps
Step 1 — Create Constants
Create constants.js. See constants.js template.
export const DAVINCI_CONFIG = {
clientId: import.meta.env.VITE_CLIENT_ID,
serverConfig: {
wellknown: import.meta.env.VITE_DISCOVERY_ENDPOINT,
},
scope: import.meta.env.VITE_SCOPE,
redirectUri: import.meta.env.VITE_REDIRECT_URI,
};
See the @forgerock/davinci-client section in SDK Package Reference for all configuration options.
Step 2 — Create the DaVinci Hook
Create use-davinci.hook.js. See use-davinci.hook.js template.
Key responsibilities:
- Initialize the DaVinci client via
davinci({ config }) - Manage node state (
continue,success,error,start) - Expose
getClient(),getCollectors(),update(),flow(),next()methods - Handle flow navigation and form submission
Step 3 — Create the Form Component
Create form.jsx. See form.jsx template.
The form component dispatches each collector to its dedicated React component:
function mapCollectorsToComponents(davinciClient, collectors, submitForm) {
return collectors.map((collector) => {
switch (collector.type) {
case 'TextCollector': return <TextCollector key={collector.id} collector={collector} updater={davinciClient.update(collector)} />;
case 'PasswordCollector': return <PasswordCollector key={collector.id} collector={collector} updater={davinciClient.update(collector)} />;
case 'SubmitCollector': return <SubmitButton key={collector.id} collector={collector} submitForm={submitForm} />;
case 'FlowCollector': return <FlowButton key={collector.id} collector={collector} startFlow={davinciClient.flow({ action: collector.output.key })} />;
// ... more collectors
}
});
}
See the collector template files in this skill's assets/ directory for the full list of supported collector implementations.
Step 4 — Create Collector Components
Create individual React component files for each collector type. See the assets/ directory for all templates.
All collector types supported by the Ping JavaScript DaVinci SDK:
Single Value Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
TextCollector |
TextCollector |
SingleValueCollector |
Text input (username, email) |
PasswordCollector |
PasswordCollector |
SingleValueCollector |
Secure password input |
SingleSelectCollector |
SingleSelectCollector |
SingleValueCollector |
Dropdown/radio selection |
Validated Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
ValidatedTextCollector |
TextCollector |
ValidatedSingleValueCollector |
Text input with validation rules |
Action Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
SubmitCollector |
SubmitButton |
ActionCollector |
Form submission button |
FlowCollector |
FlowButton |
ActionCollector |
Flow navigation button/link |
IdpCollector |
SocialLoginButton |
ActionCollector |
Social login (Google, Facebook, Apple) |
Multi-Value Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
MultiSelectCollector |
MultiSelectCollector |
MultiValueCollector |
Multi-select checkboxes |
Object Value Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
DeviceRegistrationCollector |
DeviceRegistration |
ObjectValueCollector |
MFA device registration |
DeviceAuthenticationCollector |
DeviceAuthentication |
ObjectValueCollector |
MFA device authentication |
PhoneNumberCollector |
PhoneNumber |
ObjectValueCollector |
Phone number input |
No-Value / Read-Only Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
ReadOnlyCollector |
ReadOnly |
NoValueCollector |
Static text/label display |
Auto-Advancing Collectors:
| Collector Type | Component | Category | Description |
|---|---|---|---|
ProtectCollector |
Protect |
SingleValueAutoCollector |
PingOne Protect risk signals |
FidoRegistrationCollector |
FidoRegistration |
ObjectValueAutoCollector |
FIDO2 passkey / security-key registration |
FidoAuthenticationCollector |
FidoAuthentication |
ObjectValueAutoCollector |
FIDO2 passkey / security-key authentication |
Each collector component follows this pattern:
- Receive the collector object and an updater/flow function as props
- Render an appropriate HTML/React control
- Call the updater with user input:
updater(value)for value collectors - Call the flow function for
FlowCollector:startFlow()navigates to new flow - Call
submitForm()forSubmitCollector: advances to next node
Key API Methods:
davinciClient.update(collector)— Returns an updater function for value collectorsdavinciClient.flow({ action: collector.output.key })— Returns a function to start a new flowdavinciClient.next()— Submits the current node and advances to the nextdavinciClient.validate(collector)— Returns a validator function for validated collectors
Step 5 — Create the Login Page
Create login.jsx. See login.jsx template.
export default function Login() {
const { davinciClient, clientInfo, collectors, submitForm, startFlow, error } = useDavinci();
if (!clientInfo || clientInfo.status === 'start') return <p>Loading...</p>;
if (clientInfo.status === 'success') return <Navigate to="/home" />;
return (
<form => { e.preventDefault(); submitForm(); }}>
<h2>{clientInfo.name}</h2>
{error && <div className="error">{error.message}</div>}
<DaVinciForm davinciClient={davinciClient} collectors={collectors} submitForm={submitForm} />
</form>
);
}
Step 6 — Create the OAuth Callback Page
Create callback.jsx. See callback.jsx template.
Step 7 — Wire Navigation
<BrowserRouter>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/callback" element={<Callback />} />
<Route path="/home" element={<ProtectedRoute><Home /></ProtectedRoute>} />
</Routes>
</BrowserRouter>
Scaffolding Script
For quick setup, use the scaffolding script to copy all template files into your project:
chmod +x scripts/scaffold_auth.sh
./scripts/scaffold_auth.sh \
--target-dir src
See scaffold_auth.sh for details.
Common Mistakes
| Mistake | Fix |
|---|---|
Using @forgerock/journey-client instead of @forgerock/davinci-client |
DaVinci uses a separate package — install @forgerock/davinci-client |
Missing openid scope |
Always include openid — required for OIDC token exchange |
| Wrong discovery endpoint | Must end with /.well-known/openid-configuration and point to your PingOne environment |
Calling update() without the collector |
davinciClient.update(collector) requires the collector object as argument |
Not calling flow() for FlowCollector |
Flow navigation requires davinciClient.flow({ action: collector.output.key }), not next() |
| Hardcoding credentials | Use environment variables — never commit secrets |
Not handling error status |
Check clientInfo.status === 'error' and display error messages from davinciClient.getError() |
| Confusing collector categories | Check collector.category (SingleValueCollector, ActionCollector, etc.) to determine how to handle each collector |
Reference Documentation
- SDK Package Reference — Package selection guide for
@forgerock/davinci-client,@forgerock/oidc-client, and optional add-ons - OIDC Centralized Reference — Full
@forgerock/oidc-clientAPI: authorize, token exchange, user info, logout, storage - Collector implementations — see template files in
assets/(e.g.text.jsx.template,password.jsx.template,fido-registration.jsx.template,social-login-button.jsx.template)
Related Skills
ping-orchestration-javascript-sdk— JavaScript umbrella skill (routes Journey/DaVinci/OIDC, delegates here for DaVinci flows)ping-orchestration-reactjs-journey-sdk— ReactJS authentication using the Journey module (for PingOne AIC/PingAM)ping-orchestration-android-sdk— Android (Kotlin/Jetpack Compose) DaVinci equivalentping-orchestration-ios-sdk— iOS (Swift/SwiftUI) DaVinci equivalent