From 135dcefa19b992dad85ff2f440894111344bc841 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Wed, 08 Jun 2016 14:37:08 +0000
Subject: [PATCH] OPENDJ-3067 Make authzIdTemplate config parameter specific to each resolver config

---
 opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/opendj-rest2ldap-config.json              |   68 +++++++++++++++++++++++++--------
 opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java |   33 +++++++++++-----
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java        |    3 +
 3 files changed, 75 insertions(+), 29 deletions(-)

diff --git a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/opendj-rest2ldap-config.json b/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/opendj-rest2ldap-config.json
index e0d9e0d..460d55b 100644
--- a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/opendj-rest2ldap-config.json
+++ b/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/opendj-rest2ldap-config.json
@@ -156,19 +156,6 @@
 			// 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": {
@@ -191,7 +178,19 @@
             "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"
+                "endpointURL": "http://openam.example.com:8080/openam/oauth2/tokeninfo",
+
+				// The default authzIdTemplate demonstrates how an authorization DN may be constructed
+				// from the "uid" field in the following example OpenAM tokeninfo response:
+				// {
+				//     "scope":["uid"],
+				//     "realm":"/",
+				//     "expires_in":45,
+				//     "uid" : "bjensen",
+			    // }
+				// This attribute is required and has a string syntax.
+				// It must start with either 'dn:' or 'u:'.
+				"authzIdTemplate": "dn:uid={uid},ou=People,dc=example,dc=com"
             },
 
             // The RFC-7662 (see https://tools.ietf.org/html/rfc7662) access token resolver configuration.
@@ -206,7 +205,19 @@
 				// It should support HTTP basic authorization (a base64-encoded string of clientId:clientSecret)
 				// These attributes are mandatory.
 				"clientId": "client_id",
-				"clientSecret": "client_secret"
+				"clientSecret": "client_secret",
+
+				// The default authzIdTemplate demonstrates how an authorization DN may be constructed
+				// from the "username" field in the following example introspect response:
+				// {
+				//     "active": true,
+				//     "token_type": "access_token",
+				//     "exp": 3524,
+				//     "username" : "bjensen",
+				// }
+				// This attribute is required and has a string syntax.
+				// It must start with either 'dn:' or 'u:'.
+				"authzIdTemplate": "dn:uid={username},ou=People,dc=example,dc=com"
             },
 
             // The CTS access token resolver.
@@ -223,7 +234,19 @@
 
                 // 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"
+                "baseDN": "ou=famrecords,ou=openam-session,ou=tokens,dc=example,dc=com",
+
+				// The default authzIdTemplate demonstrates how an authorization DN may be constructed
+				// from the "userName" field in the following example CTS access token entry:
+				// {
+				//     "active": true,
+				//     "tokenName": ["access_token"],
+				//     "exp": [3524],
+				//     "userName" : ["bjensen"],
+				// }
+				// This attribute is required and has a string syntax.
+				// It must start with either 'dn:' or 'u:'.
+				"authzIdTemplate": "dn:uid={userName/0},ou=People,dc=example,dc=com"
             },
 
             // ONLY FOR TEST PURPOSE: A File based access token resolver
@@ -236,7 +259,18 @@
                 // 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"
+                "folderPath": "/path/to/test/folder",
+
+				// The default authzIdTemplate demonstrates how an authorization DN may be constructed
+				// from the "uid" field extracted from a fake token file:
+				// {
+				//      "scope": ["read", "uid", "write"],
+				//      "expireTime": 1961336698000,
+				//      "uid": "bjensen"
+			    // }
+				// This attribute is required and has a string syntax.
+				// It must start with either 'dn:' or 'u:'.
+				"authzIdTemplate": "dn:uid={uid},ou=People,dc=example,dc=com"
             }
         }
     },
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
index 0c53d23..b994823 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
@@ -224,8 +224,9 @@
         final Set<String> scopes = config.get(SCOPES).required().asSet(String.class);
         final AccessTokenResolver resolver =
                 createCachedTokenResolverIfNeeded(config, parseUnderlyingResolver(config));
+        final String resolverName = config.get(RESOLVER_CONFIG_OBJECT).asString();
         final ConditionalFilter oAuth2Filter = newConditionalOAuth2ResourceServerFilter(
-                realm, scopes, resolver, config.get(AUTHZID_TEMPLATE).required().asString());
+                realm, scopes, resolver, config.get(resolverName).get(AUTHZID_TEMPLATE).required().asString());
         return newConditionalFilter(
                 Filters.chainOf(oAuth2Filter.getFilter(),
                                 newProxyAuthzFilter(getConnectionFactory(DEFAULT_ROOT_FACTORY))),
diff --git a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java
index 72c29b4..74690ee 100644
--- a/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java
+++ b/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/OAuth2JsonConfigurationTestCase.java
@@ -83,19 +83,23 @@
                 // Invalid 'authzIdTemplate' content
                 {
                         "{'realm': 'example.com',"
-                                + "'authzIdTemplate': 'userName: ou={/user/id},dc=example,dc=com',"
                                 + "'requiredScopes': ['read', 'write', 'dolphin'],"
                                 + "'resolver': 'openam',"
-                                + "'openam': {'endpointURL': 'http://www.example.com/token-info'},"
+                                + "'openam': {"
+                                + "    'endpointURL': 'http://www.example.com/token-info',"
+                                + "    'authzIdTemplate': 'userName: ou={/user/id},dc=example,dc=com'"
+                                + "},"
                                 + "'accessTokenCache': {'enabled': true, 'cacheExpiration': '42'}}",
                 },
                 // Invalid 'accessTokenCache/expiration' duration
                 {
                         "{'realm': 'example.com',"
-                                + "'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com',"
                                 + "'requiredScopes': ['read', 'write', 'dolphin'],"
                                 + "'resolver': 'openam',"
-                                + "'openam': {'endpointURL': 'http://www.example.com/token-info'},"
+                                + "'openam': {"
+                                + "    'endpointURL': 'http://www.example.com/token-info',"
+                                + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'"
+                                + "},"
                                 + "'accessTokenCache': {'enabled': true, 'cacheExpiration': '42'}}",
                 }
         };
@@ -112,10 +116,12 @@
     public void testOAuth2FilterWithEmptyScopes() throws Exception {
         final String config =
             "{'realm': 'example.com',"
-                    + "'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com',"
                     + "'requiredScopes': [],"
                     + "'resolver': 'openam',"
-                    + "'openam': {'endpointURL': 'http://www.example.com/token-info'}}";
+                    + "'openam': {"
+                    + "    'endpointURL': 'http://www.example.com/token-info',"
+                    + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'"
+                    + "}}";
         fakeApp.buildOAuth2Filter(parseJson(config));
     }
 
@@ -211,20 +217,25 @@
                 {
                         "{'resolver': 'rfc7662',"
                                 + "'rfc7662': { 'endpointURL': 'http:/example.com/introspect',"
-                                + "               'clientId': 'client_app_id',"
-                                + "               'clientSecret': 'client_app_secret'}}"
+                                + "             'clientId': 'client_app_id',"
+                                + "             'clientSecret': 'client_app_secret',"
+                                + "             'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                 },
                 {
                         "{'resolver': 'openam',"
-                                + "'openam': { 'endpointURL': 'http:/example.com/tokeninfo'}}"
+                                + "'openam': { "
+                                + "    'endpointURL': 'http:/example.com/tokeninfo',"
+                                + "    'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                 },
                 {
                         "{'resolver': 'cts',"
-                                + "'cts': { 'baseDN': 'coreTokenId={token},dc=com' }}"
+                                + "'cts': { 'baseDN': 'coreTokenId={token},dc=com',"
+                                + "         'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                 },
                 {
                         "{'resolver': 'file',"
-                                + "'file': { 'folderPath': '/path/to/test/folder'}}"
+                                + "'file': { 'folderPath': '/path/to/test/folder',"
+                                + "          'authzIdTemplate': 'dn: ou={/user/id},dc=example,dc=com'}}"
                 }
         };
         // @Checkstyle:on

--
Gitblit v1.10.0