Skip to content

Instantly share code, notes, and snippets.

@cerebrl
Created October 31, 2022 15:28
Show Gist options
  • Save cerebrl/868fe5405d65f257066f07763bc53390 to your computer and use it in GitHub Desktop.
Save cerebrl/868fe5405d65f257066f07763bc53390 to your computer and use it in GitHub Desktop.
Registering a custom callback with ForgeRock's JavaScript SDK

Registering a custom callback

Fair warning: you are going to wade into advanced usage of the SDK, so prepare yourself for a complicated topic :)

To do this, you have a few options when it comes to custom callback handlers. It really depends on how much you want to preserve of the default handlers of the JavaScript SDK. Essentially callback handlers are JavaScript classes that provide better ergonomics around handling the callbacks that come from AM. They do this by "decorating" the plain JSON object that represents the current journey/tree node in AM with prototypal methods (I hope this makes sense).

Because the object that contains the callback is still just a JavaScript object at its core, you are not required to mutate its values through the SDK provided callback handlers exclusively. You could write your own getters and setters for the data, and use them independently have the provided callback handlers.

The main concept is that you receive a step object after calling next:

step = FRAuth.next();

... you then mutate that step object according to AM's expectations. This could be done using either our SDK, directly using standard object and array path value assignment, or your own custom functions:

// Using our SDK's callback handler
step.getCallbackOfType('NameCallback').setName('user@example.com');

// Or, direct object and array path assignment
step.callbacks[0].input[0].value = 'user@example.com';

// Or, you create your own custom function
step = myCustomCallbackFunction(step);

... the end result just needs to be that the step object gets the values assigned to the right callback input. Finally, you pass the newly mutated step back to AM:

step = FRAuth.next(step);

Now, if you want to preserve the SDK's ergonomics while adding custom behavior, you'll need to create your own callbacks by extending the base, generic FRCallback handler seen here: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/master/packages/javascript-sdk/src/fr-auth/callbacks/index.ts. Or, you can extend one of the higher-level callback handlers. It's up to you; it just needs to follow the expected interface design.

All the specific callback handlers like NameCallback or DeviceProfileCallback all extend this same base class. You can see this base class being extended here for NameCallback: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/master/packages/javascript-sdk/src/fr-auth/callbacks/name-callback.ts.

Once you have your callbacks written, you'll need to register them through a custom "callback factory" and set it into the config of the SDK. Here's the default callbackFactory: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/master/packages/javascript-sdk/src/fr-auth/callbacks/factory.ts.

To register your new callbacks with the SDK (preserving the original ergonomics), you'll need to copy the SDK's callback factory, and add your custom callback handlers to the factory. Then, when you call Config.set, you'll pass this custom callback factory as a property of the object:

Config.set({
  // ...
  callbackFactory; myCustomCallbackFactory,
  // ...
});

// Or, you can pass it to FRAuth.next for a specific request
step = FRAuth.next(step, {
  // ...
  callbackFactory; myCustomCallbackFactory,
  // ...
});

Once this is done, the next time you call FRAuth.next and the SDK receives the response from AM, it decorates the step object with your new callbacks using your custom callback factory here: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/master/packages/javascript-sdk/src/fr-auth/index.ts#L65. That should be it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment