PingAM 8.0.0

Config interface

The Config interface defines the configuration data for a node. A node can’t have state, but it can have configuration data. Configuration is per node. Different nodes of the same type in the same tree have their own configuration.

You don’t need to write a class that implements the interface you define. AM automatically creates this as required.

Define node properties

Configure the node properties using methods. To provide a default value to the tree administrator, mark the method as default and define both a method and a value. To omit a default value, define the method’s signature but not the implementation.

For example:

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;
  }
}

For this Config example, a custom enum named LockStatus is returned.

The defined properties appear as configurable options in the tree designer view when adding a node of the relevant type. The options display to the user automatically.

Attribute names are used when localizing the node’s text. Learn more in Internationalize nodes.

The output from an example Config interface

You can find more information in the Config annotation type in the AM Public API Javadoc.

The @Attribute annotation

The @Attribute annotation is required. It defines the properties that appear as configurable options when you add or update a node.

Consider the following when using the @Attribute annotation:

  • You must specify an integer value for order to determine the position of the attribute in the UI.

  • Only use compatible Java types as attributes.

    Compatible Java types
    Java type Additional information

    java.lang.String

    java.lang.Integer

    java.lang.Long

    java.lang.Boolean

    java.lang.Enum

    Use any enum type.

    org.forgerock.json.JsonValue

    java.util.Locale

    java.net.URL

    char[] (char array)

    Use for passwords, but consider using org.forgerock.secrets.Purpose instead.

    java.util.List

    java.util.Set

    java.util.Map

    Use with the following elements:

    • Boolean

    • Duration

    • Integer

    • Locale

    • Long

    • String

    • URL

    • JsonValue

    • char[]

    Keys must be strings for java.util.Map.

    java.util.Optional

    Use with any of these compatible Java types.

    org.forgerock.secrets.Purpose

    Use for secret values such as passwords.

    You must annotate this type with @SecretPurpose to define the secret label.

  • Include requiredValue = true if the attribute is a required value.

    Any attributes that aren’t required should be an Optional attribute unless they’re already part of a collection through List, Map, or Set.

    Attributes aren’t required by default when either requiredValue is omitted or set to false.

  • Specify one or more validators if you need to validate the attribute values provided.

    Include a validator as follows:

    • Use an existing validator class from the org.forgerock.openam.auth.nodes.validators package, such as DecimalValidator or HMACKeyLengthValidator.

    • Create your own validator by implementing the ServiceAttributeValidator interface.

      Example

      The following example creates a validator called GreaterThanZeroValidator:

      public class GreaterThanZeroValidator implements ServiceAttributeValidator {
      
          @Override
          public boolean validate(Set<String> values) {
              boolean isValid = true;
              for (String value : values) {
                  if (Integer.parseInt(value) <= 0) {
                      isValid = false;
                      break;
                  }
              }
              return isValid;
          }
      }

For example:

public interface Config {
  @Attribute(order = 1)
  String domain();                                                    1

  @Attribute(order = 2, validators = {DecimalValidator.class,         2
                                      HMACKeyLengthValidator.class})
  int exampleNumber();

  @Attribute(order = 3, requiredValue = true)
  boolean isVerificationRequired();                                   3

  @Attribute(order = 4)
  @TextArea                                                           4
  String textBox();

  @Attribute(order = 5)
  @Password                                                           5
  char[] clientSecret();

  @Attribute(order = 6)
  default YourCustomEnum action() {
    return YourCustomEnum.LockScreen;                                 6

  @Attribute(order = 7, requiredValue = true, resourceName = "secretLabelIdentifier")
  @SecretPurpose("am.authentication.nodes.customauth.%s.secret")
  Purpose<GenericSecret> secretValuePurpose();                        7
  };
}

1 The domain attribute defines a String-type node property for display in the UI. Access the attribute in the process method by using a reference to the config interface; for example, config.domain().

2 Specify one or more validator classes as the validators parameter.

3 The boolean attribute is defined as a required value.

4 Use the TextArea annotation to indicate a String-type node property that needs a larger text input than a single line.

5 Use the Password annotation to mask the input characters and encrypt the value of the attribute.

6 A custom enum attribute. This provides type safety and negates the misuse of Strings as generic type-unsafe value holders. The UI will correctly handle the enum and only let the tree administrator choose from the defined enum values.

Learn more in the Attribute annotation type in the AM Public API Javadoc.

7 An identifier used to create a secret label for the node that maps to a secret in a secret store. The default custom authentication node secret label is am.authentication.nodes.customauth.%s.secret where %s is the value of the identifier. The identifier can only contain alphanumeric characters a-z, A-Z, 0-9, and periods (.). It can’t start or end with a period.

To retrieve the secret using the identifier from your custom node, use the Secrets class, for example:

var validSecrets = secrets.getRealmSecrets(realm)
        .getValidSecrets(config.secretValuePurpose())
        .getOrThrowIfInterrupted()
        .map(s → s.revealAsUtf8(String::new))
        .collect(Collectors.toList());

Learn more in: