mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Yannick Lecaillez
13.00.2016 4c0475f46e5cda9d995e792b459825e06fe19557
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPAnonymousAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-anonymous-authorization-mechanism" plural-name="http-anonymous-authorization-mechanisms"
  extends="http-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define static authorization.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-anonymous-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HttpAnonymousAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:property name="user-dn" mandatory="false">
    <adm:synopsis>
      The authorization DN which will be used for performing anonymous operations.
    </adm:synopsis>
    <adm:syntax>
      <adm:dn />
    </adm:syntax>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          By default, operations will be performed using an anonymously bound connection.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-bind-user-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object abstract="true" name="http-authorization-mechanism" plural-name="http-authorization-mechanisms"
  package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin" xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define HTTP authorization mechanism.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-authorization-mechanism</ldap:name>
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="java-class" mandatory="true" advanced="true">
    <adm:synopsis>
      Specifies the fully-qualified name of the Java class that provides
      the
      <adm:user-friendly-name />
      implementation.
    </adm:synopsis>
    <adm:syntax>
      <adm:java-class>
        <adm:instance-of>
          org.opends.server.protocols.http.authz.HttpAuthorizationMechanism
        </adm:instance-of>
      </adm:java-class>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-java-class</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="enabled" mandatory="true">
    <adm:synopsis>
      Indicates whether the
      <adm:user-friendly-name />
      is enabled.
    </adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPBasicAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-basic-authorization-mechanism" plural-name="http-basic-authorization-mechanisms"
  extends="http-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    authenticates the end-user using credentials extracted from the HTTP Basic 'Authorization' header.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-basic-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-mapped-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
    <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HTTPBasicAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:constraint>
    <adm:synopsis>
      Alternative user's name and password header must be specified when
      alternative authentication is enabled.
    </adm:synopsis>
    <adm:condition>
      <adm:implies>
        <adm:contains property="alt-authentication-enabled" value="true" />
        <adm:implies>
          <adm:is-present property="alt-username-header" />
          <adm:is-present property="alt-password-header" />
        </adm:implies>
      </adm:implies>
    </adm:condition>
  </adm:constraint>
  <adm:property name="alt-authentication-enabled" mandatory="true">
    <adm:synopsis>
      Specifies whether user credentials may be provided using alternative headers to the standard
      'Authorize' header.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>false</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-http-basic-alt-authentication-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="alt-username-header">
    <adm:synopsis>
      Alternate HTTP headers to get the user's name from.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-http-basic-alt-username-header</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="alt-password-header">
    <adm:synopsis>
      Alternate HTTP headers to get the user's password from.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-http-basic-alt-password-header</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="identity-mapper" mandatory="true">
    <adm:synopsis>>
      Specifies the name of the identity mapper used to get the user's entry corresponding to the user-id
      provided in
      the HTTP authentication header.
    </adm:synopsis>
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper" parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced identity mapper must be enabled when the
            <adm:user-friendly-name />
            is enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-identity-mapper</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPEndpointConfiguration.xml
@@ -14,67 +14,106 @@
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-endpoint" plural-name="http-endpoints"
   package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
   xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
   <adm:synopsis>
      The
      <adm:user-friendly-name />
      is used to define HTTP endpoint.
   </adm:synopsis>
   <adm:profile name="ldap">
      <ldap:object-class>
         <ldap:name>ds-cfg-http-endpoint</ldap:name>
         <ldap:superior>top</ldap:superior>
      </ldap:object-class>
   </adm:profile>
   <adm:property name="enabled" mandatory="true">
      <adm:synopsis>
         Indicates whether the
         <adm:user-friendly-name />
         is enabled.
      </adm:synopsis>
      <adm:syntax>
         <adm:boolean />
      </adm:syntax>
      <adm:profile name="ldap">
         <ldap:attribute>
            <ldap:name>ds-cfg-enabled</ldap:name>
         </ldap:attribute>
      </adm:profile>
   </adm:property>
   <adm:property name="java-class" mandatory="true">
      <adm:synopsis>
         Specifies the fully-qualified name of the Java class that provides
         the
         <adm:user-friendly-name />
         implementation.
      </adm:synopsis>
      <adm:syntax>
         <adm:java-class>
            <adm:instance-of>
               org.opends.server.api.HttpEndpoint
            </adm:instance-of>
         </adm:java-class>
      </adm:syntax>
      <adm:profile name="ldap">
         <ldap:attribute>
            <ldap:name>ds-cfg-java-class</ldap:name>
         </ldap:attribute>
      </adm:profile>
   </adm:property>
   <adm:property name="base-path" mandatory="true" read-only="true">
      <adm:synopsis>
         All HTTP requests matching the base path or subordinate to it will be routed to the HTTP endpoint
         unless a more specific HTTP endpoint is found.
      </adm:synopsis>
      <adm:syntax>
         <adm:string />
      </adm:syntax>
      <adm:profile name="ldap">
         <ldap:attribute>
            <ldap:name>ds-cfg-base-path</ldap:name>
         </ldap:attribute>
      </adm:profile>
   </adm:property>
<adm:managed-object name="http-endpoint" plural-name="http-endpoints" package="org.forgerock.opendj.server.config"
  xmlns:adm="http://opendj.forgerock.org/admin" xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define HTTP endpoint.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-endpoint</ldap:name>
      <ldap:superior>top</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="enabled" mandatory="true">
    <adm:synopsis>
      Indicates whether the
      <adm:user-friendly-name />
      is enabled.
    </adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="authorization-mechanism" mandatory="false" multi-valued="true">
    <adm:synopsis>
      DNs of the authorization filters to apply to this
      <adm:user-friendly-name />
      .
    </adm:synopsis>
    <adm:syntax>
      <adm:aggregation relation-name="http-authorization-mechanism" parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced authorization-mechanism must be enabled when the
            <adm:user-friendly-name />
            is enabled.
          </adm:synopsis>
          <adm:target-needs-enabling-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-needs-enabling-condition>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>cn=HTTP Basic,cn=HTTP Authorization Mechanisms,cn=config</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-http-authorization-mechanism</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="java-class" mandatory="true">
    <adm:synopsis>
      Specifies the fully-qualified name of the Java class that provides
      the
      <adm:user-friendly-name />
      implementation.
    </adm:synopsis>
    <adm:syntax>
      <adm:java-class>
        <adm:instance-of>
          org.opends.server.api.HttpEndpoint
        </adm:instance-of>
      </adm:java-class>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-java-class</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="base-path" mandatory="true" read-only="true">
    <adm:synopsis>
      All HTTP requests matching the base path or subordinate to it will be routed to the HTTP endpoint
      unless a more specific HTTP endpoint is found.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-base-path</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPOauth2AuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object abstract="true" name="http-oauth2-authorization-mechanism" plural-name="http-oauth2-authorization-mechanisms"
  extends="http-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define HTTP OAuth2 authorization mechanism.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-oauth2-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="authzid-json-pointer" mandatory="true">
    <adm:synopsis>
      Specifies the JSON pointer to the value to use as Authorization ID. The JSON pointer
      is applied to the resolved access token
      JSON document.
      (example: /uid)
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-authzid-json-pointer</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="identity-mapper" mandatory="true">
    <adm:synopsis>>
      Specifies the name of the identity mapper to use in conjunction with the authzid-json-pointer
      to get the
      user corresponding to the acccess-token.
    </adm:synopsis>
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper" parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced identity mapper must be enabled when the
            <adm:user-friendly-name />
            is enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-identity-mapper</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="required-scope" mandatory="true" multi-valued="true">
    <adm:synopsis>
      Scopes required to grant access to the service.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-required-scope</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:constraint>
    <adm:synopsis>
      The access token cache expiration must be specified when the access token cache is enabled.
    </adm:synopsis>
    <adm:condition>
      <adm:implies>
        <adm:contains property="access-token-cache-enabled" value="true" />
        <adm:is-present property="access-token-cache-expiration" />
      </adm:implies>
    </adm:condition>
  </adm:constraint>
  <adm:property name="access-token-cache-enabled" mandatory="true">
    <adm:synopsis>
      Indicates whether the
      <adm:user-friendly-name />
      is enabled for use.
    </adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>false</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-access-token-cache-enabled</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="access-token-cache-expiration">
    <adm:synopsis>
      Token cache expiration
    </adm:synopsis>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:duration base-unit="s" lower-limit="0" upper-limit="2147483647" allow-unlimited="false" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-access-token-cache-expiration</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPOauth2CtsAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-oauth2-cts-authorization-mechanism" plural-name="http-oauth2-cts-authorization-mechanisms"
  extends="http-oauth2-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define OAuth2 authorization through a direct access to the CTS (Core Token Service).
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-oauth2-cts-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http_oauth2-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HttpOAuth2CtsAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:property-override name="authzid-json-pointer">
    <adm:synopsis>
      Specifies the JSON pointer to the value to use as Authorization ID. The JSON pointer
      is applied to the resolved access token JSON document. (example: userName/0)
    </adm:synopsis>
  </adm:property-override>
  <adm:property name="base-dn" mandatory="true" read-only="false">
    <adm:synopsis>
      The base DN of the Core Token Service where access token are stored.
      (example: ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com)
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-cts-base-dn</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPOauth2FileAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-oauth2-file-authorization-mechanism" plural-name="http-oauth2-file-authorization-mechanisms"
  extends="http-oauth2-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define OAuth2 authorization through a file based access-token resolution.
    For test purpose only, this mechanism is looking up for JSON access-token files under the specified path.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-oauth2-file-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-oauth2-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HttpOAuth2FileAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:property name="access-token-directory" mandatory="true" read-only="false">
    <adm:synopsis>
      Directory containing token files. File names must be equal to the token strings.
      The file content must a JSON object with the following attributes:
      'scope', 'expireTime' and all the field(s) needed to resolve the authzIdTemplate.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>oauth2-demo/</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-access-token-directory</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPOauth2OpenamAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-oauth2-openam-authorization-mechanism" plural-name="http-oauth2-openam-authorization-mechanisms"
  extends="http-oauth2-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define OAuth2 authorization using an OpenAM server as authorization server .
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-oauth2-openam-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-oauth2-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HttpOAuth2OpenAmAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
   </adm:property-override>
    <adm:property-override name="authzid-json-pointer">
    <adm:synopsis>
      Specifies the JSON pointer to the value to use as Authorization ID. The JSON pointer
      is applied to the resolved access token JSON document. (example: uid)
    </adm:synopsis>
  </adm:property-override>
  <adm:property name="token-info-url" mandatory="true" read-only="false">
    <adm:synopsis>
      Defines the OpenAM endpoint URL where the access-token resolution request should be sent.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-openam-token-info-url</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="key-manager-provider">
    <adm:synopsis>
      Specifies the name of the key manager that should be used with
      this
      <adm:user-friendly-name />
      .
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property take effect immediately, but
          only for subsequent requests to the authorization server.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          By default the system key manager(s) will be used.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="key-manager-provider" parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced key manager provider must be enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-key-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="trust-manager-provider">
    <adm:synopsis>
      Specifies the name of the trust manager that should be used
      when negotiating SSL connections with the remote authorization server.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property take effect immediately, but only
          impact subsequent SSL connection negotiations.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          By default, no trust manager is specified indicating that only
          certificates signed by the authorities associated with this JVM will
          be accepted.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="trust-manager-provider"
        parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced trust manager provider must be enabled
            when SSL is enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-trust-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/HTTPOauth2TokenIntrospectionAuthorizationMechanismConfiguration.xml
New file
@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
  The contents of this file are subject to the terms of the Common Development and
  Distribution License (the License). You may not use this file except in compliance with the
  License.
  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
  specific language governing permission and limitations under the License.
  When distributing Covered Software, include this CDDL Header Notice in each file and include
  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
  Header, with the fields enclosed by brackets [] replaced by your own identifying
  information: "Portions Copyright [year] [name of copyright owner]".
  Copyright 2016 ForgeRock AS.
  ! -->
<adm:managed-object name="http-oauth2-token-introspection-authorization-mechanism" plural-name="http-oauth2-token-introspection-authorization-mechanisms"
  extends="http-oauth2-authorization-mechanism" package="org.forgerock.opendj.server.config" xmlns:adm="http://opendj.forgerock.org/admin"
  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to define OAuth2 authorization using an introspection (RFC7662) compliant authorization server.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-http-oauth2-token-introspection-authorization-mechanism</ldap:name>
      <ldap:superior>ds-cfg-http-oauth2-authorization-mechanism</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class" advanced="true">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.protocols.http.authz.HttpOAuth2TokenIntrospectionAuthorizationMechanism
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:property-override name="authzid-json-pointer">
    <adm:synopsis>
      Specifies the JSON pointer to the value to use as Authorization ID. The JSON pointer
      is applied to the
      resolved access token JSON document. (example: sub)
    </adm:synopsis>
  </adm:property-override>
  <adm:property name="token-introspection-url" mandatory="true" read-only="false">
    <adm:synopsis>
      Defines the token introspection endpoint URL where the access-token resolution request should be sent.
      (example:
      http://example.com/introspect)
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-token-introspection-url</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="client-id" mandatory="true" read-only="false">
    <adm:synopsis>
      Client's ID to use during the HTTP basic authentication against the authorization server.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-token-introspection-client-id</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="client-secret" mandatory="true" read-only="false">
    <adm:synopsis>
      Client's secret to use during the HTTP basic authentication against the authorization server.
    </adm:synopsis>
    <adm:syntax>
      <adm:string />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-oauth2-token-introspection-client-secret</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="key-manager-provider">
    <adm:synopsis>
      Specifies the name of the key manager that should be used with
      this
      <adm:user-friendly-name />
      .
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property take effect immediately, but
          only for subsequent requests to the authorization server.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="key-manager-provider" parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced key manager provider must be enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-key-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="trust-manager-provider">
    <adm:synopsis>
      Specifies the name of the trust manager that should be used
      when negotiating SSL connections with the remote authorization server.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property take effect immediately, but only
          impact subsequent SSL connection negotiations.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:alias>
        <adm:synopsis>
          By default, no trust manager is specified indicating that only
          certificates signed by the authorities associated with this JVM will
          be accepted.
        </adm:synopsis>
      </adm:alias>
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="trust-manager-provider"
        parent-path="/">
        <adm:constraint>
          <adm:synopsis>
            The referenced trust manager provider must be enabled
            when SSL is enabled.
          </adm:synopsis>
          <adm:target-is-enabled-condition>
            <adm:contains property="enabled" value="true" />
          </adm:target-is-enabled-condition>
        </adm:constraint>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-trust-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/Rest2ldapEndpointConfiguration.xml
@@ -58,32 +58,4 @@
         </ldap:attribute>
      </adm:profile>
   </adm:property>
   <adm:property name="authentication-required" mandatory="true">
    <adm:synopsis>
      Specifies whether only authenticated requests can be processed by the
      <adm:user-friendly-name />.
    </adm:synopsis>
    <adm:description>
      If true, only authenticated requests will be processed by the
      <adm:user-friendly-name />. If false, both authenticated requests and
      unauthenticated requests will be processed. All requests are subject
      to ACI limitations and unauthenticated requests are subject to server
      limits like maximum number of entries returned. Note that setting
      ds-cfg-reject-unauthenticated-requests to true will override the current
      setting.
    </adm:description>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>true</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-authentication-required</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/RootConfiguration.xml
@@ -437,6 +437,14 @@
      </cli:relation>
    </adm:profile>
  </adm:relation>
  <adm:relation name="http-authorization-mechanism">
   <adm:one-to-many />
   <adm:profile name="ldap">
      <ldap:rdn-sequence>
        cn=HTTP Authorization Mechanisms,cn=config
      </ldap:rdn-sequence>
    </adm:profile>
  </adm:relation>
  <adm:product-name>OpenDJ</adm:product-name>
  <adm:tag-definition name="logging">
    <adm:synopsis>Logging</adm:synopsis>
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/AuthorizationFilter.java
@@ -17,8 +17,6 @@
import static org.forgerock.util.Reject.checkNotNull;
import java.util.List;
import org.forgerock.http.Filter;
import org.forgerock.http.Handler;
import org.forgerock.http.protocol.Request;
@@ -42,10 +40,9 @@
            return Response.newResponsePromise(new Response(Status.FORBIDDEN));
        }
    };
    private final Iterable<? extends ConditionalFilter> filters;
    private final List<ConditionalFilter> filters;
    AuthorizationFilter(List<ConditionalFilter> filters) {
    AuthorizationFilter(Iterable<? extends ConditionalFilter> filters) {
        this.filters = checkNotNull(filters, "filters cannot be null");
    }
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/Authorizations.java
@@ -21,7 +21,6 @@
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -64,11 +63,11 @@
     * filter in the list will be applied allowing it to formulate a valid, implementation specific, error response.
     *
     * @param filters
     *            List of authorization {@link ConditionalFilters} to try. If empty, the returned filter will always
     *            respond with 403 Forbidden.
     *            {@link Iterable} of authorization {@link ConditionalFilters} to try. If empty, the returned filter
     *            will always respond with 403 Forbidden.
     * @return A new authorization {@link Filter}
     */
    public static Filter newAuthorizationFilter(List<ConditionalFilter> filters) {
    public static Filter newAuthorizationFilter(Iterable<? extends ConditionalFilter> filters) {
        return new AuthorizationFilter(filters);
    }
opendj-server-legacy/resource/config/config.ldif
@@ -386,8 +386,103 @@
ds-cfg-enabled: true
ds-cfg-java-class: org.opends.server.protocols.http.rest2ldap.Rest2LdapEndpoint
ds-cfg-base-path: /api
ds-cfg-authentication-required: true
ds-cfg-config-url: config/http-config.json
ds-cfg-http-authorization-mechanism: cn=HTTP Basic,cn=HTTP Authorization Mechanisms,cn=config
dn: cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: HTTP Authorizations
dn: cn=HTTP Anonymous,cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-anonymous-authorization-mechanism
cn: HTTP Anonymous
ds-cfg-enabled: true
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpAnonymousAuthorizationMechanism
dn: cn=HTTP Basic,cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-basic-authorization-mechanism
cn: HTTP Basic
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpBasicAuthorizationMechanism
ds-cfg-enabled: true
ds-cfg-http-basic-alt-authentication-enabled: true
ds-cfg-http-basic-alt-username-header: X-OpenIDM-Username
ds-cfg-http-basic-alt-password-header: X-OpenIDM-Password
ds-cfg-identity-mapper: cn=Exact Match,cn=Identity Mappers,cn=config
dn: cn=HTTP OAuth2 CTS,cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-oauth2-authorization-mechanism
objectClass: ds-cfg-http-oauth2-cts-authorization-mechanism
cn: HTTP OAuth2 CTS
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpOAuth2CtsAuthorizationMechanism
ds-cfg-enabled: false
ds-cfg-cts-base-dn: ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com
ds-cfg-oauth2-authzid-json-pointer: userName/0
ds-cfg-identity-mapper: cn=Exact Match,cn=Identity Mappers,cn=config
ds-cfg-oauth2-required-scope: read
ds-cfg-oauth2-required-scope: write
ds-cfg-oauth2-required-scope: uid
ds-cfg-oauth2-access-token-cache-enabled: false
ds-cfg-oauth2-access-token-cache-expiration: 300s
dn: cn=HTTP OAuth2 OpenAM,cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-oauth2-authorization-mechanism
objectClass: ds-cfg-http-oauth2-openam-authorization-mechanism
cn: HTTP OAuth2 OpenAM
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpOAuth2OpenAmAuthorizationMechanism
ds-cfg-enabled: false
ds-cfg-openam-token-info-url: http://openam.example.com:8080/openam/oauth2/tokeninfo
ds-cfg-oauth2-authzid-json-pointer: uid
ds-cfg-identity-mapper: cn=Exact Match,cn=Identity Mappers,cn=config
ds-cfg-oauth2-required-scope: read
ds-cfg-oauth2-required-scope: write
ds-cfg-oauth2-required-scope: uid
ds-cfg-oauth2-access-token-cache-enabled: false
ds-cfg-oauth2-access-token-cache-expiration: 300s
dn: cn=HTTP OAuth2 Token Introspection (RFC7662),cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-oauth2-authorization-mechanism
objectClass: ds-cfg-http-oauth2-token-introspection-authorization-mechanism
cn: HTTP OAuth2 Token Introspection (RFC7662)
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpOAuth2TokenIntrospectionAuthorizationMechanism
ds-cfg-enabled: false
ds-cfg-oauth2-token-introspection-url: http://openam.example.com:8080/oauth2/myrealm/introspect
ds-cfg-oauth2-token-introspection-client-id: directoryserver
ds-cfg-oauth2-token-introspection-client-secret: secret
ds-cfg-oauth2-authzid-json-pointer: sub
ds-cfg-identity-mapper: cn=Exact Match,cn=Identity Mappers,cn=config
ds-cfg-oauth2-required-scope: read
ds-cfg-oauth2-required-scope: write
ds-cfg-oauth2-required-scope: uid
ds-cfg-oauth2-access-token-cache-enabled: false
ds-cfg-oauth2-access-token-cache-expiration: 300s
dn: cn=HTTP OAuth2 File,cn=HTTP Authorization Mechanisms,cn=config
objectClass: top
objectClass: ds-cfg-http-authorization-mechanism
objectClass: ds-cfg-http-oauth2-authorization-mechanism
objectClass: ds-cfg-http-oauth2-file-authorization-mechanism
cn: HTTP OAuth2 File
ds-cfg-java-class: org.opends.server.protocols.http.authz.HttpOAuth2FileAuthorizationMechanism
ds-cfg-enabled: false
ds-cfg-oauth2-access-token-directory: oauth2-demo/
ds-cfg-oauth2-authzid-json-pointer: uid
ds-cfg-identity-mapper: cn=Exact Match,cn=Identity Mappers,cn=config
ds-cfg-oauth2-required-scope: read
ds-cfg-oauth2-required-scope: write
ds-cfg-oauth2-required-scope: uid
ds-cfg-oauth2-access-token-cache-enabled: false
ds-cfg-oauth2-access-token-cache-expiration: 300s
dn: cn=LDIF Connection Handler,cn=Connection Handlers,cn=config
objectClass: top
opendj-server-legacy/resource/config/http-config.json
@@ -1,163 +1,4 @@
{
   "authorization": {
      // The authorization policies to use. Supported policies are "anonymous", "basic" and "oauth2".
      "policies": [ "basic" ],
      "anonymous": {
         // Perform all operations using anonymous user
      },
       // Use HTTP Basic authentication's information to bind to the LDAP server.
       "basic": {
         // Indicates whether the filter should allow alternative authentication
           // and, if so, which HTTP headers it should obtain the username and
           // password from.
           "supportAltAuthentication"        : true,
           "altAuthenticationUsernameHeader" : "X-OpenIDM-Username",
           "altAuthenticationPasswordHeader" : "X-OpenIDM-Password",
            // Define which LDAP bind mechanism to use
            // Supported mechanisms are "simple", "sasl-plain", "search"
         "bind": "search",
         // Bind to the LDAP server using the DN built from the HTTP Basic's username
         "simple": {
            // Connection factory used to perform the bind operation.
            // If missing, "bind" factory will be used.
             "ldapConnectionFactory": "bind",
            // The Bind DN Template containing a single %s which will be replaced by the authenticating
                // user's name. (i.e: uid=%s,ou=People,dc=example,dc=com)
                // If missing, "%s" is used.
            "bindDNTemplate": "uid=%s,ou=People,dc=example,dc=com"
         },
         // Bind to the LDAP server using a SASL Plain request
         "sasl-plain": {
            // Connection factory used to perform the bind operation.
            // If missing, "bind" factory will be used.
             "ldapConnectionFactory": "bind",
            // Authentication identity template containing a single %s which will be replaced by the authenticating
                // user's name. (i.e: u:%s)
            "authzIdTemplate": "u:%s"
         },
         // Bind to the LDAP server using the resulting DN of a search request.
         "search": {
            // Connection factory used to perform the search operation.
            // If missing, "root" factory will be used.
            "searchLDAPConnectionFactory": "root",
            // Connection factory used to perform the bind operation.
            // If missing, "bind" factory will be used.
            "bindLDAPConnectionFactory": "bind",
                // The %s filter format parameters will be substituted with the client-provided username,
                // using LDAP filter string character escaping.
                "baseDN"         : "ou=people,dc=example,dc=com",
                "scope"          : "sub", // Or "one".
                "filterTemplate" : "(&(uid=%s)(objectClass=inetOrgPerson))"
         }
           // TODO: support for HTTP sessions?
       },
        // Use OAuth2 authorization method. If used, LDAP requests will be performed with proxied authorization control.
        // This field is optional.
        "oauth2": {
            // Access tokens associated realm.
            // This attribute is optional and has a string syntax.
            "realm": "myrealm",
            // Defines the list of required scopes required to access the service.
            // This field is required and cannot be empty.
            "requiredScopes": [ "read", "write", "uid" ],
            // Specify the resolver to use to resolve OAuth2 access token.
            // This attribute is required and its value must be one of "openam", "rfc7662", "cts".
            // Note that the JSON object corresponding to this attribute value must be present
            // and well formed in the "oauth2" JSON attribute.
            "resolver": "openam",
            // The default authzIdTemplate demonstrates how an authorization DN may be constructed
            // from the "uid" field in the following example OAuth2 token introspection response:
            // {
            //     "token": "access_token_string",
            //     "uid" : "user.2",
            //     "userName" : [ "user.2" ]
            // }
            // This attribute is required and has a string syntax.
            // It must start with either 'dn:' or 'u:'.
            // Note: For the CTS resolver, the following placeholder "{userName/0}" must be part of the template string,
            //       e.g "authzIdTemplate": "dn:uid={userName/0},ou=People,dc=example,dc=com"
            "authzIdTemplate": "dn:uid={uid},ou=People,dc=example,dc=com",
            // Configures caching of access token introspection results.
            // This attribute is optional, if it is not present, no token caching will be performed.
            "accessTokenCache": {
                // Indicates whether the access token caching should be used.
                // This attribute is optional (default value is false) and must have a boolean syntax.
                "enabled": false,
                // Specifies the maximal caching duration for an access token.
                // Once this delay is over, token will be refreshed from an access token resolver (see "oauth2/resolver")
                // This attribute is optional, its default value is "5 minutes".
                // The duration syntax supports all human readable notations from day ("days", "day", "d")
                // to nanosecond ("nanoseconds", "nanosecond", "nanosec", "nanos", "nano", "ns")
                // Any negative or zero values are incorrect.
                "cacheExpiration": "5 minutes"
            },
            // The OpenAM access token resolver configuration.
            // This attribute must be present if the "oauth2/resolver" is equal to "openam".
            // If "oauth2/resolver" is set to another resolver, this attribute will be ignored.
            "openam": {
                // Defines the OpenAM endpoint URL where the request should be sent.
                // This attribute is required and must have a string syntax.
                "endpointURL": "http://openam.example.com:8080/openam/oauth2/tokeninfo"
            },
            // The RFC-7662 (see https://tools.ietf.org/html/rfc7662) access token resolver configuration.
            // This attribute must be present if the "oauth2/resolver" is equal to "rfc7662".
            // If "oauth2/resolver" is set to another resolver, this attribute will be ignored.
            "rfc7662": {
                // Defines the token introspection endpoint URL where the request should be sent.
                // This attribute is required and must have a string syntax.
                "endpointURL": "http:/example.com/introspect",
                // Token introspect endpoint requires authentication.
                // It should support HTTP basic authorization (a base64-encoded string of clientId:clientSecret)
                // These attributes are mandatory.
                "clientId": "client_id",
                "clientSecret": "client_secret"
            },
            // The CTS access token resolver.
            // This attribute must be present if the "oauth2/resolver" is equal to "cts".
            // If "oauth2/resolver" is set to another resolver, this attribute will be ignored.
            // Note: You can use {userName/0} in authzIdTemplate configuration to access
            //       user id from the default CTS access token content config.
            "cts": {
                // The access token base DN.
                // This attribute is required and must have a string syntax.
                "baseDN": "ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com"
            },
            // ONLY FOR TEST PURPOSE: A File based access token resolver
            // This attribute must be present if the "oauth2/resolver" is equal to "file".
            // If "oauth2/resolver" is set to another resolver, this attribute will be ignored.
            "file": {
                // Directory containing token files.
                // You can test the rest2ldap OAuth2 authorization support by providing some json token files under
                // the directory set in the configuration below.
                // File names must be equal to the token strings.
                // The file content must a JSON object with the following attributes:
                // 'scope', 'expireTime' and all the field(s) needed to resolve the authzIdTemplate.
                "folderPath": "/path/to/test/folder"
            }
        }
   },
    // The REST APIs and their LDAP attribute mappings.
    "mappings" : {
        "/users" : {
opendj-server-legacy/resource/schema/02-config.ldif
@@ -3854,6 +3854,94 @@
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.162
  NAME 'ds-cfg-http-authorization-mechanism'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.163
  NAME 'ds-cfg-http-basic-alt-authentication-enabled'
  EQUALITY booleanMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.164
  NAME 'ds-cfg-http-basic-alt-username-header'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.165
  NAME 'ds-cfg-http-basic-alt-password-header'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.166
  NAME 'ds-cfg-bind-user-dn'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.167
  NAME 'ds-cfg-oauth2-authzid-json-pointer'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.168
  NAME 'ds-cfg-oauth2-required-scope'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.169
  NAME 'ds-cfg-oauth2-access-token-cache-enabled'
  EQUALITY booleanMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.170
  NAME 'ds-cfg-oauth2-access-token-cache-expiration'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.171
  NAME 'ds-cfg-openam-token-info-url'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.172
  NAME 'ds-cfg-oauth2-token-introspection-url'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.173
  NAME 'ds-cfg-oauth2-token-introspection-client-id'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.174
  NAME 'ds-cfg-oauth2-token-introspection-client-secret'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.175
  NAME 'ds-cfg-cts-base-dn'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.36733.2.1.1.176
  NAME 'ds-cfg-oauth2-access-token-directory'
  EQUALITY caseIgnoreMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler'
  SUP top
@@ -5898,12 +5986,75 @@
  STRUCTURAL
  MUST ( ds-cfg-base-path $
         ds-cfg-enabled $
         ds-cfg-http-authorization-mechanism $
         ds-cfg-java-class )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.34
  NAME 'ds-cfg-rest2ldap-endpoint'
  SUP ds-cfg-http-endpoint
  STRUCTURAL
  MUST ( ds-cfg-authentication-required $
         ds-cfg-config-url )
  MUST ( ds-cfg-config-url )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.35
  NAME 'ds-cfg-http-authorization-mechanism'
  SUP top
  STRUCTURAL
  MUST ( cn $
         ds-cfg-java-class $
         ds-cfg-enabled )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.36
  NAME 'ds-cfg-http-anonymous-authorization-mechanism'
  SUP ds-cfg-http-authorization-mechanism
  STRUCTURAL
  MAY ( ds-cfg-bind-user-dn )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.37
  NAME 'ds-cfg-http-basic-authorization-mechanism'
  SUP ds-cfg-http-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-http-basic-alt-authentication-enabled $
         ds-cfg-identity-mapper )
  MAY  ( ds-cfg-http-basic-alt-username-header $
         ds-cfg-http-basic-alt-password-header )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.38
  NAME 'ds-cfg-http-oauth2-authorization-mechanism'
  SUP ds-cfg-http-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-oauth2-authzid-json-pointer $
         ds-cfg-identity-mapper $
         ds-cfg-oauth2-required-scope $
         ds-cfg-oauth2-access-token-cache-enabled )
  MAY  ( ds-cfg-oauth2-access-token-cache-expiration )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.39
  NAME 'ds-cfg-http-oauth2-openam-authorization-mechanism'
  SUP ds-cfg-http-oauth2-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-openam-token-info-url )
  MAY ( ds-cfg-trust-manager-provider $
        ds-cfg-key-manager-provider )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.40
  NAME 'ds-cfg-http-oauth2-token-introspection-authorization-mechanism'
  SUP ds-cfg-http-oauth2-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-oauth2-token-introspection-url $
         ds-cfg-oauth2-token-introspection-client-id $
         ds-cfg-oauth2-token-introspection-client-secret )
  MAY ( ds-cfg-trust-manager-provider $
        ds-cfg-key-manager-provider )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.41
  NAME 'ds-cfg-http-oauth2-cts-authorization-mechanism'
  SUP ds-cfg-http-oauth2-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-cts-base-dn )
  X-ORIGIN 'OpenDJ Directory Server' )
objectClasses: ( 1.3.6.1.4.1.36733.2.1.2.42
  NAME 'ds-cfg-http-oauth2-file-authorization-mechanism'
  SUP ds-cfg-http-oauth2-authorization-mechanism
  STRUCTURAL
  MUST ( ds-cfg-oauth2-access-token-directory )
  X-ORIGIN 'OpenDJ Directory Server' )
opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Adapters.java
@@ -141,7 +141,14 @@
        };
    }
    private static Connection newConnection(final InternalClientConnection icc) {
    /**
     * Returns a new connection.
     *
     * @param icc
     *            The internal client connection from server side.
     * @return A new SDK connection.
     */
    public static Connection newConnection(final InternalClientConnection icc) {
      return new AbstractSynchronousConnection() {
          @Override
opendj-server-legacy/src/main/java/org/opends/server/api/HttpEndpoint.java
@@ -22,6 +22,7 @@
import org.forgerock.http.HttpApplication;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.i18n.LocalizableException;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.server.config.server.HTTPEndpointCfg;
import org.opends.server.core.ServerContext;
@@ -76,6 +77,11 @@
    }
    catch (HttpApplicationException e)
    {
      if (e instanceof LocalizableException)
      {
        unacceptableReasons.add(((LocalizableException) e).getMessageObject());
        return false;
      }
      unacceptableReasons.add(ERR_CONFIG_HTTPENDPOINT_INVALID_CONFIGURATION
          .get(configuration.dn(), stackTraceToSingleLineString(e)));
      return false;
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -6416,15 +6416,14 @@
    {
      logger.traceException(ie);
      LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(ie.getMessage());
      LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(stackTraceToSingleLineString(ie));
      shutDown(theDirectoryServer.getClass().getName(), message);
    }
    catch (ConfigException ce)
    {
      logger.traceException(ce);
      LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(ce.getMessage() +
      (ce.getCause() != null ? " " + ce.getCause().getLocalizedMessage() : ""));
      LocalizableMessage message = ERR_DSCORE_CANNOT_START.get(stackTraceToSingleLineString(ce));
      shutDown(theDirectoryServer.getClass().getName(), message);
    }
    catch (Exception e)
opendj-server-legacy/src/main/java/org/opends/server/core/HttpEndpointConfigManager.java
@@ -15,16 +15,30 @@
 */
package org.opends.server.core;
import static org.forgerock.http.routing.RouteMatchers.*;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.util.StaticUtils.*;
import static org.forgerock.http.routing.RouteMatchers.requestUriMatcher;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newAuthorizationFilter;
import static org.forgerock.util.Reject.checkNotNull;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_HTTPENDPOINT_CONFLICTING_AUTHZ_DN;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_HTTPENDPOINT_INITIALIZATION_FAILED;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_HTTPENDPOINT_INVALID_AUTHZ_DN;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_HTTPENDPOINT_UNABLE_TO_START;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.forgerock.http.Handler;
import org.forgerock.http.HttpApplication;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.http.handler.Handlers;
import org.forgerock.http.protocol.Request;
import org.forgerock.http.protocol.Response;
import org.forgerock.http.protocol.Status;
import org.forgerock.http.routing.Router;
import org.forgerock.http.routing.RoutingMode;
import org.forgerock.i18n.LocalizableMessage;
@@ -36,10 +50,19 @@
import org.forgerock.opendj.config.server.ConfigurationDeleteListener;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.opendj.server.config.meta.HTTPEndpointCfgDefn;
import org.forgerock.opendj.server.config.server.HTTPAuthorizationMechanismCfg;
import org.forgerock.opendj.server.config.server.HTTPEndpointCfg;
import org.forgerock.opendj.server.config.server.RootCfg;
import org.forgerock.services.context.Context;
import org.forgerock.services.routing.RouteMatcher;
import org.forgerock.util.Pair;
import org.forgerock.util.promise.NeverThrowsException;
import org.forgerock.util.promise.Promise;
import org.opends.server.api.HttpEndpoint;
import org.opends.server.protocols.http.authz.HttpAuthorizationMechanism;
import org.opends.server.protocols.http.authz.HttpAuthorizationMechanismFactory;
import org.opends.server.types.InitializationException;
/**
@@ -54,9 +77,10 @@
{
  private static final LocalizedLogger LOGGER = LocalizedLogger.getLoggerForThisClass();
  private final AuthorizationMechanismManager auhtzFilterManager;
  private final ServerContext serverContext;
  private final Router router;
  private final Map<DN, HttpApplication> applications;
  private final Map<DN, Pair<HttpApplication, Handler>> startedApplications;
  /**
   * Creates a new instance of this HTTP endpoint config manager.
@@ -66,9 +90,10 @@
   */
  public HttpEndpointConfigManager(ServerContext serverContext)
  {
    this.serverContext = serverContext;
    this.serverContext = checkNotNull(serverContext, "serverContext cannot be null");
    this.auhtzFilterManager = new AuthorizationMechanismManager();
    this.router = serverContext.getHTTPRouter();
    this.applications = new HashMap<>();
    this.startedApplications = new HashMap<>();
  }
  /**
@@ -84,6 +109,8 @@
   */
  public void registerTo(RootCfg rootConfiguration) throws ConfigException
  {
    auhtzFilterManager.registerTo(rootConfiguration);
    rootConfiguration.addHTTPEndpointAddListener(this);
    rootConfiguration.addHTTPEndpointDeleteListener(this);
@@ -109,11 +136,13 @@
  {
    try
    {
      // Check that endpoint's authorization filters are valid.
      auhtzFilterManager.getFilters(configuration.dn(), configuration.getAuthorizationMechanismDNs());
      return loadEndpoint(configuration).isConfigurationValid(unacceptableReasons);
    }
    catch (InitializationException ie)
    catch (InitializationException | ConfigException e)
    {
      unacceptableReasons.add(ie.getMessageObject());
      unacceptableReasons.add(e.getMessageObject());
      return false;
    }
  }
@@ -128,28 +157,37 @@
      return ccr;
    }
    final RouteMatcher<Request> route = newRoute(configuration.getBasePath());
    try
    {
      final HttpApplication application = loadEndpoint(configuration).newHttpApplication();
      router.addRoute(
          requestUriMatcher(RoutingMode.STARTS_WITH, removeLeadingAndTrailingSlashes(configuration.getBasePath())),
          application.start());
      applications.put(configuration.dn(), application);
      final Handler handler = application.start();
      startedApplications.put(configuration.dn(), Pair.of(application, handler));
      bindApplication(auhtzFilterManager.getFilters(configuration.dn(), configuration.getAuthorizationMechanismDNs()),
                      handler, configuration.getBasePath());
    }
    catch (HttpApplicationException e)
    {
      ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode());
      ccr.addMessage(ERR_CONFIG_HTTPENDPOINT_UNABLE_TO_START.get(configuration.dn(), stackTraceToSingleLineString(e)));
      router.addRoute(route, ErrorHandler.INTERNAL_SERVER_ERROR);
    }
    catch (InitializationException ie)
    catch (InitializationException | ConfigException ie)
    {
      ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode());
      ccr.addMessage(ie.getMessageObject());
      router.addRoute(route, ErrorHandler.INTERNAL_SERVER_ERROR);
    }
    return ccr;
  }
  private void bindApplication(final Iterable<? extends ConditionalFilter> conditionalAuthorizationFilters,
      final Handler applicationHandler, final String basePath)
  {
    router.addRoute(newRoute(basePath),
                    Handlers.chainOf(applicationHandler, newAuthorizationFilter(conditionalAuthorizationFilters)));
  }
  @Override
  public boolean isConfigurationDeleteAcceptable(HTTPEndpointCfg configuration,
      List<LocalizableMessage> unacceptableReasons)
@@ -160,12 +198,11 @@
  @Override
  public ConfigChangeResult applyConfigurationDelete(HTTPEndpointCfg configuration)
  {
    router.removeRoute(
        requestUriMatcher(RoutingMode.STARTS_WITH, removeLeadingAndTrailingSlashes(configuration.getBasePath())));
    final HttpApplication application = applications.remove(configuration.dn());
    if (application != null)
    router.removeRoute(newRoute(configuration.getBasePath()));
    final Pair<HttpApplication, Handler> startedApplication = startedApplications.remove(configuration.dn());
    if (startedApplication != null)
    {
      application.stop();
      startedApplication.getFirst().stop();
    }
    return new ConfigChangeResult();
  }
@@ -174,22 +211,19 @@
  public boolean isConfigurationChangeAcceptable(HTTPEndpointCfg configuration,
      List<LocalizableMessage> unacceptableReasons)
  {
    try
    {
      return loadEndpoint(configuration).isConfigurationValid(unacceptableReasons);
    }
    catch (InitializationException e)
    {
      return false;
    }
    return isConfigurationAddAcceptable(configuration, unacceptableReasons);
  }
  @Override
  public ConfigChangeResult applyConfigurationChange(HTTPEndpointCfg configuration)
  {
    applyConfigurationDelete(configuration);
    applyConfigurationAdd(configuration);
    return new ConfigChangeResult();
    final Pair<HttpApplication, Handler> startedApplication = startedApplications.remove(configuration.dn());
    if (startedApplication != null)
    {
      router.addRoute(newRoute(configuration.getBasePath()), ErrorHandler.SERVICE_UNAVAILABLE);
      startedApplication.getFirst().stop();
    }
    return applyConfigurationAdd(configuration);
  }
  @SuppressWarnings("unchecked")
