From 154bb05e9bbd45eaa3ca8bef8d2a6af076b1790c Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Fri, 1 Feb 2013 13:05:38 -0500
Subject: [PATCH] Added AuthMapping annotation.

A new AuthMapping annotation has been added to configure the required
authentication methods to acces each REST method. The annotation maps each
method into a list of authentication methods in auth.properties.

For security reason, most REST methods that require authentication have been
configured to require client certificate authentication. Authentication using
username and password will only be used to get installation token from the
security domain.

Previously the auth.properties files were used to store ACL mappings. Now the
ACL mappings have been moved into acl.properties.

Ticket #477
---
 .../ca/WEB-INF/{auth.properties => acl.properties} |   6 +-
 base/ca/shared/webapps/ca/WEB-INF/auth.properties  |  19 ++-
 .../ca/CertificateAuthorityApplication.java        |   4 +-
 .../netscape/certsrv/account/AccountResource.java  |   2 +
 .../com/netscape/certsrv/acls/ACLInterceptor.java  |  16 +--
 .../certsrv/authentication/AuthInterceptor.java    | 159 +++++++++++++++++++++
 .../AuthMapping.java}                              |  24 +---
 .../netscape/certsrv/cert/CertRequestResource.java |  52 ++++---
 .../com/netscape/certsrv/cert/CertResource.java    |   5 +
 .../certsrv/group/GroupMemberResource.java         |   2 +
 .../com/netscape/certsrv/group/GroupResource.java  |   2 +
 .../netscape/certsrv/key/KeyRequestResource.java   |   2 +
 .../src/com/netscape/certsrv/key/KeyResource.java  |   2 +
 .../netscape/certsrv/profile/ProfileResource.java  |   3 +
 .../certsrv/system/KRAConnectorResource.java       |   2 +
 .../certsrv/system/SecurityDomainResource.java     |   2 +
 .../netscape/certsrv/user/UserCertResource.java    |   2 +
 .../com/netscape/certsrv/user/UserResource.java    |   2 +
 .../WEB-INF/{auth.properties => acl.properties}    |   6 +-
 .../kra/shared/webapps/kra/WEB-INF/auth.properties |  16 +--
 .../kra/KeyRecoveryAuthorityApplication.java       |   4 +-
 .../WEB-INF/{auth.properties => acl.properties}    |   6 +-
 .../shared/webapps/ocsp/WEB-INF/auth.properties    |  13 +-
 .../src/com/netscape/ocsp/OCSPApplication.java     |   4 +-
 .../WEB-INF/{auth.properties => acl.properties}    |   6 +-
 .../tks/shared/webapps/tks/WEB-INF/auth.properties |  13 +-
 base/tks/src/com/netscape/tks/TKSApplication.java  |   4 +-
 27 files changed, 282 insertions(+), 96 deletions(-)
 copy base/ca/shared/webapps/ca/WEB-INF/{auth.properties => acl.properties} (73%)
 create mode 100644 base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java
 copy base/common/src/com/netscape/certsrv/{account/AccountResource.java => authentication/AuthMapping.java} (67%)
 copy base/kra/shared/webapps/kra/WEB-INF/{auth.properties => acl.properties} (65%)
 copy base/ocsp/shared/webapps/ocsp/WEB-INF/{auth.properties => acl.properties} (56%)
 copy base/tks/shared/webapps/tks/WEB-INF/{auth.properties => acl.properties} (56%)

diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/acl.properties
similarity index 73%
copy from base/ca/shared/webapps/ca/WEB-INF/auth.properties
copy to base/ca/shared/webapps/ca/WEB-INF/acl.properties
index b73b9ac10eaf5f07da61e78d85dd4d9c703d7064..20f3dd864254779f9939c3d2873eb28a9cddf57c 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties
+++ b/base/ca/shared/webapps/ca/WEB-INF/acl.properties
@@ -1,8 +1,8 @@
-# Restful API auth/authz mapping info
+# Restful API authorization mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <resource ID>,<operation>
+# ex: admin.users = certServer.ca.users,read
 
 account.login = certServer.ca.account,login
 account.logout = certServer.ca.account,logout
diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
index b73b9ac10eaf5f07da61e78d85dd4d9c703d7064..3a6658765ed3382b7a5f0136eb75555566a54127 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties
+++ b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
@@ -1,14 +1,11 @@
-# Restful API auth/authz mapping info
+# Restful API auth mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <allowed auth methods>
+# ex: admin.users = certUserDBAuthMgr,passwdUserDBAuthMgr
 
-account.login = certServer.ca.account,login
-account.logout = certServer.ca.account,logout
-admin.users = certServer.ca.users,execute
-admin.groups = certServer.ca.groups,execute
-admin.kraconnector = certServer.ca.connectorInfo,modify
-agent.certrequests = certServer.ca.certrequests,execute
-agent.certs = certServer.ca.certs,execute
-securityDomain.installToken = certServer.securitydomain.domainxml,read
+default = *
+account = certUserDBAuthMgr,passwdUserDBAuthMgr
+admin = certUserDBAuthMgr
+agent = certUserDBAuthMgr
+securityDomain.installToken = passwdUserDBAuthMgr
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
index 14b44e5d7695b230aa99c109d603594ee37a745c..35e93811cfd5c24f1f89fba64e27d554272c69df 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
@@ -7,6 +7,7 @@ import javax.ws.rs.core.Application;
 
 import com.netscape.certsrv.acls.ACLInterceptor;
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.AuthInterceptor;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.PKIException;
@@ -85,7 +86,8 @@ public class CertificateAuthorityApplication extends Application {
         // exception mapper
         classes.add(PKIException.Mapper.class);
 
-        // ACL interceptor
+        // interceptors
+        singletons.add(new AuthInterceptor());
         singletons.add(new ACLInterceptor());
     }
 
diff --git a/base/common/src/com/netscape/certsrv/account/AccountResource.java b/base/common/src/com/netscape/certsrv/account/AccountResource.java
index a69a3d122e1d887b7a8d081e6fb3f477fa1715e9..cbe061b5a22b997e35fd679a610c38e810410e45 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountResource.java
+++ b/base/common/src/com/netscape/certsrv/account/AccountResource.java
@@ -22,11 +22,13 @@ import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Endi S. Dewata
  */
 @Path("account")
+@AuthMapping("account")
 public interface AccountResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java
