diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a320b14029..71e905285a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build on: push: + branches: [ 'sustaining/6.3.x','master' ] pull_request: branches: [ 'sustaining/6.3.x','master' ] diff --git a/openidm-core/src/main/java/org/forgerock/openidm/managed/ManagedObjectSet.java b/openidm-core/src/main/java/org/forgerock/openidm/managed/ManagedObjectSet.java index b5c28c1648..5b392fcab5 100644 --- a/openidm-core/src/main/java/org/forgerock/openidm/managed/ManagedObjectSet.java +++ b/openidm-core/src/main/java/org/forgerock/openidm/managed/ManagedObjectSet.java @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2011-2016 ForgeRock AS. + * Portions copyright 2026 3A Systems, LLC. */ package org.forgerock.openidm.managed; @@ -149,6 +150,9 @@ private enum ScriptHook { /** Script to execute once an object is retrieved from the repository. */ onRetrieve, + /** Script to execute for each object returned from a query; return false to exclude the object. */ + onQueryResult, + /** Script to execute when an object is about to be stored in the repository. */ onStore, @@ -1286,6 +1290,33 @@ public boolean handleResource(ResourceResponse resource) { return false; } } + // Execute the onQueryResult script if configured; skip object if it returns a falsy value + try { + Object queryResultScriptResult = execScriptHook(managedContext, ScriptHook.onQueryResult, + resource.getContent(), + prepareScriptBindings(managedContext, request, resource.getId(), + new JsonValue(null), new JsonValue(null))); + // Normalize the script result using simple truthiness semantics: + // - null (or no return) => include (do not filter) + // - Boolean false, numeric zero, or empty string => exclude + if (queryResultScriptResult != null) { + boolean include = true; + if (queryResultScriptResult instanceof Boolean) { + include = (Boolean) queryResultScriptResult; + } else if (queryResultScriptResult instanceof Number) { + include = ((Number) queryResultScriptResult).doubleValue() != 0.0d; + } else if (queryResultScriptResult instanceof CharSequence) { + include = ((CharSequence) queryResultScriptResult).length() != 0; + } + if (!include) { + // Object excluded by onQueryResult script + return true; + } + } + } catch (ResourceException e) { + ex[0] = e; + return false; + } if (ServerConstants.QUERY_ALL_IDS.equals(request.getQueryId())) { // Don't populate relationships if this is a query-all-ids query. resourceResponse = resource; diff --git a/openidm-core/src/test/java/org/forgerock/openidm/managed/ManagedObjectSetTest.java b/openidm-core/src/test/java/org/forgerock/openidm/managed/ManagedObjectSetTest.java index 2f9fde0e01..81f0f768e3 100644 --- a/openidm-core/src/test/java/org/forgerock/openidm/managed/ManagedObjectSetTest.java +++ b/openidm-core/src/test/java/org/forgerock/openidm/managed/ManagedObjectSetTest.java @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions copyright 2026 3A Systems, LLC. */ package org.forgerock.openidm.managed; @@ -38,6 +39,7 @@ import java.security.KeyStore; import java.security.KeyStore.PasswordProtection; import java.security.KeyStore.SecretKeyEntry; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -48,12 +50,14 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import org.forgerock.json.JsonPointer; import org.forgerock.json.JsonValue; import org.forgerock.json.crypto.JsonDecryptFunction; import org.forgerock.json.crypto.simple.SimpleDecryptor; import org.forgerock.json.crypto.simple.SimpleKeySelector; import org.forgerock.json.crypto.simple.SimpleKeyStoreSelector; import org.forgerock.json.resource.MemoryBackend; +import org.forgerock.json.resource.QueryRequest; import org.forgerock.json.resource.ResourceException; import org.forgerock.json.resource.ResourceResponse; import org.forgerock.json.resource.Router; @@ -78,6 +82,7 @@ import org.forgerock.services.context.RootContext; import org.forgerock.util.promise.Promise; import org.forgerock.util.promise.ResultHandler; +import org.forgerock.util.query.QueryFilter; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; @@ -100,6 +105,7 @@ public class ManagedObjectSetTest { private static final String CONF_MANAGED_USER_USING_ALIAS1 = "/conf/managed-user-alias1.json"; private static final String CONF_MANAGED_USER_USING_NO_ENCRYPTION = "/conf/managed-user-no-encryption.json"; private static final String CONF_MANAGED_USER_WITH_ACTION = "/conf/managed-user-action.json"; + private static final String CONF_MANAGED_USER_WITH_ON_QUERY_RESULT = "/conf/managed-user-on-query-result.json"; private static final String RESOURCE_ID = "user1"; private static final String KEYSTORE_PASSWORD = "Password1"; private static final int NUMBER_OF_USERS = 5; @@ -481,6 +487,14 @@ private ManagedObjectSet createManagedObjectSet(final String configJson, final C new NullActivityLogger()); } + private ManagedObjectSet createManagedObjectSetWithScriptRegistry(final String configJson, + final CryptoService cryptoService, final IDMConnectionFactory connectionFactory) throws Exception { + final AtomicReference routeService = new AtomicReference<>(mock(RouteService.class)); + final JsonValue config = getResource(configJson); + return new ManagedObjectSet(scriptRegistry, cryptoService, routeService, connectionFactory, config, + new NullActivityLogger()); + } + private JsonValue createUser(final String resourceId, final JsonValue userContent, final ManagedObjectSet managedObjectSet) throws ResourceException { Promise promise = managedObjectSet.createInstance(new RootContext(), @@ -537,6 +551,69 @@ List getErrors() { } } + /** + * Tests that when the {@code onQueryResult} script returns {@code false} for an object, + * that object is excluded from the query results. + */ + @Test + public void testQueryCollectionOnQueryResultExcludesObjects() throws Exception { + // given + final CryptoService cryptoService = createCryptoService(); + final ConnectionObjects connectionObjects = createConnectionObjects(); + final ManagedObjectSet managedObjectSet = + createManagedObjectSetWithScriptRegistry(CONF_MANAGED_USER_WITH_ON_QUERY_RESULT, cryptoService, + connectionObjects.getConnectionFactory()); + addRoutesToRouter(connectionObjects.getRouter(), managedObjectSet, new MemoryBackend()); + + // create 2 active users and 1 inactive user + createUser("activeUser1", createUserObject("activeUser1", true), managedObjectSet); + createUser("activeUser2", createUserObject("activeUser2", true), managedObjectSet); + createUser("inactiveUser", createUserObject("inactiveUser", false), managedObjectSet); + + // when: query all users + final List results = new ArrayList<>(); + final QueryRequest queryRequest = newQueryRequest(MANAGED_USER_RESOURCE_PATH) + .setQueryFilter(QueryFilter.alwaysTrue()); + managedObjectSet.queryCollection(new RootContext(), queryRequest, results::add) + .getOrThrowUninterruptibly(); + + // then: only active users are included; inactive user is excluded by onQueryResult + assertThat(results).hasSize(2); + assertThat(results.stream() + .map(r -> r.getContent().get(FIELD_ACTIVE).asBoolean()) + .allMatch(Boolean.TRUE::equals)).isTrue(); + } + + /** + * Tests that when no {@code onQueryResult} script is configured, all objects are returned + * from the query without any filtering. + */ + @Test + public void testQueryCollectionWithoutOnQueryResultIncludesAllObjects() throws Exception { + // given + final CryptoService cryptoService = createCryptoService(); + final ConnectionObjects connectionObjects = createConnectionObjects(); + final ManagedObjectSet managedObjectSet = + createManagedObjectSet(CONF_MANAGED_USER_USING_NO_ENCRYPTION, cryptoService, + connectionObjects.getConnectionFactory()); + addRoutesToRouter(connectionObjects.getRouter(), managedObjectSet, new MemoryBackend()); + + // create 3 users (mix of active/inactive) + createUser("user0", createUserObject("user0", "pwd0", "user0@example.com"), managedObjectSet); + createUser("user1", createUserObject("user1", "pwd1", "user1@example.com"), managedObjectSet); + createUser("user2", createUserObject("user2", "pwd2", "user2@example.com"), managedObjectSet); + + // when: query all users + final List results = new ArrayList<>(); + final QueryRequest queryRequest = newQueryRequest(MANAGED_USER_RESOURCE_PATH) + .setQueryFilter(QueryFilter.alwaysTrue()); + managedObjectSet.queryCollection(new RootContext(), queryRequest, results::add) + .getOrThrowUninterruptibly(); + + // then: all 3 users are returned (no onQueryResult hook to filter them) + assertThat(results).hasSize(3); + } + private static class ConnectionObjects { private IDMConnectionFactory connectionFactory; private Router router; diff --git a/openidm-core/src/test/resources/conf/managed-user-on-query-result.json b/openidm-core/src/test/resources/conf/managed-user-on-query-result.json new file mode 100644 index 0000000000..b847f33730 --- /dev/null +++ b/openidm-core/src/test/resources/conf/managed-user-on-query-result.json @@ -0,0 +1,17 @@ +{ + "name" : "user", + "onQueryResult" : { + "type" : "text/javascript", + "source" : "object.active !== false;" + }, + "schema" : { + "properties" : { + "_id" : { + "type" : "string" + }, + "active" : { + "type" : "boolean" + } + } + } +} diff --git a/openidm-doc/src/main/asciidoc/connectors-guide/chap-groovy.adoc b/openidm-doc/src/main/asciidoc/connectors-guide/chap-groovy.adoc index a3f86cd4d7..cd5354e5c0 100644 --- a/openidm-doc/src/main/asciidoc/connectors-guide/chap-groovy.adoc +++ b/openidm-doc/src/main/asciidoc/connectors-guide/chap-groovy.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-groovy] diff --git a/openidm-doc/src/main/asciidoc/connectors-guide/chap-ldap.adoc b/openidm-doc/src/main/asciidoc/connectors-guide/chap-ldap.adoc index 99517b306d..01d4385992 100644 --- a/openidm-doc/src/main/asciidoc/connectors-guide/chap-ldap.adoc +++ b/openidm-doc/src/main/asciidoc/connectors-guide/chap-ldap.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-ldap] diff --git a/openidm-doc/src/main/asciidoc/connectors-guide/chap-overview.adoc b/openidm-doc/src/main/asciidoc/connectors-guide/chap-overview.adoc index e7ae7a9b0a..163358cd01 100644 --- a/openidm-doc/src/main/asciidoc/connectors-guide/chap-overview.adoc +++ b/openidm-doc/src/main/asciidoc/connectors-guide/chap-overview.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-overview] diff --git a/openidm-doc/src/main/asciidoc/connectors-guide/index.adoc b/openidm-doc/src/main/asciidoc/connectors-guide/index.adoc index 7b1f6cbd95..9b8afda191 100644 --- a/openidm-doc/src/main/asciidoc/connectors-guide/index.adoc +++ b/openidm-doc/src/main/asciidoc/connectors-guide/index.adoc @@ -20,14 +20,14 @@ :toc: :authors: Lana Frost :copyright: Copyright 2011-2017 ForgeRock AS. -:copyright: Portions Copyright 2024 3A Systems LLC. +:copyright: Portions Copyright 2024-2026 3A Systems LLC. :imagesdir: ../ :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [abstract] This guide describes the connectors that are supported with OpenIDM {openidm-version-short}. The guide provides installation and configuration instructions for each connectors, and examples that demonstrate how to use the connectors in a deployment. diff --git a/openidm-doc/src/main/asciidoc/install-guide/appendix-ro-install.adoc b/openidm-doc/src/main/asciidoc/install-guide/appendix-ro-install.adoc index 7688344939..568a457cbc 100644 --- a/openidm-doc/src/main/asciidoc/install-guide/appendix-ro-install.adoc +++ b/openidm-doc/src/main/asciidoc/install-guide/appendix-ro-install.adoc @@ -12,13 +12,13 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 +:openidm-version: x.y.z [appendix] [#appendix-ro-install] diff --git a/openidm-doc/src/main/asciidoc/install-guide/chap-install.adoc b/openidm-doc/src/main/asciidoc/install-guide/chap-install.adoc index 8bc9709764..23470f1377 100644 --- a/openidm-doc/src/main/asciidoc/install-guide/chap-install.adoc +++ b/openidm-doc/src/main/asciidoc/install-guide/chap-install.adoc @@ -12,13 +12,13 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 +:openidm-version: x.y.z [#chap-install] diff --git a/openidm-doc/src/main/asciidoc/install-guide/chap-repository.adoc b/openidm-doc/src/main/asciidoc/install-guide/chap-repository.adoc index 95d9bd7fd3..46b1c8343a 100644 --- a/openidm-doc/src/main/asciidoc/install-guide/chap-repository.adoc +++ b/openidm-doc/src/main/asciidoc/install-guide/chap-repository.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-repository] diff --git a/openidm-doc/src/main/asciidoc/install-guide/chap-update.adoc b/openidm-doc/src/main/asciidoc/install-guide/chap-update.adoc index f888983263..5d98ff90c1 100644 --- a/openidm-doc/src/main/asciidoc/install-guide/chap-update.adoc +++ b/openidm-doc/src/main/asciidoc/install-guide/chap-update.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-update] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-auth-modules.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-auth-modules.adoc index f32c400c2e..cccac0dd8a 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-auth-modules.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-auth-modules.adoc @@ -12,7 +12,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: @@ -291,4 +291,282 @@ a|authentication.json |=== In general, if you add a custom property, the Admin UI writes changes to the `authentication.json` or `ui-configuration.json` files. +[#social-providers-module-details] +=== SOCIAL_PROVIDERS Module Configuration Options +The `SOCIAL_PROVIDERS` module is a meta-module (template) that dynamically generates `OPENID_CONNECT` and `OAUTH` authentication modules at startup for supported providers registered in the `IdentityProviderService`. The identity provider configurations themselves (client IDs, client secrets, authorization endpoints, etc.) are defined in `conf/identityProviders.json`, not inside the `SOCIAL_PROVIDERS` module entry. + +[NOTE] +====== +The `SOCIAL_PROVIDERS` entry is removed from the active authentication module list at startup — it is never initialized as an authenticator itself. Each `OPENID_CONNECT` or `OAUTH` provider entry in `conf/identityProviders.json` results in exactly one generated authentication module. +====== + +[#social-providers-module-prop-basic] +.SOCIAL_PROVIDERS Module Basic Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Module Enabled +a|true +a|Controls whether the meta-module activates and generates child modules. If set to `false`, no social provider auth modules are generated. +a|authentication.json + +a|Default User Roles +a|openidm-authorized +a|List of roles inherited by all generated `OAUTH` and `OPENID_CONNECT` modules. +a|authentication.json + +a|Method for Determining Roles +a|User Roles Property +a|How authorization roles are resolved. When set to `User Roles Property`, the value of the User Roles Property field is used as the attribute name on the managed object. +a|authentication.json + +a|User Roles Property +a|authzRoles +a|The managed-object attribute used for authorization roles. Applies when Method for Determining Roles is set to `User Roles Property`. +a|authentication.json + +|=== + +[#social-providers-module-prop-advanced] +.SOCIAL_PROVIDERS Module Advanced Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Use Query ID +a|(blank) +a|A defined `queryId` searches against the `queryOnResource` endpoint. Leave blank to use `action=reauthenticate`. +a|authentication.json + +a|Augment Security Context — Type +a|Javascript +a|Script language for the augment security context script. Supports `Javascript` or `Groovy`. +a|authentication.json + +a|Augment Security Context — File Path +a|auth/populateAsManagedUserFromRelationship.js +a|Path to the security context script, relative to the `bin/defaults/script` directory. This script is inherited by all generated `OAUTH` and `OPENID_CONNECT` modules. +a|authentication.json + +|=== + +[#openid-connect-module-details] +=== OPENID_CONNECT Module Configuration Options + +The `OPENID_CONNECT` module authenticates users via an OpenID Connect 1.0 provider. It exchanges an access token for user information from the provider's userinfo endpoint, then maps the identity to an OpenIDM managed object. + +The options shown in the Admin UI are subdivided into basic and advanced properties. You may need to click Advanced Properties to review those details. + +The following table describes the label that you see in the Admin UI, the default value (if any), a brief description, and the associated configuration file. If you need the property name, look at the configuration file. + +[#table-openid-connect-basic] +.OPENID_CONNECT Module Basic Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Module Enabled +a|false +a|Whether OpenIDM uses this module. +a|authentication.json + +a|Well-Known Endpoint +a|(blank) +a|OIDC Discovery URL (for example, `https://openam.example.com/openam/oauth2/.well-known/openid-configuration`). When provided, the module auto-populates `authorization_endpoint`, `token_endpoint`, and `userinfo_endpoint` from the provider's discovery document. +a|authentication.json + +a|Client ID +a|(blank) +a|OAuth 2.0 client ID registered with the OIDC provider. +a|authentication.json + +a|Client Secret +a|(blank) +a|OAuth 2.0 client secret registered with the OIDC provider. +a|authentication.json + +a|Scope +a|openid +a|OAuth 2.0 scopes to request. Must include `openid` (for example, `openid email profile`). +a|authentication.json + +a|Authorization Endpoint +a|(blank) +a|Provider's authorization endpoint URL. Can be omitted when Well-Known Endpoint is set. +a|authentication.json + +a|Token Endpoint +a|(blank) +a|Provider's token endpoint URL. Can be omitted when Well-Known Endpoint is set. +a|authentication.json + +a|End Session Endpoint +a|(blank) +a|Provider's end-session (logout) endpoint URL. Can be omitted when Well-Known Endpoint is set. +a|authentication.json + +a|Sign-In Button HTML +a|(default button HTML) +a|HTML markup for the social login button displayed in the OpenIDM UI. +a|authentication.json + +a|Query on Resource +a|managed/user +a|Managed object endpoint to query after token validation (for example, `managed/user`). +a|authentication.json + +a|Default User Roles +a|openidm-authorized +a|Roles assigned to all users who authenticate successfully through this module. +a|authentication.json + +a|Authentication ID +a|userName +a|Attribute in the managed object used as the user identifier, matched against the claim returned from the provider's userinfo endpoint. +a|authentication.json + +a|Method for Determining Roles +a|User Roles Property +a|How OpenIDM determines the user's roles after authentication (for example, `User Roles Property`). +a|authentication.json + +a|User Roles Property +a|authzRoles +a|Attribute in the managed object that holds the user's authorization roles. +a|authentication.json +|=== + +[#table-openid-connect-advanced] +.OPENID_CONNECT Module Advanced Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Use Query ID +a|(blank) +a|A defined query ID searches against the `queryOnResource` endpoint. Leave blank to use `action=reauthenticate` against `queryOnResource`. +a|authentication.json + +a|OpenID Connect Header +a|authToken +a|Name of the HTTP header that carries the OpenID Connect ID token (JWT) provided by the client. +a|authentication.json + +a|Augment Security Context +a|(blank) +a|Optional script executed after a successful authentication request, used to populate additional security context fields. Supports Javascript or Groovy. +a|authentication.json +|=== + +[#oauth-module-details] +=== OAUTH Module Configuration Options + +The `OAUTH` module authenticates users via a generic OAuth 2.0 provider. It validates an OAuth 2.0 `access_token` by calling the provider's `userinfo_endpoint`. For more information, see xref:chap-auth.adoc#oauth-module["OAUTH"]. + +The options shown in the Admin UI are subdivided into basic and advanced properties. You may need to click Advanced Properties to review those details. + +[#table-oauth-basic] +.OAUTH Module Basic Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Module Enabled +a|false +a|Whether to enable the module +a|authentication.json + +a|Client ID +a|blank +a|OAuth 2.0 client ID registered with the provider (`resolvers[].client_id`) +a|authentication.json + +a|Client Secret +a|blank +a|OAuth 2.0 client secret registered with the provider (`resolvers[].client_secret`) +a|authentication.json + +a|Scope +a|blank +a|OAuth 2.0 scopes needed to access provider APIs (`resolvers[].scope`) +a|authentication.json + +a|Authorization Endpoint +a|https://openam.example.com/openam/oauth2/authorize +a|Provider's authorization endpoint URL (`resolvers[].authorization_endpoint`) +a|authentication.json + +a|Token Endpoint +a|https://openam.example.com/openam/oauth2/access_token +a|Provider's token endpoint URL (`resolvers[].token_endpoint`) +a|authentication.json + +a|User Info Endpoint +a|https://openam.example.com/openam/oauth2/userinfo +a|Provider's userinfo endpoint URL (`resolvers[].userinfo_endpoint`). The access token is validated by calling this endpoint. +a|authentication.json + +a|Authentication ID attribute for the User ID +a|sub +a|Attribute name in the provider's userinfo response that contains the user identifier (`resolvers[].authenticationId`) +a|authentication.json + +a|Sign-In Button HTML +a|(HTML button markup) +a|HTML markup for the social login button displayed in the UI (`resolvers[].icon`) +a|authentication.json + +a|Query on Resource +a|managed/user +a|Managed object endpoint to query after the token is validated against the provider (`queryOnResource`) +a|authentication.json + +a|Default User Roles +a|openidm-authorized +a|Roles assigned to all users who authenticate successfully through this module (`defaultUserRoles`) +a|authentication.json + +a|Authentication ID +a|userName +a|Attribute in the managed object used as the authentication identifier when querying the resource (`propertyMapping.authenticationId`) +a|authentication.json + +a|Method for Determining Roles +a|User Roles Property +a|How roles are determined for the authenticated user (`propertyMapping`) +a|authentication.json + +a|User Roles Property +a|authzRoles +a|Attribute in the managed object used for authorization roles (`propertyMapping.userRoles`) +a|authentication.json +|=== + +[#table-oauth-advanced] +.OAUTH Module Advanced Properties +[cols="18%,27%,27%,28%"] +|=== +|Admin UI Label |Default |Description |Configuration File + +a|Use Query ID +a|blank +a|A defined `queryId` used to search against the `queryOnResource` endpoint (`queryId`) +a|authentication.json + +a|OAuth Token Header +a|authToken +a|Name of the HTTP request header that carries the OAuth 2.0 access token (`authTokenHeader`). This header is required; authentication fails if it is absent. +a|authentication.json + +a|OAuth Resolver Header +a|provider +a|Name of the HTTP request header that identifies the provider resolver to use (`authResolverHeader`). The value must match the resolver name. +a|authentication.json + +a|Augment Security Context +a|JavaScript +a|Type of script executed after a successful authentication request (`augmentSecurityContext`). Supports JavaScript or Groovy. +a|authentication.json +|=== diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-file-layout.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-file-layout.adoc index 054405d052..8b9562236e 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-file-layout.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-file-layout.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [appendix] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-jetty.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-jetty.adoc index 2529bfd07b..9398fe7354 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-jetty.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-jetty.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [appendix] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-objects.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-objects.adoc index 14c757d4ac..a181bcf400 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-objects.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-objects.adoc @@ -12,7 +12,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: @@ -244,9 +244,10 @@ Specifies the configuration of each managed object. "onDelete" : script object, "postDelete": script object, "onValidate": script object, - "onRetrieve": script object, - "onStore" : script object, - "onSync" : script object + "onRetrieve" : script object, + "onQueryResult" : script object, + "onStore" : script object, + "onSync" : script object } ---- @@ -322,6 +323,12 @@ script object, optional + A script object to trigger when an object is retrieved from the repository. The object that was retrieved is provided in the root scope as an `object` property. The script can change the object. If an exception is thrown, then object retrieval fails. +onQueryResult:: +script object, optional + ++ +A script object to trigger for each object returned from a query. The object being evaluated is provided in the root scope as an `object` property. The script should return `true` (or a truthy value) to include the object in the query results, or `false` to exclude it. If an exception is thrown, the query fails. + onStore:: script object, optional diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-ports-used.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-ports-used.adoc index 941b277acc..04315e6058 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-ports-used.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-ports-used.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [appendix] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-scripting.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-scripting.adoc index 473ee82a08..f64adea7cb 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/appendix-scripting.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/appendix-scripting.adoc @@ -12,7 +12,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: @@ -1148,7 +1148,7 @@ condition, transform ==== Scripts called in the managed object configuration (`conf/managed.json`) file:: -onCreate, onRead, onUpdate, onDelete, onValidate, onRetrieve, onStore, onSync, postCreate, postUpdate, and postDelete +onCreate, onRead, onUpdate, onDelete, onValidate, onRetrieve, onQueryResult, onStore, onSync, postCreate, postUpdate, and postDelete + `managed.json` supports only one script per hook. If multiple scripts are defined for the same hook, only the last one is kept. @@ -1191,6 +1191,9 @@ a|object, oldObject, newObject a|onDelete, onRetrieve, onRead a|object +a|onQueryResult +a|object + a|postDelete a|oldObject diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-auditing.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-auditing.adoc index deb3178154..eb869be940 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-auditing.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-auditing.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-auditing] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-auth.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-auth.adoc index 80ce42f3b6..c67d7ec701 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-auth.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-auth.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-auth] @@ -480,6 +480,163 @@ Set up logins with OpenAM, to work with the related login session cookie, known IWA:: The IWA module enables users to authenticate by using Integrated Windows Authentication (IWA), rather than by providing a username and password. For information about configuring the IWA module with OpenIDM, see xref:#openidm-auth-kerberos["Configuring IWA Authentication"]. +[[social-providers-module]]SOCIAL_PROVIDERS:: +The `SOCIAL_PROVIDERS` module is a __meta-module__ (template) that bridges the social identity provider configuration in `conf/identityProviders.json` and the OpenIDM authentication filter. It is not an authenticator itself — instead, at startup it scans all providers registered with the `IdentityProviderService`, removes itself from the active module list, and dynamically generates the corresponding `OPENID_CONNECT` or `OAUTH` authentication modules: + ++ +* For each provider of type `OPENID_CONNECT`, an `OPENID_CONNECT` auth module is generated with `openIdConnectHeader: "authToken"`. +* For each provider of type `OAUTH`, an `OAUTH` auth module is generated with `authTokenHeader: "authToken"` and `authResolverHeader: "provider"`. + ++ +The generated modules inherit the `augmentSecurityContext`, `propertyMapping`, and `defaultUserRoles` values from the `SOCIAL_PROVIDERS` template entry. + ++ +Providers are configured separately in `conf/identityProviders.json`, or via the Admin UI under *Configure > Social ID Providers*. The `SOCIAL_PROVIDERS` module acts as a single configuration point so that operators do not need to add individual `OPENID_CONNECT` or `OAUTH` entries to `authentication.json` for every social provider. + ++ +[NOTE] +====== +Any `OPENID_CONNECT` or `OAUTH` modules that are __explicitly__ defined in `authentication.json` are independent of `SOCIAL_PROVIDERS` and will coexist alongside the dynamically generated modules. They are not managed or removed by `SOCIAL_PROVIDERS`. +====== + ++ +A sample `SOCIAL_PROVIDERS` configuration is as follows: ++ +[source, json] +---- +{ + "name" : "SOCIAL_PROVIDERS", + "enabled" : true, + "properties" : { + "augmentSecurityContext": { + "type" : "text/javascript", + "file" : "auth/populateAsManagedUserFromRelationship.js" + }, + "propertyMapping" : { + "userRoles" : "authzRoles" + }, + "defaultUserRoles" : [ + "openidm-authorized" + ] + } +} +---- + ++ +For detailed property options, see xref:appendix-auth-modules.adoc#social-providers-module-details["SOCIAL_PROVIDERS Module Configuration Options"]. + +[#openid-connect-module] +OPENID_CONNECT:: +The `OPENID_CONNECT` module authenticates users via an OpenID Connect 1.0 provider. It reads an OpenID Connect ID token (JWT) from an HTTP header (configured via `openIdConnectHeader`), validates it against the configured OIDC provider endpoints, and maps the authenticated identity to an OpenIDM managed object. ++ +The module uses a single OIDC provider configuration from the first entry in the `resolvers` array (`resolvers[0]`). Although `resolvers` is defined as an array, only one resolver is supported and used per `OPENID_CONNECT` module instance; that entry configures the provider with its own `client_id`, `client_secret`, and endpoint URLs. When a `well-known` discovery URL is provided, the module auto-populates the `authorization_endpoint`, `token_endpoint`, and `userinfo_endpoint` from the provider's OIDC discovery document. ++ +The following excerpt shows a sample `OPENID_CONNECT` configuration using Google as the identity provider: ++ + +[source, json] +---- +{ + "name" : "OPENID_CONNECT", + "enabled" : true, + "properties" : { + "augmentSecurityContext": { + "type" : "text/javascript", + "file" : "auth/populateAsManagedUserFromRelationship.js" + }, + "propertyMapping" : { + "userRoles" : "authzRoles", + "authenticationId" : "_id" + }, + "defaultUserRoles" : [ + "openidm-authorized" + ], + "resolvers" : [ + { + "name" : "google", + "type" : "OPENID_CONNECT", + "icon" : "", + "scope" : ["openid", "email", "profile"], + "authenticationId" : "sub", + "enabled" : true, + "client_id" : "your-client-id.apps.googleusercontent.com", + "client_secret" : "your-client-secret", + "well-known" : "https://accounts.google.com/.well-known/openid-configuration", + "authorization_endpoint" : "https://accounts.google.com/o/oauth2/v2/auth", + "token_endpoint" : "https://oauth2.googleapis.com/token", + "userinfo_endpoint" : "https://openidconnect.googleapis.com/v1/userinfo" + } + ], + "queryOnResource" : "managed/google", + "openIdConnectHeader" : "authToken" + } +} +---- + +For detailed options, see xref:appendix-auth-modules.adoc#openid-connect-module-details["OPENID_CONNECT Module Configuration Options"]. + +[#oauth-module] +OAUTH:: +The `OAUTH` module authenticates users via a generic OAuth 2.0 provider by validating an OAuth 2.0 `access_token` against the provider's `userinfo_endpoint`. Unlike the `OPENID_CONNECT` module, it does not use JWT identity tokens. ++ +The module requires two HTTP request headers. Their names are configured by the following properties: ++ +* `authTokenHeader` — configuration property that specifies the name of the HTTP header carrying the OAuth 2.0 access token (for example, `authToken` in the sample below). +* `authResolverHeader` — configuration property that specifies the name of the HTTP header that identifies the provider resolver (from the `resolvers` list) that should validate the token (for example, `provider` in the sample below). ++ +Using two headers allows a single module instance to support multiple OAuth providers simultaneously, each defined as a separate entry in the `resolvers` array. ++ +The following sample configuration shows the `OAUTH` module with a single provider resolver: ++ +[source, json] +---- +{ + "name" : "OAUTH", + "enabled" : true, + "properties" : { + "augmentSecurityContext": { + "type" : "text/javascript", + "file" : "auth/populateAsManagedUserFromRelationship.js" + }, + "propertyMapping" : { + "userRoles" : "authzRoles", + "authenticationId" : "userName" + }, + "defaultUserRoles" : [ + "openidm-authorized" + ], + "resolvers" : [ + { + "name" : "myProvider", + "type" : "OAUTH", + "icon" : "", + "scope" : ["profile", "email"], + "authenticationId" : "sub", + "propertyMap" : [ + { + "source" : "sub", + "target" : "userName" + } + ], + "enabled" : true, + "client_id" : "your-client-id", + "client_secret" : "your-client-secret", + "authorization_endpoint" : "https://provider.example.com/oauth2/authorize", + "token_endpoint" : "https://provider.example.com/oauth2/access_token", + "userinfo_endpoint" : "https://provider.example.com/oauth2/userinfo" + } + ], + "queryOnResource" : "managed/oauth", + "authTokenHeader" : "authToken", + "authResolverHeader" : "provider" + } +} +---- ++ +Note that `authenticationId` appears at two different levels with different meanings: inside each `resolvers[]` entry it names the field in the provider's userinfo response that identifies the user (for example, `sub`); at the `propertyMapping` level it names the attribute in the managed object (for example, `userName`) that OpenIDM uses as the authentication identifier after the userinfo fields have been mapped via `propertyMap`. The resolver-level `authenticationId` userinfo field must therefore be included in `propertyMap` and mapped into the managed-object attribute referenced by `propertyMapping.authenticationId`, so that OpenIDM can correlate the resolved user to the `queryOnResource` entry. ++ +For detailed property descriptions, see xref:appendix-auth-modules.adoc#oauth-module-details["OAUTH Module Configuration Options"]. + -- diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-cli.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-cli.adoc index f952debc76..06087ba8c6 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-cli.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-cli.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-cli] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-external-rest.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-external-rest.adoc index 8237e693bf..768f2eb64d 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-external-rest.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-external-rest.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-external-rest] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-overview.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-overview.adoc index 92bf1bbe2a..5db17c5cbe 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-overview.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-overview.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-overview] == Architectural Overview diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-resource-conf.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-resource-conf.adoc index 50f5e09f21..a85171148d 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-resource-conf.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-resource-conf.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-resource-conf] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-scripting.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-scripting.adoc index ec75e02553..61a7e39fc2 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-scripting.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-scripting.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-scripting] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-security.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-security.adoc index 1b7b915962..54d85c1e87 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-security.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-security.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-security] == Securing & Hardening OpenIDM diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-services.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-services.adoc index 92e43e726d..a963574328 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-services.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-services.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-services] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-synchronization.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-synchronization.adoc index 972b2a654a..acb7681cbc 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-synchronization.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-synchronization.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-synchronization] diff --git a/openidm-doc/src/main/asciidoc/integrators-guide/chap-workflow.adoc b/openidm-doc/src/main/asciidoc/integrators-guide/chap-workflow.adoc index 33bc740a50..fd4e44f912 100644 --- a/openidm-doc/src/main/asciidoc/integrators-guide/chap-workflow.adoc +++ b/openidm-doc/src/main/asciidoc/integrators-guide/chap-workflow.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-workflow] diff --git a/openidm-doc/src/main/asciidoc/samples-guide/chap-groovy-samples.adoc b/openidm-doc/src/main/asciidoc/samples-guide/chap-groovy-samples.adoc index 5bcd4c26c8..8ea733d59e 100644 --- a/openidm-doc/src/main/asciidoc/samples-guide/chap-groovy-samples.adoc +++ b/openidm-doc/src/main/asciidoc/samples-guide/chap-groovy-samples.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-groovy-samples] diff --git a/openidm-doc/src/main/asciidoc/samples-guide/chap-salesforce-sample.adoc b/openidm-doc/src/main/asciidoc/samples-guide/chap-salesforce-sample.adoc index 458e339bd6..ffb6120ec0 100644 --- a/openidm-doc/src/main/asciidoc/samples-guide/chap-salesforce-sample.adoc +++ b/openidm-doc/src/main/asciidoc/samples-guide/chap-salesforce-sample.adoc @@ -12,14 +12,14 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024-2025 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: :example-caption!: :table-caption!: -:openidm-version: 6.2.3 -:openidm-version-short: 6.2 +:openidm-version: x.y.z +:openidm-version-short: x.y [#chap-salesforce-sample]