@forgerock/journey-client is a JavaScript client for interacting with ForgeRock Access Management (AM) authentication journeys (authentication trees). It provides a stateful, developer-friendly API that abstracts the complexities of the underlying authentication flow.
Note: This client is designed specifically for ForgeRock AM servers. For PingOne DaVinci flows, use
@forgerock/davinci-client. For standard OIDC operations, use@forgerock/oidc-client.
baseUrl, authenticate, and sessions paths directly from the well-known responsepnpm add @forgerock/journey-client
# or
npm install @forgerock/journey-client
# or
yarn add @forgerock/journey-client
import { journey } from '@forgerock/journey-client';
import { callbackType } from '@forgerock/sdk-types';
async function authenticateUser() {
// Initialize the client with wellknown discovery
try {
const client = await journey({
config: {
serverConfig: {
wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration',
},
},
});
// Start the authentication journey
let step = await client.start({ journey: 'Login' });
// Handle callbacks in a loop until success or failure
while (step?.type === 'Step') {
const nameCallbacks = step.getCallbacksOfType(callbackType.NameCallback);
for (const cb of nameCallbacks) {
cb.setName('demo');
}
const passwordCallbacks = step.getCallbacksOfType(callbackType.PasswordCallback);
for (const cb of passwordCallbacks) {
cb.setPassword('password');
}
step = await client.next(step);
}
// Check the final result
if (step?.type === 'LoginSuccess') {
console.log('Login successful!', step.getSessionToken());
} else if (step?.type === 'LoginFailure') {
console.error('Login failed:', step.payload.message);
}
} catch (error) {
console.error('Failed to initialize client:', error);
}
}
The client requires only the OIDC wellknown endpoint URL. All other configuration is derived automatically from the well-known response:
import type { JourneyClientConfig } from '@forgerock/journey-client/types';
const config: JourneyClientConfig = {
serverConfig: {
wellknown: 'https://am.example.com/am/oauth2/alpha/.well-known/openid-configuration',
},
};
The client automatically derives all needed configuration from the well-known response:
| Property | Derived From |
|---|---|
baseUrl |
authorization_endpoint origin |
authenticate |
Issuer path with /oauth2 replaced by /json, plus /authenticate |
sessions |
Issuer path with /oauth2 replaced by /json, plus /sessions/ |
journey(options)Factory function that creates a journey client instance. Throws on initialization failure (invalid URL, fetch error, non-AM server).
const client = await journey({
config: JourneyClientConfig,
requestMiddleware?: RequestMiddleware[],
logger?: { level: LogLevel; custom?: CustomLogger },
});
Returns: Promise<JourneyClient>
Throws: Error if the wellknown URL is invalid, the fetch fails, or the server is not a ForgeRock AM instance.
try {
const client = await journey({ config });
} catch (error) {
console.error('Initialization failed:', error.message);
}
client.start(options?)Initiates a new authentication journey.
const step = await client.start({
journey: 'Login', // Required: Journey/tree name
query: { locale: 'en' }, // Optional: Query parameters
});
Returns: Promise<JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | undefined>
client.next(step, options?)Submits the current step and retrieves the next one.
const nextStep = await client.next(step, {
query: { noSession: 'true' }, // Optional: Query parameters
});
Returns: Promise<JourneyStep | JourneyLoginSuccess | JourneyLoginFailure | undefined>
client.redirect(step)Handles redirect callbacks by redirecting the browser.
await client.redirect(step);
client.resume(url, options?)Resumes a journey after an external redirect.
const step = await client.resume(window.location.href, {
journey: 'Login', // Optional: Override journey name
});
client.terminate(options?)Ends the current session.
await client.terminate();
The JourneyStep object provides methods to access and manipulate callbacks:
// Get all callbacks of a type
const nameCallbacks = step.getCallbacksOfType(callbackType.NameCallback);
// Get a single callback (throws if not exactly one)
const nameCallback = step.getCallbackOfType(callbackType.NameCallback);
// Common callback operations
nameCallback.getPrompt(); // Get the prompt text
nameCallback.setName('value'); // Set the input value
passwordCallback.getPrompt();
passwordCallback.setPassword('value');
choiceCallback.getChoices();
choiceCallback.setChoice(0);
Add custom logic to requests using middleware:
import type { RequestMiddleware } from '@forgerock/journey-client/types';
const loggingMiddleware: RequestMiddleware = (req, action, next) => {
console.log(`${action.type}: ${req.url}`);
next();
};
const client = await journey({
config,
requestMiddleware: [loggingMiddleware],
});
| Action Type | Description |
|---|---|
JOURNEY_START |
Starting a new journey |
JOURNEY_NEXT |
Submitting a step |
JOURNEY_TERMINATE |
Terminating the session |
The journey() factory throws on initialization failure. Use try/catch:
try {
const client = await journey({ config });
// client is guaranteed to be a JourneyClient
} catch (error) {
// Handle initialization errors (invalid URL, fetch failure, non-AM server)
console.error('Failed to initialize:', error.message);
}
pnpm nx build @forgerock/journey-client
pnpm nx test @forgerock/journey-client