index c30740260505ffc0223ac55b7658f57f02a53532..dd4985eab049aad49089343c239b7c646eab19b1 100644
--- a/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java
+++ b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java
@@ -54,7 +54,7 @@ import com.netscape.cmscore.realm.PKIPrincipal;
 @Precedence("SECURITY")
 public class ACLInterceptor implements PreProcessInterceptor {
 
-    Properties authProperties;
+    Properties aclProperties;
 
     @Context
     ServletContext servletContext;
@@ -62,13 +62,13 @@ public class ACLInterceptor implements PreProcessInterceptor {
     @Context
     SecurityContext securityContext;
 
-    public synchronized void loadAuthProperties() throws IOException {
+    public synchronized void loadACLProperties() throws IOException {
 
-        if (authProperties != null) return;
+        if (aclProperties != null) return;
 
-        URL url = servletContext.getResource("/WEB-INF/auth.properties");
-        authProperties = new Properties();
-        authProperties.load(url.openStream());
+        URL url = servletContext.getResource("/WEB-INF/acl.properties");
+        aclProperties = new Properties();
+        aclProperties.load(url.openStream());
     }
 
     @Override
@@ -111,10 +111,10 @@ public class ACLInterceptor implements PreProcessInterceptor {
         }
 
         try {
-            loadAuthProperties();
+            loadACLProperties();
 
             String name = aclMapping.value();
-            String value = authProperties.getProperty(name);
+            String value = aclProperties.getProperty(name);
 
             // If no property defined, allow request.
             if (value == null) return null;
diff --git a/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java b/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fd7cdd319199d882ff1db57b335326912992873
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java
@@ -0,0 +1,159 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2013 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.authentication;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.annotations.interception.Precedence;
+import org.jboss.resteasy.annotations.interception.ServerInterceptor;
+import org.jboss.resteasy.core.ResourceMethod;
+import org.jboss.resteasy.core.ServerResponse;
+import org.jboss.resteasy.spi.Failure;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
+
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.cmscore.realm.PKIPrincipal;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+@Provider
+@ServerInterceptor
+@Precedence("SECURITY")
+public class AuthInterceptor implements PreProcessInterceptor {
+
+    Properties authProperties;
+
+    @Context
+    ServletContext servletContext;
+
+    @Context
+    SecurityContext securityContext;
+
+    public synchronized void loadAuthProperties() throws IOException {
+
+        if (authProperties != null) return;
+
+        URL url = servletContext.getResource("/WEB-INF/auth.properties");
+        authProperties = new Properties();
+        authProperties.load(url.openStream());
+    }
+
+    @Override
+    public ServerResponse preProcess(
+            HttpRequest request,
+            ResourceMethod resourceMethod
+        ) throws Failure, ForbiddenException {
+
+        Class<?> clazz = resourceMethod.getResourceClass();
+        Method method = resourceMethod.getMethod();
+        System.out.println("AuthInterceptor: "+clazz.getSimpleName()+"."+method.getName()+"()");
+
+        // Get authentication mapping for the method.
+        AuthMapping authMapping = method.getAnnotation(AuthMapping.class);
+
+        // If not available, get authentication mapping for the class.
+        if (authMapping == null) {
+            authMapping = clazz.getAnnotation(AuthMapping.class);
+        }
+
+        String name;
+        if (authMapping == null) {
+            // If not available, use the default mapping.
+            name = "default";
+        } else {
+            // Get the method label
+            name = authMapping.value();
+        }
+
+        System.out.println("AuthInterceptor: mapping name: "+name);
+
+        try {
+            loadAuthProperties();
+
+            String value = authProperties.getProperty(name);
+            Collection<String> authMethods = new HashSet<String>();
+            if (value != null) {
+                for (String v : value.split(",")) {
+                    authMethods.add(v.trim());
+                }
+            }
+
+            System.out.println("AuthInterceptor: required auth methods: "+authMethods);
+
+            Principal principal = securityContext.getUserPrincipal();
+
+            // If unauthenticated, reject request.
+            if (principal == null) {
+                if (authMethods.isEmpty() || authMethods.contains("anonymous") || authMethods.contains("*")) {
+                    System.out.println("AuthInterceptor: anonymous access allowed");
+                    return null;
+                }
+                System.out.println("AuthInterceptor: anonymous access not allowed");
+                throw new ForbiddenException("Anonymous access not allowed.");
+            }
+
+            // If unrecognized principal, reject request.
+            if (!(principal instanceof PKIPrincipal)) {
+                System.out.println("AuthInterceptor: unknown principal");
+                throw new ForbiddenException("Unknown user principal");
+            }
+
+            PKIPrincipal pkiPrincipal = (PKIPrincipal)principal;
+            IAuthToken authToken = pkiPrincipal.getAuthToken();
+
+            // If missing auth token, reject request.
+            if (authToken == null) {
+                System.out.println("AuthInterceptor: missing authentication token");
+                throw new ForbiddenException("Missing authentication token.");
+            }
+
+            String authManager = (String)authToken.get(AuthToken.TOKEN_AUTHMGR_INST_NAME);
+            System.out.println("AuthInterceptor: authentication manager: "+authManager);
+
+            if (authManager == null) {
+                System.out.println("AuthInterceptor: missing authentication manager");
+                throw new ForbiddenException("Missing authentication manager.");
+            }
+
+            if (authMethods.isEmpty() || authMethods.contains(authManager) || authMethods.contains("*")) {
+                System.out.println("AuthInterceptor: "+authManager+" allowed");
+                return null;
+            }
+
+            throw new ForbiddenException("Authentication method not allowed.");
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new Failure(e);
+        }
+    }
+}
diff --git a/base/common/src/com/netscape/certsrv/account/AccountResource.java b/base/common/src/com/netscape/certsrv/authentication/AuthMapping.java
similarity index 67%
copy from base/common/src/com/netscape/certsrv/account/AccountResource.java
copy to base/common/src/com/netscape/certsrv/authentication/AuthMapping.java
index a69a3d122e1d887b7a8d081e6fb3f477fa1715e9..e00cc9d63cad4f01e0523ed1e9efac79d94573be 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountResource.java
+++ b/base/common/src/com/netscape/certsrv/authentication/AuthMapping.java
@@ -12,30 +12,20 @@
 // with this program; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 //
-// (C) 2012 Red Hat, Inc.
+// (C) 2013 Red Hat, Inc.
 // All rights reserved.
 // --- END COPYRIGHT BLOCK ---
 
-package com.netscape.certsrv.account;
+package com.netscape.certsrv.authentication;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
-import com.netscape.certsrv.acls.ACLMapping;
 
 /**
  * @author Endi S. Dewata
  */
-@Path("account")
-public interface AccountResource {
-
-    @GET
-    @Path("login")
-    @ACLMapping("account.login")
-    public void login();
-
-    @GET
-    @Path("logout")
-    @ACLMapping("account.logout")
-    public void logout();
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AuthMapping {
+    public String value();
 }
diff --git a/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java b/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
index 0bd285136639ea80810a7637acf83bd16ac48253..901104cad9e005b91a2c655f2b53dbf1a058b0fc 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertRequestResource.java
@@ -28,11 +28,33 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 import com.netscape.certsrv.request.RequestId;
 
 @Path("")
 public interface CertRequestResource {
 
+    // Enrollment - used to test integration with a browser
+    @POST
+    @Path("certrequests")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
+    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form);
+
+    @POST
+    @Path("certrequests")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public CertRequestInfos enrollCert(CertEnrollmentRequest data);
+
+    /**
+     * Used to retrieve cert request info for a specific request
+     */
+    @GET
+    @Path("certrequests/{id}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public CertRequestInfo getRequestInfo(@PathParam("id") RequestId id);
+
     /**
      * Used to generate list of cert requests based on the search parameters
      */
@@ -40,6 +62,7 @@ public interface CertRequestResource {
     @Path("agent/certrequests")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public CertRequestInfos listRequests(@QueryParam("requestState") String requestState,
             @QueryParam("requestType") String requestType,
             @QueryParam("start") RequestId start,
@@ -47,72 +70,59 @@ public interface CertRequestResource {
             @QueryParam("maxResults") Integer maxResults,
             @QueryParam("maxTime") Integer maxTime);
 
-    /**
-     * Used to retrieve cert request info for a specific request
-     */
-    @GET
-    @Path("certrequests/{id}")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfo getRequestInfo(@PathParam("id") RequestId id);
-
     @GET
     @Path("agent/certrequests/{id}")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public CertReviewResponse reviewRequest(@PathParam("id") RequestId id);
 
-    // Enrollment - used to test integration with a browser
-    @POST
-    @Path("certrequests")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
-    public CertRequestInfos enrollCert(MultivaluedMap<String, String> form);
-
-    @POST
-    @Path("certrequests")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public CertRequestInfos enrollCert(CertEnrollmentRequest data);
-
     @POST
     @Path("agent/certrequests/{id}/approve")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void approveRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/reject")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void rejectRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/cancel")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void cancelRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/update")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void updateRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/validate")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void validateRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/unassign")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void unassignRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 
     @POST
     @Path("agent/certrequests/{id}/assign")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certrequests")
+    @AuthMapping("agent")
     public void assignRequest(@PathParam("id") RequestId id, CertReviewResponse data);
 }
diff --git a/base/common/src/com/netscape/certsrv/cert/CertResource.java b/base/common/src/com/netscape/certsrv/cert/CertResource.java
index 17395032d335f4a8f74a5cb2a64b886f5f7492f3..d7e2c0fb18a00bebf8df71cc7cba9e255727d417 100644
--- a/base/common/src/com/netscape/certsrv/cert/CertResource.java
+++ b/base/common/src/com/netscape/certsrv/cert/CertResource.java
@@ -11,6 +11,7 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 import com.netscape.certsrv.dbs.certdb.CertId;
 
 @Path("")
@@ -45,6 +46,7 @@ public interface CertResource {
     @Path("agent/certs/{id}")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certs")
+    @AuthMapping("agent")
     public CertData reviewCert(@PathParam("id") CertId id);
 
     @POST
@@ -52,6 +54,7 @@ public interface CertResource {
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certs")
+    @AuthMapping("agent")
     public CertRequestInfo revokeCACert(@PathParam("id") CertId id, CertRevokeRequest request);
 
     @POST
@@ -59,6 +62,7 @@ public interface CertResource {
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certs")
+    @AuthMapping("agent")
     public CertRequestInfo revokeCert(@PathParam("id") CertId id, CertRevokeRequest request);
 
     @POST
@@ -66,5 +70,6 @@ public interface CertResource {
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("agent.certs")
+    @AuthMapping("agent")
     public CertRequestInfo unrevokeCert(@PathParam("id") CertId id, CertUnrevokeRequest request);
 }
diff --git a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
index c984daa65ad130250b2f23ebde47434df43e00c9..7ebb09c2b7f79284bec78959a39c7c2f47880847 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupMemberResource.java
@@ -32,12 +32,14 @@ import javax.ws.rs.core.Response;
 import org.jboss.resteasy.annotations.ClientResponseType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Endi S. Dewata
  */
 @Path("admin/groups/{groupID}/members")
 @ACLMapping("admin.groups")
+@AuthMapping("admin")
 public interface GroupMemberResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/group/GroupResource.java b/base/common/src/com/netscape/certsrv/group/GroupResource.java
index 17728dd13fbd9bbf2b653f4eb0eee61f316f3266..8851bdaa026a6ca79f7ba44e18f086b275028318 100644
--- a/base/common/src/com/netscape/certsrv/group/GroupResource.java
+++ b/base/common/src/com/netscape/certsrv/group/GroupResource.java
@@ -32,12 +32,14 @@ import javax.ws.rs.core.Response;
 import org.jboss.resteasy.annotations.ClientResponseType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Endi S. Dewata
  */
 @Path("admin/groups")
 @ACLMapping("admin.groups")
+@AuthMapping("admin")
 public interface GroupResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
index 9f1ffbe023d73d82e959f35c582eae20012de2bc..fc1132f9c7fff08a4f1ddf3b368c54526350dedd 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyRequestResource.java
@@ -11,10 +11,12 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 import com.netscape.certsrv.request.RequestId;
 
 @Path("agent/keyrequests")
 @ACLMapping("agent.keyrequests")
+@AuthMapping("agent")
 public interface KeyRequestResource {
 
     public final String SYMMETRIC_KEY_TYPE = "symmetricKey";
diff --git a/base/common/src/com/netscape/certsrv/key/KeyResource.java b/base/common/src/com/netscape/certsrv/key/KeyResource.java
index da7f2203121072a593c2ad300f732b1da5adba1c..4a419a8c5f65c51818d0cb606e48b0c659ed39be 100644
--- a/base/common/src/com/netscape/certsrv/key/KeyResource.java
+++ b/base/common/src/com/netscape/certsrv/key/KeyResource.java
@@ -10,10 +10,12 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 
 @Path("agent/keys")
 @ACLMapping("agent.keys")
+@AuthMapping("agent")
 public interface KeyResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/profile/ProfileResource.java b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
index 6dadef560d5f7a2dfc6024b6874fe42b72bf7ed4..93cb6785cea2137e3f91e433d99f492f5e12e8f5 100644
--- a/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
+++ b/base/common/src/com/netscape/certsrv/profile/ProfileResource.java
@@ -6,8 +6,11 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
+import com.netscape.certsrv.authentication.AuthMapping;
+
 
 @Path("agent/profiles")
+@AuthMapping("agent")
 public interface ProfileResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java
index 01f159e965fb2482f42931e92f87444b82394eb7..8f34985ac87008db5bbccdc518ecd0a8e96093ae 100644
--- a/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java
+++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java
@@ -26,12 +26,14 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Ade Lee
  */
 @Path("admin/kraconnector")
 @ACLMapping("admin.kraconnector")
+@AuthMapping("admin")
 public interface KRAConnectorResource {
 
     @POST
diff --git a/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
index b34d9fe13715ab85fded77c7d90db82e0a89bf6d..dd9693eaa26c546f2f9a8b4551d62f6da271361a 100644
--- a/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
@@ -24,6 +24,7 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author alee
@@ -35,6 +36,7 @@ public interface SecurityDomainResource {
     @Path("installToken")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     @ACLMapping("securityDomain.installToken")
+    @AuthMapping("securityDomain.installToken")
     public InstallToken getInstallToken(
             @QueryParam("hostname") String hostname,
             @QueryParam("subsystem") String subsystem);
diff --git a/base/common/src/com/netscape/certsrv/user/UserCertResource.java b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
index d85abd6e0d86e3febda76c3ce5d139893a577042..67159c5ffdb3009c0a47e2422b83a9c37349933c 100644
--- a/base/common/src/com/netscape/certsrv/user/UserCertResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserCertResource.java
@@ -32,12 +32,14 @@ import javax.ws.rs.core.Response;
 import org.jboss.resteasy.annotations.ClientResponseType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Endi S. Dewata
  */
 @Path("admin/users/{userID}/certs")
 @ACLMapping("admin.users")
+@AuthMapping("admin")
 public interface UserCertResource {
 
     @GET
diff --git a/base/common/src/com/netscape/certsrv/user/UserResource.java b/base/common/src/com/netscape/certsrv/user/UserResource.java
index e72bb0cefbc204aea7da51ea1f7e4da3fde5960f..b00278aea384906d28b257d25ac2f1e12b4121b0 100644
--- a/base/common/src/com/netscape/certsrv/user/UserResource.java
+++ b/base/common/src/com/netscape/certsrv/user/UserResource.java
@@ -32,12 +32,14 @@ import javax.ws.rs.core.Response;
 import org.jboss.resteasy.annotations.ClientResponseType;
 
 import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMapping;
 
 /**
  * @author Endi S. Dewata
  */
 @Path("admin/users")
 @ACLMapping("admin.users")
+@AuthMapping("admin")
 public interface UserResource {
 
     @GET
diff --git a/base/kra/shared/webapps/kra/WEB-INF/auth.properties b/base/kra/shared/webapps/kra/WEB-INF/acl.properties
similarity index 65%
copy from base/kra/shared/webapps/kra/WEB-INF/auth.properties
copy to base/kra/shared/webapps/kra/WEB-INF/acl.properties
index 567747f5b0d5aa504ef0184190d271d7ff2b64ab..952bdad33e5d2006fdcd7a4bfc74a3d1c01d3c05 100644
--- a/base/kra/shared/webapps/kra/WEB-INF/auth.properties
+++ b/base/kra/shared/webapps/kra/WEB-INF/acl.properties
@@ -1,8 +1,8 @@
-# Restful API auth/authz mapping info
+# Restful API authorization mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <resource ID>,<operation>
+# ex: admin.users = certServer.ca.users,read
 
 account.login = certServer.kra.account,login
 account.logout = certServer.kra.account,logout
diff --git a/base/kra/shared/webapps/kra/WEB-INF/auth.properties b/base/kra/shared/webapps/kra/WEB-INF/auth.properties
index 567747f5b0d5aa504ef0184190d271d7ff2b64ab..29a2f2381f6a9006a137dc289ff48cf0699f966e 100644
--- a/base/kra/shared/webapps/kra/WEB-INF/auth.properties
+++ b/base/kra/shared/webapps/kra/WEB-INF/auth.properties
@@ -1,12 +1,10 @@
-# Restful API auth/authz mapping info
+# Restful API auth mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <allowed auth methods>
+# ex: admin.users = certUserDBAuthMgr,passwdUserDBAuthMgr
 
-account.login = certServer.kra.account,login
-account.logout = certServer.kra.account,logout
-admin.users = certServer.kra.users,execute
-admin.groups = certServer.kra.groups,execute
-agent.keys = certServer.kra.keys,execute
-agent.keyrequests = certServer.kra.keyrequests,execute
+default = *
+account = certUserDBAuthMgr,passwdUserDBAuthMgr
+admin = certUserDBAuthMgr
+agent = certUserDBAuthMgr
diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
index 0ed23f6971f6d0f7c1ec42301f7bb1a29b7e1a89..d256c04382650e463e906c742501e06b4e78e69a 100644
--- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
+++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java
@@ -6,6 +6,7 @@ import java.util.Set;
 import javax.ws.rs.core.Application;
 
 import com.netscape.certsrv.acls.ACLInterceptor;
+import com.netscape.certsrv.authentication.AuthInterceptor;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.cms.servlet.account.AccountService;
 import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -46,7 +47,8 @@ public class KeyRecoveryAuthorityApplication extends Application {
         // exception mapper
         classes.add(PKIException.Mapper.class);
 
-        // ACL interceptor
+        // interceptors
+        singletons.add(new AuthInterceptor());
         singletons.add(new ACLInterceptor());
     }
 
diff --git a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties b/base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties
similarity index 56%
copy from base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
copy to base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties
index cd2e14058f382429f0ca12813b275fee70ea7c09..95fabba720adcc6d13eb3139e0edeb775a6220fc 100644
--- a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
+++ b/base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties
@@ -1,8 +1,8 @@
-# Restful API auth/authz mapping info
+# Restful API authorization mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <resource ID>,<operation>
+# ex: admin.users = certServer.ca.users,read
 
 account.login = certServer.ocsp.account,login
 account.logout = certServer.ocsp.account,logout
diff --git a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties b/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
index cd2e14058f382429f0ca12813b275fee70ea7c09..81e24403fb635c014be3c5edde7906888775f096 100644
--- a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
+++ b/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties
@@ -1,10 +1,9 @@
-# Restful API auth/authz mapping info
+# Restful API auth mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <allowed auth methods>
+# ex: admin.users = certUserDBAuthMgr,passwdUserDBAuthMgr
 
-account.login = certServer.ocsp.account,login
-account.logout = certServer.ocsp.account,logout
-admin.users = certServer.ocsp.users,execute
-admin.groups = certServer.ocsp.groups,execute
+default = *
+account = certUserDBAuthMgr,passwdUserDBAuthMgr
+admin = certUserDBAuthMgr
diff --git a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
index 21b37f8010f2f25dec85d666581b8d5b34c0383d..6a5f60f6e0b2f8702ead65a368ddf643cf6280f6 100644
--- a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
+++ b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java
@@ -6,6 +6,7 @@ import java.util.Set;
 import javax.ws.rs.core.Application;
 
 import com.netscape.certsrv.acls.ACLInterceptor;
+import com.netscape.certsrv.authentication.AuthInterceptor;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.cms.servlet.account.AccountService;
 import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -40,7 +41,8 @@ public class OCSPApplication extends Application {
         // exception mapper
         classes.add(PKIException.Mapper.class);
 
-        // ACL interceptor
+        // interceptors
+        singletons.add(new AuthInterceptor());
         singletons.add(new ACLInterceptor());
     }
 
diff --git a/base/tks/shared/webapps/tks/WEB-INF/auth.properties b/base/tks/shared/webapps/tks/WEB-INF/acl.properties
similarity index 56%
copy from base/tks/shared/webapps/tks/WEB-INF/auth.properties
copy to base/tks/shared/webapps/tks/WEB-INF/acl.properties
index 6de7f08e557a36742b603c87eda6a92ee6b9fa37..62367135ec8f503b34bb0a4bb04ebfc535ff582b 100644
--- a/base/tks/shared/webapps/tks/WEB-INF/auth.properties
+++ b/base/tks/shared/webapps/tks/WEB-INF/acl.properties
@@ -1,8 +1,8 @@
-# Restful API auth/authz mapping info
+# Restful API authorization mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <resource ID>,<operation>
+# ex: admin.users = certServer.ca.users,read
 
 account.login = certServer.tks.account,login
 account.logout = certServer.tks.account,logout
diff --git a/base/tks/shared/webapps/tks/WEB-INF/auth.properties b/base/tks/shared/webapps/tks/WEB-INF/auth.properties
index 6de7f08e557a36742b603c87eda6a92ee6b9fa37..81e24403fb635c014be3c5edde7906888775f096 100644
--- a/base/tks/shared/webapps/tks/WEB-INF/auth.properties
+++ b/base/tks/shared/webapps/tks/WEB-INF/auth.properties
@@ -1,10 +1,9 @@
-# Restful API auth/authz mapping info
+# Restful API auth mapping info
 #
 # Format:
-# <ACL Mapping> = <ACL Resource ID>,<ACL Resource Operation>
-# ex:      admin.users = certServer.ca.users,read
+# <mapping name> = <allowed auth methods>
+# ex: admin.users = certUserDBAuthMgr,passwdUserDBAuthMgr
 
-account.login = certServer.tks.account,login
-account.logout = certServer.tks.account,logout
-admin.users = certServer.tks.users,execute
-admin.groups = certServer.tks.groups,execute
+default = *
+account = certUserDBAuthMgr,passwdUserDBAuthMgr
+admin = certUserDBAuthMgr
diff --git a/base/tks/src/com/netscape/tks/TKSApplication.java b/base/tks/src/com/netscape/tks/TKSApplication.java
index 229a64c95abe5b0dce25d94df89d6fc6c04904b8..c79e0d0f2ce2fb6552e9e093a48b0eb096fd2ff0 100644
--- a/base/tks/src/com/netscape/tks/TKSApplication.java
+++ b/base/tks/src/com/netscape/tks/TKSApplication.java
@@ -6,6 +6,7 @@ import java.util.Set;
 import javax.ws.rs.core.Application;
 
 import com.netscape.certsrv.acls.ACLInterceptor;
+import com.netscape.certsrv.authentication.AuthInterceptor;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.cms.servlet.account.AccountService;
 import com.netscape.cms.servlet.admin.GroupMemberService;
@@ -40,7 +41,8 @@ public class TKSApplication extends Application {
         // exception mapper
         classes.add(PKIException.Mapper.class);
 
-        // ACL interceptor
+        // interceptors
+        singletons.add(new AuthInterceptor());
         singletons.add(new ACLInterceptor());
     }
 
-- 
1.7.12.1