@@ -228,4 +262,183 @@
    return path.substring(start, end);
  }
  private static RouteMatcher<Request> newRoute(String basePath) {
    return requestUriMatcher(RoutingMode.STARTS_WITH, removeLeadingAndTrailingSlashes(basePath));
  }
  /**
   * Manages the {@link AuthorizationMechanism}. When a configuration is updated, all the {@link HttpEndpoint}s
   * referencing the updated {@link AuthorizationMechanism} will be removed and re-added to the {@link Router} once the
   * filter chain has been reconfigured.
   */
  private final class AuthorizationMechanismManager implements
      ConfigurationChangeListener<HTTPAuthorizationMechanismCfg>,
      ConfigurationAddListener<HTTPAuthorizationMechanismCfg>,
      ConfigurationDeleteListener<HTTPAuthorizationMechanismCfg>
  {
    private final HttpAuthorizationMechanismFactory authzFilterFactory =
        new HttpAuthorizationMechanismFactory(serverContext);
    private final Map<DN, HttpAuthorizationMechanism<?>> authzFilters = new HashMap<>();
    public void registerTo(RootCfg rootConfiguration) throws ConfigException
    {
      rootConfiguration.addHTTPAuthorizationMechanismAddListener(this);
      rootConfiguration.addHTTPAuthorizationMechanismDeleteListener(this);
      for (String authorizationName : rootConfiguration.listHTTPAuthorizationMechanisms())
      {
        final HTTPAuthorizationMechanismCfg configuration =
            rootConfiguration.getHTTPAuthorizationMechanism(authorizationName);
        configuration.addChangeListener(this);
        final ConfigChangeResult result = applyConfigurationAdd(configuration);
        if (!result.getResultCode().equals(ResultCode.SUCCESS))
        {
          throw new ConfigException(result.getMessages().get(0));
        }
      }
    }
    Collection<? extends ConditionalFilter> getFilters(DN endpointConfigDN, Set<DN> authzFilterDNs)
        throws ConfigException
    {
      final SortedSet<HttpAuthorizationMechanism<?>> endpointAuthzMechanisms = new TreeSet<>();
      for (DN dn : authzFilterDNs)
      {
        final HttpAuthorizationMechanism<?> authzMechanism = authzFilters.get(dn);
        if (authzMechanism == null)
        {
          throw new ConfigException(ERR_CONFIG_HTTPENDPOINT_INVALID_AUTHZ_DN.get(endpointConfigDN, dn));
        }
        if (!endpointAuthzMechanisms.add(authzMechanism))
        {
          throw new ConfigException(ERR_CONFIG_HTTPENDPOINT_CONFLICTING_AUTHZ_DN.get(
              endpointConfigDN, dn.rdn(0), endpointAuthzMechanisms.tailSet(authzMechanism).first()));
        }
      }
      return endpointAuthzMechanisms;
    }
    private void rebindStartedApplications(DN authorizationFilterDN)
    {
      final RootCfg rootConfiguration = serverContext.getRootConfig();
      for (String endpointName : rootConfiguration.listHTTPEndpoints())
      {
        try
        {
          final HTTPEndpointCfg configuration = rootConfiguration.getHTTPEndpoint(endpointName);
          if (configuration.getAuthorizationMechanismDNs().contains(authorizationFilterDN))
          {
            final Pair<HttpApplication, Handler> startedApplication = startedApplications.get(configuration.dn());
            if (startedApplication != null)
            {
              bindApplication(getFilters(configuration.dn(), configuration.getAuthorizationMechanismDNs()),
                              startedApplication.getSecond(),
                              configuration.getBasePath());
            }
          }
        }
        catch (ConfigException e)
        {
          LOGGER.error(ERR_CONFIG_HTTPENDPOINT_UNABLE_TO_START.get(endpointName, stackTraceToSingleLineString(e)), e);
          continue;
        }
      }
    }
    @Override
    public boolean isConfigurationDeleteAcceptable(HTTPAuthorizationMechanismCfg configuration,
        List<LocalizableMessage> unacceptableReasons)
    {
      return true;
    }
    @Override
    public ConfigChangeResult applyConfigurationDelete(HTTPAuthorizationMechanismCfg configuration)
    {
      authzFilters.remove(configuration.dn());
      rebindStartedApplications(configuration.dn());
      return new ConfigChangeResult();
    }
    @Override
    public boolean isConfigurationAddAcceptable(HTTPAuthorizationMechanismCfg configuration,
        List<LocalizableMessage> unacceptableReasons)
    {
      try
      {
        return authzFilterFactory.newInstance(configuration) != null;
      }
      catch (InitializationException ie)
      {
        unacceptableReasons.add(ie.getMessageObject());
        return false;
      }
    }
    @Override
    public ConfigChangeResult applyConfigurationAdd(HTTPAuthorizationMechanismCfg configuration)
    {
      final ConfigChangeResult ccr = new ConfigChangeResult();
      if (!configuration.isEnabled())
      {
        return ccr;
      }
      try
      {
        authzFilters.put(configuration.dn(), authzFilterFactory.newInstance(configuration));
        rebindStartedApplications(configuration.dn());
      }
      catch (InitializationException ie)
      {
        ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
        ccr.addMessage(ie.getMessageObject());
      }
      return ccr;
    }
    @Override
    public boolean isConfigurationChangeAcceptable(HTTPAuthorizationMechanismCfg configuration,
        List<LocalizableMessage> unacceptableReasons)
    {
      return !configuration.isEnabled() ||
             ( isConfigurationDeleteAcceptable(configuration, unacceptableReasons)
             && isConfigurationAddAcceptable(configuration, unacceptableReasons) );
    }
    @Override
    public ConfigChangeResult applyConfigurationChange(HTTPAuthorizationMechanismCfg configuration)
    {
      final ConfigChangeResult deleteResult = applyConfigurationDelete(configuration);
      if (deleteResult.getResultCode().isExceptional() || !configuration.isEnabled())
      {
        return deleteResult;
      }
      return applyConfigurationAdd(configuration);
    }
  }
  /**
   * {@link Handler} returning error status. This is used when {@link HttpApplication} failed to start or while a
   * configuration is updated.
   */
  private static final class ErrorHandler implements Handler
  {
    private final static Handler SERVICE_UNAVAILABLE = new ErrorHandler(Status.SERVICE_UNAVAILABLE);
    private final static Handler INTERNAL_SERVER_ERROR = new ErrorHandler(Status.INTERNAL_SERVER_ERROR);
    private final Status status;
    ErrorHandler(Status status)
    {
      this.status = status;
    }
    @Override
    public Promise<Response, NeverThrowsException> handle(Context context, Request request)
    {
      return Response.newResponsePromise(new Response(status));
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LocalizedHttpApplicationException.java
New file
@@ -0,0 +1,65 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.i18n.LocalizableException;
import org.forgerock.i18n.LocalizableMessage;
/**
 * Thrown to indicate that an {@link HttpApplication} was unable to start. A {@code LocalizedHttpApplicationException}
 * contains a localized error message which may be used to provide the user with detailed diagnosis information. The
 * localized message can be retrieved using the {@link #getMessageObject} method.
 */
public class LocalizedHttpApplicationException extends HttpApplicationException implements LocalizableException
{
  private static final long serialVersionUID = 2150656895248806504L;
  private final LocalizableMessage message;
  /**
   * Creates a new localized http application exception with the provided message.
   *
   * @param message
   *          The message that explains the problem that occurred.
   */
  public LocalizedHttpApplicationException(LocalizableMessage message)
  {
    super(message.toString());
    this.message = message;
  }
  /**
   * Creates a new localized http application exception with the provided message and cause.
   *
   * @param message
   *          The message that explains the problem that occurred.
   * @param cause
   *          The cause which may be later retrieved by the {@link #getCause} method. A {@code null} value is permitted,
   *          and indicates that the cause is nonexistent or unknown.
   */
  public LocalizedHttpApplicationException(LocalizableMessage message, Throwable cause)
  {
    super(message.toString(), cause);
    this.message = message;
  }
  @Override
  public final LocalizableMessage getMessageObject()
  {
    return message;
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpAnonymousAuthorizationMechanism.java
New file
@@ -0,0 +1,60 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newConditionalDirectConnectionFilter;
import static org.forgerock.opendj.adapter.server3x.Adapters.*;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.opendj.server.config.server.HTTPAnonymousAuthorizationMechanismCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.core.ServerContext;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.DirectoryException;
/**
 * Injects an {@link AuthenticatedConnectionContext} with a {@link Connection} authenticated as the given user's DN.
 *
 * @see {@link Authorizations#newConditionalDirectConnectionFilter(ConnectionFactory)}
 */
final class HttpAnonymousAuthorizationMechanism extends
    HttpAuthorizationMechanism<HTTPAnonymousAuthorizationMechanismCfg>
{
  private static final int STATIC_FILTER_PRIORITY = Integer.MAX_VALUE;
  private final ConditionalFilter delegate;
  HttpAnonymousAuthorizationMechanism(HTTPAnonymousAuthorizationMechanismCfg config, ServerContext serverContext)
      throws ConfigException
  {
    super(config.dn(), STATIC_FILTER_PRIORITY);
    try
    {
      this.delegate =
          newConditionalDirectConnectionFilter(newConnectionFactory(new InternalClientConnection(config.getUserDN())));
    }
    catch (DirectoryException e)
    {
      throw new ConfigException(e.getMessageObject(), e);
    }
  }
  @Override
  ConditionalFilter getDelegate()
  {
    return delegate;
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpAuthorizationMechanism.java
New file
@@ -0,0 +1,76 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import org.forgerock.http.Filter;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.Condition;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.opendj.server.config.server.HTTPAuthorizationMechanismCfg;
/**
 * Provides foundation for http authorization mechanisms.
 *
 * @param <T>
 *          Type of the configuration specific to the {@link HttpAuthorizationMechanism}.
 */
public abstract class HttpAuthorizationMechanism<T extends HTTPAuthorizationMechanismCfg>
  implements ConditionalFilter, Comparable<HttpAuthorizationMechanism<?>>
{
  private final DN configDN;
  private final int priority;
  /**
   * Create a new {@link HttpAuthorizationMechanism}.
   *
   * @param configDN
   *          DN where the configuration of this {@link HttpAuthorizationMechanism} resides.
   * @param priority
   *          Priority of evaluation when multiple {@link HttpAuthorizationMechanism} are present. Authorization
   *          mechanism with lower value will processed before the ones with bigger values.
   */
  public HttpAuthorizationMechanism(DN configDN, int priority)
  {
    this.configDN = configDN;
    this.priority = priority;
  }
  @Override
  public final Filter getFilter()
  {
    return getDelegate().getFilter();
  }
  @Override
  public final Condition getCondition()
  {
    return getDelegate().getCondition();
  }
  @Override
  public final int compareTo(HttpAuthorizationMechanism<?> other)
  {
    return Integer.compare(priority, other.priority);
  }
  abstract ConditionalFilter getDelegate();
  @Override
  public String toString()
  {
    return configDN.rdn(0).toString();
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpAuthorizationMechanismFactory.java
New file
@@ -0,0 +1,84 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.util.Reject.checkNotNull;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_HTTPENDPOINT_INITIALIZATION_FAILED;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import org.forgerock.i18n.LocalizableException;
import org.forgerock.opendj.server.config.meta.HTTPAuthorizationMechanismCfgDefn;
import org.forgerock.opendj.server.config.server.HTTPAuthorizationMechanismCfg;
import org.opends.server.core.ServerContext;
import org.opends.server.types.InitializationException;
/**
 * Creates {@link HttpAuthorizationMechanism} performing the authentication/authorization of incoming {@link Request}.
 */
public final class HttpAuthorizationMechanismFactory
{
  private final ServerContext serverContext;
  /**
   * Creates a new authorization mechanism factory.
   *
   * @param serverContext
   *          {@link ServerContext} of this directory server.
   * @throws NullPointerException
   *           if serverContext is null
   */
  public HttpAuthorizationMechanismFactory(ServerContext serverContext)
  {
    this.serverContext = checkNotNull(serverContext, "serverContext cannot be null");
  }
  /**
   * Creates a new {@link HttpAuthorizationMechanism} based on the configuration.
   *
   * @param config
   *          The configuration used to build this authorization mechanism.
   * @return a new {@link HttpAuthorizationMechanism}
   * @throws InitializationException
   *           If the filter cannot be created.
   */
  public HttpAuthorizationMechanism<?> newInstance(HTTPAuthorizationMechanismCfg config) throws InitializationException
  {
    try
    {
      @SuppressWarnings("unchecked")
      final Class<? extends HttpAuthorizationMechanism<?>> endpointClass =
          (Class<? extends HttpAuthorizationMechanism<?>>)
            HTTPAuthorizationMechanismCfgDefn.getInstance().getJavaClassPropertyDefinition().loadClass(
                config.getJavaClass(), HttpAuthorizationMechanism.class);
      return (HttpAuthorizationMechanism<?>) endpointClass
                          .getDeclaredConstructor(config.configurationClass(), ServerContext.class)
                          .newInstance(config, serverContext);
    }
    catch (Exception e)
    {
      if (e instanceof LocalizableException) {
        throw new InitializationException(((LocalizableException) e).getMessageObject());
      }
      if (e.getCause() != null && e.getCause() instanceof LocalizableException)
      {
        throw new InitializationException(((LocalizableException) e.getCause()).getMessageObject());
      }
      throw new InitializationException(ERR_CONFIG_HTTPENDPOINT_INITIALIZATION_FAILED.get(
          config.getJavaClass(), config.dn(), stackTraceToSingleLineString(e)), e);
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpBasicAuthorizationMechanism.java
New file
@@ -0,0 +1,181 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.http.filter.Filters.chainOf;
import static org.forgerock.opendj.adapter.server3x.Adapters.newConnection;
import static org.forgerock.opendj.adapter.server3x.Adapters.newRootConnectionFactory;
import static org.forgerock.opendj.ldap.LdapException.newLdapException;
import static org.forgerock.opendj.ldap.ResultCode.INVALID_CREDENTIALS;
import static org.forgerock.opendj.ldap.ResultCode.OPERATIONS_ERROR;
import static org.forgerock.opendj.ldap.requests.Requests.newSimpleBindRequest;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newConditionalHttpBasicAuthenticationFilter;
import static org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.newConditionalFilter;
import static org.forgerock.opendj.rest2ldap.authz.CredentialExtractors.httpBasicExtractor;
import static org.forgerock.opendj.rest2ldap.authz.CredentialExtractors.newCustomHeaderExtractor;
import static org.forgerock.services.context.SecurityContext.AUTHZID_DN;
import static org.forgerock.util.Reject.checkNotNull;
import static org.forgerock.util.Utils.closeSilently;
import static org.forgerock.util.promise.Promises.newExceptionPromise;
import static org.forgerock.util.promise.Promises.newResultPromise;
import static org.opends.server.core.DirectoryServer.getIdentityMapper;
import static org.opends.server.core.DirectoryServer.isRootDN;
import java.util.HashMap;
import java.util.Map;
import org.forgerock.http.Filter;
import org.forgerock.http.Handler;
import org.forgerock.http.protocol.Request;
import org.forgerock.http.protocol.Response;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.ConnectionFactory;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.responses.BindResult;
import org.forgerock.opendj.rest2ldap.AuthenticatedConnectionContext;
import org.forgerock.opendj.rest2ldap.authz.AuthenticationStrategy;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.opendj.server.config.server.HTTPBasicAuthorizationMechanismCfg;
import org.forgerock.services.context.Context;
import org.forgerock.services.context.SecurityContext;
import org.forgerock.util.promise.NeverThrowsException;
import org.forgerock.util.promise.Promise;
import org.opends.server.api.IdentityMapper;
import org.opends.server.core.ServerContext;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
/**
 * Implements the HTTP Basic authorization by first resolving the user's identity with an {@link IdentityMapper} and
 * then by performing a simple {@link BindRequest}. On success, an {@link AuthenticatedConnectionContext} is created.
 */
final class HttpBasicAuthorizationMechanism extends HttpAuthorizationMechanism<HTTPBasicAuthorizationMechanismCfg>
{
  private static final CloseConnectionFilter CLOSE_CONNECTION = new CloseConnectionFilter();
  private static final int HTTP_BASIC_PRIORITY = 500;
  private final ConditionalFilter delegate;
  HttpBasicAuthorizationMechanism(HTTPBasicAuthorizationMechanismCfg config, ServerContext serverContext)
  {
    super(config.dn(), HTTP_BASIC_PRIORITY);
    final ConditionalFilter httpBasicFilter = newConditionalHttpBasicAuthenticationFilter(
        new IdentityMapperAuthenticationStrategy(newRootConnectionFactory(),
                                                 getIdentityMapper(config.getIdentityMapperDN())),
        config.isAltAuthenticationEnabled()
                  ? newCustomHeaderExtractor(config.getAltUsernameHeader(), config.getAltPasswordHeader())
                  : httpBasicExtractor());
    this.delegate =
        newConditionalFilter(chainOf(httpBasicFilter.getFilter(), CLOSE_CONNECTION), httpBasicFilter.getCondition());
  }
  @Override
  ConditionalFilter getDelegate()
  {
    return delegate;
  }
  /** Close the {@link Connection} present in the {@link AuthenticatedConnectionContext}. */
  private static final class CloseConnectionFilter implements Filter
  {
    @Override
    public Promise<Response, NeverThrowsException> filter(final Context context, Request request, Handler next)
    {
      return next.handle(context, request).thenAlways(new Runnable()
      {
        @Override
        public void run()
        {
          closeSilently(context.asContext(AuthenticatedConnectionContext.class).getConnection());
        }
      });
    }
  }
  /**
   * Performs a simple {@link BindRequest} using the user's DN resolved by an {@link IdentityMapper}. For optimization
   * purpose, returns an {@link AuthenticatedConnectionContext} encapsulated in the {@link SecurityContext} By doing so
   * we're removing the redundant lookup which should otherwise have happen in the {@link InternalProxyAuthzFilter}.
   */
  private static final class IdentityMapperAuthenticationStrategy implements AuthenticationStrategy
  {
    private final ConnectionFactory rootConnectionFactory;
    private final IdentityMapper<?> identityMapper;
    IdentityMapperAuthenticationStrategy(ConnectionFactory rootConnectionFactory, IdentityMapper<?> identityMapper)
    {
      this.rootConnectionFactory = checkNotNull(rootConnectionFactory, "rootConnectionFactory cannot be null");
      this.identityMapper = checkNotNull(identityMapper, "identityMapper cannot be null");
    }
    @Override
    public Promise<SecurityContext, LdapException> authenticate(String username, String password, Context parentContext)
    {
      try
      {
        final Entry userEntry = getMappedIdentity(username);
        doBind(userEntry.getName().toString(), password);
        final Context authcContext = new AuthenticatedConnectionContext(parentContext, newConnectionAs(userEntry));
        final Map<String, Object> authz = new HashMap<>();
        authz.put(AUTHZID_DN, userEntry.getName().toString());
        return newResultPromise(new SecurityContext(authcContext, username, authz));
      }
      catch (LdapException e)
      {
        return newExceptionPromise(e);
      }
    }
    private Entry getMappedIdentity(String authzId) throws LdapException
    {
      final Entry userEntry;
      try
      {
        userEntry = identityMapper.getEntryForID(authzId);
        if (userEntry != null)
        {
          return userEntry;
        }
      }
      catch (DirectoryException e)
      {
        throw newLdapException(OPERATIONS_ERROR, e);
      }
      throw newLdapException(INVALID_CREDENTIALS);
    }
    private void doBind(String name, String password) throws LdapException
    {
      try (final Connection connection = rootConnectionFactory.getConnection())
      {
        final BindResult result = connection.bind(newSimpleBindRequest(name, password.toCharArray()));
        if (!result.isSuccess())
        {
          throw newLdapException(INVALID_CREDENTIALS);
        }
      }
    }
    private Connection newConnectionAs(Entry userEntry)
    {
      return newConnection(new InternalClientConnection(
          new AuthenticationInfo(userEntry, isRootDN(userEntry.getName()))));
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpOAuth2AuthorizationMechanism.java
New file
@@ -0,0 +1,132 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.http.filter.Filters.chainOf;
import static org.forgerock.http.handler.HttpClientHandler.OPTION_KEY_MANAGERS;
import static org.forgerock.http.handler.HttpClientHandler.OPTION_SSL_CIPHER_SUITES;
import static org.forgerock.http.handler.HttpClientHandler.OPTION_SSL_ENABLED_PROTOCOLS;
import static org.forgerock.http.handler.HttpClientHandler.OPTION_TRUST_MANAGERS;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newConditionalOAuth2ResourceServerFilter;
import static org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.newConditionalFilter;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_INVALID_JSON_POINTER;
import static org.opends.server.core.DirectoryServer.getCryptoManager;
import static org.opends.server.core.DirectoryServer.getIdentityMapper;
import static org.opends.server.core.DirectoryServer.getKeyManagerProvider;
import static org.opends.server.core.DirectoryServer.getTrustManagerProvider;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.forgerock.authz.modules.oauth2.AccessTokenException;
import org.forgerock.authz.modules.oauth2.AccessTokenInfo;
import org.forgerock.authz.modules.oauth2.AccessTokenResolver;
import org.forgerock.authz.modules.oauth2.cache.CachingAccessTokenResolver;
import org.forgerock.json.JsonException;
import org.forgerock.json.JsonPointer;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.opendj.server.config.server.HTTPOauth2AuthorizationMechanismCfg;
import org.forgerock.util.Options;
import org.forgerock.util.PerItemEvictionStrategyCache;
import org.forgerock.util.promise.Promise;
import org.forgerock.util.time.Duration;
import org.forgerock.util.time.TimeService;
import org.opends.server.core.ServerContext;
import org.opends.server.types.DirectoryException;
/**
 * Abstract Authorization Mechanism injecting an {@link AuthenticatedConnectionContext} from an OAuth2 access token
 * resolved with an {@link AccessTokenResolver}.
 *
 * @param <T>
 *          Type of the configuration required by the OAuth2 authorization mechanism.
 */
abstract class HttpOAuth2AuthorizationMechanism<T extends HTTPOauth2AuthorizationMechanismCfg> extends
    HttpAuthorizationMechanism<T>
{
  private static final int HTTP_OAUTH2_PRIORITY = 100;
  private static final ScheduledExecutorService CACHE_EVICTOR = Executors.newSingleThreadScheduledExecutor();
  protected final T config;
  protected final ServerContext serverContext;
  private final ConditionalFilter delegate;
  HttpOAuth2AuthorizationMechanism(T config, ServerContext serverContext) throws ConfigException
  {
    super(config.dn(), HTTP_OAUTH2_PRIORITY);
    this.config = config;
    this.serverContext = serverContext;
    try
    {
      new JsonPointer(config.getAuthzidJsonPointer());
    }
    catch (JsonException e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_INVALID_JSON_POINTER.get(
          config.dn(), config.getAuthzidJsonPointer(), e.getMessage()), e);
    }
    AccessTokenResolver resolver = newAccessTokenResolver();
    if (config.isAccessTokenCacheEnabled())
    {
      final Duration expiration = Duration.duration(config.getAccessTokenCacheExpiration(), TimeUnit.SECONDS);
      final PerItemEvictionStrategyCache<String, Promise<AccessTokenInfo, AccessTokenException>> cache =
          new PerItemEvictionStrategyCache<String, Promise<AccessTokenInfo, AccessTokenException>>(CACHE_EVICTOR,
              expiration);
      cache.setMaxTimeout(expiration);
      resolver = new CachingAccessTokenResolver(TimeService.SYSTEM, resolver, cache);
    }
    final ConditionalFilter oauth2Filter = newConditionalOAuth2ResourceServerFilter(
        "no_realm", config.getRequiredScope(), resolver, "u:{" + config.getAuthzidJsonPointer()+"}");
    this.delegate = newConditionalFilter(
        chainOf(oauth2Filter.getFilter(), new InternalProxyAuthzFilter(getIdentityMapper(config.getIdentityMapperDN()),
                                                                                         serverContext.getSchemaNG())),
        oauth2Filter.getCondition());
  }
  abstract AccessTokenResolver newAccessTokenResolver() throws ConfigException;
  @Override
  final ConditionalFilter getDelegate()
  {
    return delegate;
  }
  static Options toHttpOptions(DN trustManagerDN, DN keyManagerDN) throws ConfigException
  {
    final Options options = Options.defaultOptions();
    try
    {
      options.set(OPTION_TRUST_MANAGERS, trustManagerDN != null
          ? getTrustManagerProvider(trustManagerDN).getTrustManagers() : null);
      options.set(OPTION_KEY_MANAGERS, keyManagerDN != null
          ? getKeyManagerProvider(keyManagerDN).getKeyManagers() : null);
      options.set(OPTION_SSL_CIPHER_SUITES, new ArrayList<>(getCryptoManager().getSslCipherSuites()));
      options.set(OPTION_SSL_ENABLED_PROTOCOLS, new ArrayList<>(getCryptoManager().getSslProtocols()));
    }
    catch (DirectoryException e)
    {
      throw new ConfigException(e.getMessageObject(), e);
    }
    return options;
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpOAuth2CtsAuthorizationMechanism.java
New file
@@ -0,0 +1,59 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.opendj.adapter.server3x.Adapters.newRootConnectionFactory;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newCtsAccessTokenResolver;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_AUTHZ_REFERENCED_DN_DOESNT_EXISTS;
import org.forgerock.authz.modules.oauth2.AccessTokenResolver;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.server.config.server.HTTPOauth2CtsAuthorizationMechanismCfg;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ServerContext;
import org.opends.server.types.DirectoryException;
/**
 * Injects an {@link AuthenticatedConnectionContext} from an OAuth2 access token which will be resolved from core token
 * service.
 */
final class HttpOAuth2CtsAuthorizationMechanism extends
    HttpOAuth2AuthorizationMechanism<HTTPOauth2CtsAuthorizationMechanismCfg>
{
  HttpOAuth2CtsAuthorizationMechanism(HTTPOauth2CtsAuthorizationMechanismCfg config, ServerContext serverContext)
      throws ConfigException
  {
    super(config, serverContext);
  }
  @Override
  AccessTokenResolver newAccessTokenResolver() throws ConfigException
  {
    try
    {
      if (DirectoryServer.getEntry(DN.valueOf(config.getBaseDN())) == null)
      {
        throw new ConfigException(ERR_CONFIG_AUTHZ_REFERENCED_DN_DOESNT_EXISTS.get(config.dn(), config.getBaseDN()));
      }
    }
    catch (DirectoryException e)
    {
      throw new ConfigException(e.getMessageObject());
    }
    return newCtsAccessTokenResolver(newRootConnectionFactory(), config.getBaseDN());
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpOAuth2FileAuthorizationMechanism.java
New file
@@ -0,0 +1,54 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newFileAccessTokenResolver;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_NON_EXISTING_DIRECTORY;
import static org.opends.server.util.StaticUtils.getFileForPath;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.forgerock.authz.modules.oauth2.AccessTokenResolver;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.server.config.server.HTTPOauth2FileAuthorizationMechanismCfg;
import org.opends.server.core.ServerContext;
/** Injects an {@link AuthenticatedConnectionContext} from an OAuth2 access token which will be resolved from a file. */
final class HttpOAuth2FileAuthorizationMechanism extends
    HttpOAuth2AuthorizationMechanism<HTTPOauth2FileAuthorizationMechanismCfg>
{
  HttpOAuth2FileAuthorizationMechanism(HTTPOauth2FileAuthorizationMechanismCfg config, ServerContext serverContext)
      throws ConfigException
  {
    super(config, serverContext);
  }
  @Override
  AccessTokenResolver newAccessTokenResolver() throws ConfigException
  {
    final String absoluteTokenDir = getFileForPath(config.getAccessTokenDirectory()).getAbsolutePath();
    try
    {
      Files.newDirectoryStream(Paths.get(absoluteTokenDir));
    }
    catch (Exception e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_NON_EXISTING_DIRECTORY.get(config.dn(), absoluteTokenDir), e);
    }
    return newFileAccessTokenResolver(absoluteTokenDir);
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpOAuth2OpenAmAuthorizationMechanism.java
New file
@@ -0,0 +1,71 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_CONFIG_ERROR;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_INVALID_URL;
import java.net.URI;
import java.net.URISyntaxException;
import org.forgerock.authz.modules.oauth2.AccessTokenResolver;
import org.forgerock.authz.modules.oauth2.resolver.OpenAmAccessTokenResolver;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.http.handler.HttpClientHandler;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.server.config.server.HTTPOauth2OpenamAuthorizationMechanismCfg;
import org.forgerock.util.time.TimeService;
import org.opends.server.core.ServerContext;
/**
 * Injects an {@link AuthenticatedConnectionContext} from an OAuth2 access token which will be resolved by an external
 * OpenAM instance.
 */
final class HttpOAuth2OpenAmAuthorizationMechanism extends
    HttpOAuth2AuthorizationMechanism<HTTPOauth2OpenamAuthorizationMechanismCfg>
{
  HttpOAuth2OpenAmAuthorizationMechanism(HTTPOauth2OpenamAuthorizationMechanismCfg config, ServerContext serverContext)
      throws ConfigException
  {
    super(config, serverContext);
  }
  @Override
  AccessTokenResolver newAccessTokenResolver() throws ConfigException
  {
    try
    {
      new URI(config.getTokenInfoUrl());
    }
    catch (URISyntaxException e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_INVALID_URL.get(
          config.dn(), config.getTokenInfoUrl(), e.getMessage()), e);
    }
    try
    {
      return
          new OpenAmAccessTokenResolver(
              new HttpClientHandler(toHttpOptions(config.getTrustManagerProviderDN(),
                                                  config.getKeyManagerProviderDN())),
              TimeService.SYSTEM, config.getTokenInfoUrl());
    }
    catch (HttpApplicationException e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_CONFIG_ERROR.get(config.dn(), e.getMessage()), e);
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/HttpOAuth2TokenIntrospectionAuthorizationMechanism.java
New file
@@ -0,0 +1,65 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.authz;
import static org.forgerock.opendj.rest2ldap.authz.Authorizations.newRfc7662AccessTokenResolver;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_CONFIG_ERROR;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_OAUTH2_INVALID_URL;
import java.net.URI;
import java.net.URISyntaxException;
import org.forgerock.authz.modules.oauth2.AccessTokenResolver;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.http.handler.HttpClientHandler;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.server.config.server.HTTPOauth2TokenIntrospectionAuthorizationMechanismCfg;
import org.opends.server.core.ServerContext;
/**
 * Injects an {@link AuthenticatedConnectionContext} from an OAuth2 access token which will be resolved by an external
 * RFC7662 introspection endpoint.
 */
final class HttpOAuth2TokenIntrospectionAuthorizationMechanism extends
    HttpOAuth2AuthorizationMechanism<HTTPOauth2TokenIntrospectionAuthorizationMechanismCfg>
{
  HttpOAuth2TokenIntrospectionAuthorizationMechanism(HTTPOauth2TokenIntrospectionAuthorizationMechanismCfg config,
      ServerContext serverContext) throws ConfigException
  {
    super(config, serverContext);
  }
  @Override
  AccessTokenResolver newAccessTokenResolver() throws ConfigException
  {
    try
    {
      return newRfc7662AccessTokenResolver(
          new HttpClientHandler(toHttpOptions(config.getTrustManagerProviderDN(), config.getKeyManagerProviderDN())),
          new URI(config.getTokenIntrospectionUrl()),
          config.getClientSecret(), config.getClientSecret());
    }
    catch (HttpApplicationException e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_CONFIG_ERROR.get(config.dn(), e.getMessage()), e);
    }
    catch (URISyntaxException e)
    {
      throw new ConfigException(ERR_CONFIG_OAUTH2_INVALID_URL.get(
          config.dn(), config.getTokenIntrospectionUrl(), e.getMessage()), e);
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/InternalProxyAuthzFilter.java
File was renamed from opendj-server-legacy/src/main/java/org/opends/server/protocols/http/rest2ldap/InternalProxyAuthzFilter.java
@@ -13,7 +13,7 @@
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.server.protocols.http.rest2ldap;
package org.opends.server.protocols.http.authz;
import static org.forgerock.opendj.rest2ldap.Rest2LDAP.asResourceException;
import static org.forgerock.services.context.SecurityContext.AUTHZID_DN;
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/authz/package-info.java
New file
@@ -0,0 +1,24 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
/**
 * Contains factories to build the authorization stage of the HTTP request processing. Each HTTP request can go through
 * one or several {@link org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter} resulting in the
 * injection of an {@link org.forgerock.opendj.rest2ldap.AuthenticatedConnectionContext} which can be used by the
 * {@link org.opends.server.api.HttpEndpoint} to perform LDAP requests against this directory server.
 */
package org.opends.server.protocols.http.authz;
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/rest2ldap/Rest2LdapEndpoint.java
@@ -15,28 +15,32 @@
 */
package org.opends.server.protocols.http.rest2ldap;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_REST2LDAP_MALFORMED_URL;
import static org.forgerock.http.util.Json.readJsonLenient;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.util.StaticUtils.getFileForPath;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.forgerock.http.Filter;
import org.forgerock.http.Handler;
import org.forgerock.http.HttpApplication;
import org.forgerock.opendj.adapter.server3x.Adapters;
import org.forgerock.opendj.ldap.ConnectionFactory;
import org.forgerock.opendj.ldap.schema.Schema;
import org.forgerock.opendj.rest2ldap.Rest2LDAPHttpApplication;
import org.forgerock.opendj.rest2ldap.authz.ConditionalFilters.ConditionalFilter;
import org.forgerock.http.HttpApplicationException;
import org.forgerock.http.io.Buffer;
import org.forgerock.json.JsonValue;
import org.forgerock.json.JsonValueException;
import org.forgerock.json.resource.Router;
import org.forgerock.json.resource.http.CrestHttp;
import org.forgerock.opendj.rest2ldap.Rest2LDAP;
import org.forgerock.opendj.server.config.server.Rest2ldapEndpointCfg;
import org.forgerock.util.Factory;
import org.opends.server.api.HttpEndpoint;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ServerContext;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.protocols.http.LocalizedHttpApplicationException;
import org.opends.server.types.InitializationException;
/**
@@ -62,51 +66,88 @@
  @Override
  public HttpApplication newHttpApplication() throws InitializationException
  {
    try
    {
      final URI configURI = new URI(configuration.getConfigUrl());
      final URL absoluteConfigUrl =
          configURI.isAbsolute() ? configURI.toURL() : getFileForPath(configuration.getConfigUrl()).toURI().toURL();
      return new InternalRest2LDAPHttpApplication(absoluteConfigUrl, serverContext.getSchemaNG());
    }
    catch (MalformedURLException | URISyntaxException e)
    {
      throw new InitializationException(ERR_CONFIG_REST2LDAP_MALFORMED_URL
          .get(configuration.dn(), stackTraceToSingleLineString(e)));
    }
    return new InternalRest2LDAPHttpApplication();
  }
  /**
   * Specialized {@link Rest2LDAPHttpApplication} using internal connections to
   * this local LDAP server.
   */
  private final class InternalRest2LDAPHttpApplication extends Rest2LDAPHttpApplication
  private final class InternalRest2LDAPHttpApplication implements HttpApplication
  {
    private final ConnectionFactory rootInternalConnectionFactory = Adapters.newRootConnectionFactory();
    private final ConnectionFactory anonymousInternalConnectionFactory =
        Adapters.newConnectionFactory(new InternalClientConnection((AuthenticationInfo) null));
    private final URL configURL;
    InternalRest2LDAPHttpApplication(final URL configURL, final Schema schema)
    InternalRest2LDAPHttpApplication() throws InitializationException
    {
      super(configURL, schema);
      try
      {
        final URI configURI = new URI(configuration.getConfigUrl());
        configURL = configURI.isAbsolute()
            ? configURI.toURL()
            : getFileForPath(configuration.getConfigUrl()).toURI().toURL();
      }
      catch (MalformedURLException | URISyntaxException e)
      {
        throw new InitializationException(
            ERR_CONFIG_REST2LDAP_MALFORMED_URL.get(configuration.dn(), stackTraceToSingleLineString(e)));
      }
    }
    @Override
    protected ConditionalFilter newAnonymousFilter(final ConnectionFactory connectionFactory)
    public Handler start() throws HttpApplicationException
    {
      return super.newAnonymousFilter(anonymousInternalConnectionFactory);
      JsonValue mappingConfiguration;
      try
      {
        mappingConfiguration = readJson(configURL);
      }
      catch (IOException e)
      {
        throw new LocalizedHttpApplicationException(
            ERR_CONFIG_REST2LDAP_UNABLE_READ.get(configURL, configuration.dn(), stackTraceToSingleLineString(e)), e);
      }
      final JsonValue mappings = mappingConfiguration.get("mappings").required();
      final Router router = new Router();
      try
      {
        for (final String mappingUrl : mappings.keys())
        {
          final JsonValue mapping = mappings.get(mappingUrl);
          router.addRoute(Router.uriTemplate(mappingUrl), Rest2LDAP.builder().configureMapping(mapping).build());
        }
      }
      catch (JsonValueException e)
      {
        throw new LocalizedHttpApplicationException(
            ERR_CONFIG_REST2LDAP_UNEXPECTED_JSON.get(e.getJsonValue().getPointer(), configURL, configuration.dn(),
                                                     stackTraceToSingleLineString(e)), e);
      }
      catch (IllegalArgumentException e)
      {
        throw new LocalizedHttpApplicationException(
            ERR_CONFIG_REST2LDAP_INVALID.get(configURL, configuration.dn(), stackTraceToSingleLineString(e)), e);
      }
      return CrestHttp.newHttpHandler(router);
    }
    private JsonValue readJson(final URL resource) throws IOException
    {
      try (InputStream in = resource.openStream())
      {
        return new JsonValue(readJsonLenient(in));
      }
    }
    @Override
    protected Filter newProxyAuthzFilter(final ConnectionFactory connectionFactory)
    public void stop()
    {
      return new InternalProxyAuthzFilter(DirectoryServer.getProxiedAuthorizationIdentityMapper(), schema);
      // Nothing to do
    }
    @Override
    protected ConnectionFactory getConnectionFactory(final String name)
    public Factory<Buffer> getBufferFactory()
    {
      return rootInternalConnectionFactory;
      return null;
    }
  }
}
opendj-server-legacy/src/messages/org/opends/messages/config.properties
@@ -825,4 +825,24 @@
ERR_UNABLE_TO_LOAD_CONFIGURATION_ENABLED_SCHEMA_745=Unable to load the \
 configuration-enabled schema: %s
ERR_CONFIG_BACKEND_CANNOT_DELETE_ENTRY_746=Backend config error when trying to \
 delete an entry: %s
 delete an entry: %s
ERR_CONFIG_HTTPENDPOINT_INVALID_AUTHZ_DN_747=The HTTP endpoint configuration \
 defined in %s is referencing a non existing authorization DN %s
ERR_CONFIG_HTTPENDPOINT_CONFLICTING_AUTHZ_DN_748=The HTTP endpoint configuration \
 defined in %s is referencing mutually exclusive authorization DNs %s and %s
ERR_CONFIG_REST2LDAP_UNABLE_READ_749=Unable to read the configuration from %s in the \
 REST2LDAP endpoint configuration entry %s: %s
ERR_CONFIG_REST2LDAP_UNEXPECTED_JSON_750=Invalid JSON element %s from %s in the REST2LDAP \
 endpoint configuration entry %s: %s
ERR_CONFIG_REST2LDAP_INVALID_751=Invalid configuration element from %s in the REST2LDAP \
 endpoint configuration entry %s: %s
ERR_CONFIG_OAUTH2_INVALID_JSON_POINTER_752=The OAuth2 authorization mechanism defined \
 in %s contains an invalid JSON Pointer %s: %s
ERR_CONFIG_OAUTH2_NON_EXISTING_DIRECTORY_753=The authorization mechanism defined in %s \
 is referencing a non-existing or non-readable directory: %s
ERR_CONFIG_AUTHZ_REFERENCED_DN_DOESNT_EXISTS_754=The authorization mechanism defined \
 in %s is referencing a non existing DN: %s
ERR_CONFIG_OAUTH2_INVALID_URL_755=The authorization mechanism defined in %s is referencing \
 an invalid URL %s: %s
ERR_CONFIG_OAUTH2_CONFIG_ERROR_756=Unable to configure the authorization mechanism defined \
 in %s: %s