---
title: Node class
description: In Java terms, an authentication node is a class that implements the Node interface, org.forgerock.openam.auth.node.api.Node.
component: pingam
version: 7.2
page_id: pingam:auth-nodes:core-class
canonical_url: https://docs.pingidentity.com/pingam/8.1/auth-nodes/core-class.html
llms_txt: https://docs.pingidentity.com/pingam/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
superseded_by: https://docs.pingidentity.com/pingam/8.1/auth-nodes/core-class.html
section_ids:
  annotation: Annotation
  private_constants: Private constants
  config: Config
  constructor: Constructor
  process_method: process method
  private_methods: Private methods
  custom_outcome_provider: Custom outcome provider
  example_implementation: Example implementation
---

# Node class

In Java terms, an authentication node is a class that implements the `Node` interface, `org.forgerock.openam.auth.node.api.Node`.

The `Node` class may access and modify the persisted state that is shared between the nodes within a tree, and may request input by using callbacks. The class also defines the possible exit paths from the node.

The class is *annotated* with `org.forgerock.openam.auth.node.api.Node.Metadata`. The annotation has two main attributes - `configClass` and `outcomeProvider`. Typically, the `configClass` attribute is an inner interface in the node implementation class.

For simple use cases, the abstract implementations of the node interface, `org.forgerock.openam.auth.node.api.SingleOutcomeNode` and `org.forgerock.openam.auth.node.api.AbstractDecisionNode`, have their own outcome providers that can be used. For more complex use cases you can provide your own implementation.

The sections that follow describe the `Node` class.

## `Annotation`

The *annotation* specifies the outcome provider and configuration class. The outcome provider can use the default `SingleOutcomeNode` or `MultipleOutcomeNode`, or a custom `OutcomeProvider` can be created and referenced from the annotation.

See the [Choice Collector node](../authentication-guide/auth-node-configuration-hints.html#auth-node-choice-collector) for an example of a custom outcome provider.

## Private constants

These are optional.

## `Config`

The *config* interface defines the configuration data for a node. A node cannot have state, but it can have configuration data.

Note that you do not need to provide the implementation class for the `Config` interface you define. AM will create these automatically, as required.

An example is the [Account Lockout node](../authentication-guide/auth-node-configuration-hints.html#auth-node-account-lockout). The node can be configured to lock or unlock the users' account, based on it's configuration.

Configuration is per-node. Different nodes of the same type in the same tree have their own configuration.

The `config` interface configures values using methods. To provide no default value to the tree administrator, provide the method's signature but not the implementation. To provide a default value to the tree administrator, mark the method as `default` and provide both a method and a value. For example:

```java
public interface Config {

  //This will have no default value for the UI
  @Attribute(order = 10)
  String noDefaultAttribute();

  //This will default to the value LOCK.
  @Attribute(order = 20)
  default LockStatus lockAction() {
    return LockStatus.LOCK;
  }
}
```

The `Config` above would resemble the following in the tree designer view:

![The output from an example Config interface.](_images/config-interface-in-ui.png)

The `@Attribute` annotation is required. It can be configured with an order value, which determines the position of the attribute in the UI, and with validators, to validate the values being set.

In the example above, a custom enum called `LockStatus` is returned. The options are displayed to the user automatically.

## `Constructor`

Dependencies should be injected by using Guice as this makes it easier to unit test your node. For example, you should accept the `config` as a parameter.

You may also wish to obtain AM core classes, such as `CoreWrapper`, instances of third-party dependencies, or your own types.

```java
@Inject
public AccountLockoutNode(CoreWrapper coreWrapper, @Assisted Config config)
throws NodeProcessException {
  this.coreWrapper = coreWrapper;
  this.config = config;
}
```

## `process` method

The *process* method takes a `TreeContext` parameter, does some processing, and returns an *Action* object.

An action encapsulates changes to state and flow control. The `TreeContext` parameter is used to access the request, callbacks, shared state and other input.

The `process` method is where state is retrieved and stored. The returning `Action` can be a response of callback to the user, an update of state, or a choice of outcome.

The choice of outcome in a simple decision node would be `true` or `false`, resulting in the authentication tree flow moving from the current node to a node at the relevant connection.

## Private methods

These are optional.

## Custom outcome provider

This is optional.

## Example implementation

The following example is the `SetSessionPropertiesNode` class, taken from the [Set Session Properties node](../authentication-guide/auth-node-configuration-hints.html#auth-node-set-session-properties):

```none
package org.forgerock.openam.auth.nodes;

import java.util.Map;

import javax.inject.Inject;

import org.forgerock.openam.annotations.sm.Attribute;
import org.forgerock.openam.auth.node.api.Action;
import org.forgerock.openam.auth.node.api.Node;
import org.forgerock.openam.auth.node.api.SingleOutcomeNode;
import org.forgerock.openam.auth.node.api.TreeContext;
import org.forgerock.openam.auth.nodes.validators.SessionPropertyValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.assistedinject.Assisted;

/**
 * A node which contributes a configurable set of properties to be added to the user's session, if/when it is created.
 */
@Node.Metadata(outcomeProvider = SingleOutcomeNode.OutcomeProvider.class,
        configClass = SetSessionPropertiesNode.Config.class) (1)
public class SetSessionPropertiesNode extends SingleOutcomeNode { (2)

    /**
     * Configuration for the node.
     */
    public interface Config { (3)
        /**
         * A map of property name to value.
         * @return a map of properties.
         */
        @Attribute(order = 100, validators = SessionPropertyValidator.class)
        Map<String, String> properties();
    }

    private final Config config;
    private final Logger logger = LoggerFactory.getLogger("amAuth");

    /**
     * Constructs a new SetSessionPropertiesNode instance.
     * @param config Node configuration.
     */
    @Inject (4)
    public SetSessionPropertiesNode(@Assisted Config config) {
        this.config = config;
    }

    @Override
    public Action process(TreeContext context) { (5)
        logger.debug("SetSessionPropertiesNode started");
        Action.ActionBuilder actionBuilder = goToNext();
        config.properties().entrySet().forEach(property -> {
            actionBuilder.putSessionProperty(property.getKey(), property.getValue());
            logger.debug("set session property {}", property);
        });
        return actionBuilder.build();
    }
}
```

|       |                                                                                             |
| ----- | ------------------------------------------------------------------------------------------- |
| **1** | The `@Node.Metadata` annotation. See [Metadata annotation](core-metadata.html).             |
| **2** | Implementing the `Node` interface. See [Node interface](core-node.html).                    |
| **3** | Implementing the `Config` interface. See [Config interface](core-config.html).              |
| **4** | Injecting the `Node` instance. See [Inject objects into a node instance](core-inject.html). |
| **5** | Creating an `Action` instance. See [Action class](core-action.html).                        |
