diff --git a/config/application.config.php b/config/application.config.php
index 49d744a6fb86eeebb7c0ae00de908daf1de54170..2efe44d7c654c251eeed4e4c8232a1ad8bb1f5fe 100644
--- a/config/application.config.php
+++ b/config/application.config.php
@@ -2,7 +2,7 @@
 
 // Set up modules:
 $modules = array(
-    'VuFindTheme', 'VuFindSearch', 'VuFind', 'VuFindAdmin'
+    'ZfcRbac', 'VuFindTheme', 'VuFindSearch', 'VuFind', 'VuFindAdmin'
 );
 if (PHP_SAPI == 'cli' && !defined('VUFIND_PHPUNIT_RUNNING')) {
     $modules[] = 'VuFindConsole';
diff --git a/config/vufind/EIT.ini b/config/vufind/EIT.ini
index 7c8cc2f918a6c6d5db77fe631bbfaa1e392430fb..a7226ae04a9353de960cd9f7cfca4dfe2f930f01 100644
--- a/config/vufind/EIT.ini
+++ b/config/vufind/EIT.ini
@@ -10,10 +10,11 @@
 ; that is not available via the EBSCOhost API - will cause EBSCO searches to fail
 ; entirely.
 ;
-; Because of licensing restrictions, EBSCO results are only shown to users
-; who have logged in to VuFind. Please be aware of any potential licensing issues
-; that may arise if you allow users who are unaffiliated with your institution to
-; create accounts in your VuFind instance.
+; NOTE: Because of licensing restrictions, by default, EBSCO results are only shown
+; to users who have logged in to VuFind. This behavior can be changed by adjusting
+; permissions.ini. Please be aware of any potential licensing issues that may arise
+; if you allow users who are unaffiliated with your institution to create accounts
+; in your VuFind instance or if you reconfigure the default behavior.
 prof = prof.prof.prof
 pwd = password
 dbs = aph,reh,ehh,etc
@@ -31,7 +32,6 @@ default_sort         = relevance
 ; through the translator, so  be sure to update language files if necessary.
 ; The order of these settings will be maintained in the drop-down list in the
 ; UI.
-
 [Basic_Searches]
 TX           = "All Fields"
 TI               = Title
diff --git a/config/vufind/Summon.ini b/config/vufind/Summon.ini
index b2ae971d9ba1adfb2f5504616eb62cd2e4e7c008..df38e57522543412bab7e95807da207ab520f47b 100644
--- a/config/vufind/Summon.ini
+++ b/config/vufind/Summon.ini
@@ -1,3 +1,8 @@
+; IMPORTANT NOTE: By default, VuFind will not show any search results that
+; require "authenticated" status for visibility. Please configure the
+; access.SummonExtendedResults permission in permissions.ini to allow users to
+; see these results. You are responsible for complying with your license.
+
 ; This section contains global settings affecting search behavior.
 [General]
 ; This setting controls the default sort order of search results; the selected
@@ -243,16 +248,6 @@ enabled = true
 ; through the current result set from within the record view.
 next_prev_navigation = false
 
-; Users will see more records if Summon is set to "authenticated" mode. It is
-; up to you to determine how to identify authenticated users in compliance with
-; your Summon contract. Authentication is disabled by default; you can turn on
-; settings below to activate it based on various conditions.
-[Auth]
-; set to true to authenticate Summon based on user's login status within VuFind:
-check_login = false
-; set to a regular expression for matching valid IPs to activate IP whitelisting:
-;ip_range = "/1\.2\.3\.[0-2]?[0-9]?[0-9]/"
-
 ; This section defines the view options available on standard search results.
 ; If only one view is required, set default_view under [General] above, and
 ; leave this section commented out.
diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index df7b68b0e3ab8deea8cd24498d61e5d5fb9c299c..e46c919095b332068d73c2374cd1f825f0bcdeaa 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -77,8 +77,8 @@ defaultRecordTab= Holdings
 hideHoldingsTabWhenEmpty = false
 ; This page will show by default when a user accesses the MyResearch module:
 defaultAccountPage = Favorites
-; Allow access to the Admin module? (See [AdminAuth] below for more granular ways
-; to restrict Admin access).
+; Allow access to the Admin module? (See the access.AdminModule setting in
+; permissions.ini for more granular ways to restrict Admin access).
 admin_enabled = false
 ; Show sidebar on the left side instead of right
 sidebarOnLeft = false
@@ -445,7 +445,7 @@ database          = mysql://root@localhost/vufind
 ;college = HTTP_COLLEGE
 ;major = HTTP_MAJOR
 ;home_library = HTTP_HOME_LIBRARY
-;
+
 ; CAS is optional.  This section only needs to exist if the
 ; Authentication Method is set to CAS.
 ;[CAS]
@@ -1042,19 +1042,6 @@ dewey = title
 [Security]
 HMACkey = mySuperSecretValue
 
-; This section restricts access to the Admin module of VuFind.
-;[AdminAuth]
-; This setting can be used to restrict the Admin module to IP addresses matching a
-; regular expression; leave it commented out to allow all IP addresses.  When
-; generating regular expressions, remember that the "." character is a wildcard;
-; you have to use "\." to represent an actual dot!
-;ipRegEx = "/1\.2\.3\.4|1\.2\.3\.5/"
-; This setting can be used to restrict the Admin module to a particular set of users.
-; The userWhitelist[] setting can be repeated as many times as necessary.  If it is
-; commented out, login will not be required to access the Admin module.
-;userWhitelist[] = username1
-;userWhitelist[] = username2
-
 ; This section sets global defaults for caches; file caching is used by default.
 ;[Cache]
 ; Set time to live value for Zend caches (in seconds), 0 means maximum possible.
diff --git a/config/vufind/permissions.ini b/config/vufind/permissions.ini
new file mode 100644
index 0000000000000000000000000000000000000000..734f88ee6f21ae18890d2b5f2801254086300850
--- /dev/null
+++ b/config/vufind/permissions.ini
@@ -0,0 +1,55 @@
+; This file controls how permissions are assigned to roles within VuFind.
+;
+; Each section of the file contains a group of rules that grant permissions. The name
+; of the section is unimportant as long as each section has a unique name. This
+; section contains several keys:
+;
+; require    - Set to 'ALL' to require all conditions in the section to be met in
+;              order to grant the permission(s). Set to 'ANY' to allow any one or 
+;              more of the conditions to grant the permission(s). Defaults to 'ALL'
+;              if unset. Note that this rule is used for combining the output of
+;              permission provider services. When a single permission provider
+;              accepts multiple lines of configuration, the way those lines are
+;              combined may vary from provider to provider (see below).
+; permission - The name(s) of the permission(s) to grant. May be a single string or
+;              an array of strings.
+;
+; Any other keys in the section should be the names of permission provider services.
+; The values associated with these keys will be passed along to the services.
+; You can define your own permission providers, or use some of the following:
+;
+; ipRange  - Grant the permission to the single IP adresse or to the range.
+;            Accepts a single IP adresse or a range with a minus character without 
+;            blanks as seperator.
+; ipRegEx  - Grant the permission to IP addresses matching the provided regular
+;            expression(s). Accepts a string or an array; if an array is passed,
+;            permission will be granted if ANY one of the expressions matches.
+; role     - Grant the permission automatically to the role or roles specified
+;            (accepts a string or an array). Note that VuFind uses 'guest' for
+;            logged-out users and 'loggedin' for all logged-in users. You may
+;            define additional roles with custom code.
+; username - Grant the permission to logged-in users whose usernames match the
+;            specified value(s). Accepts a string or an array.
+;
+; Example configuration (grants the "sample.permission" permission to users named
+; admin1 or admin2, or anyone coming from the IP addresses 1.2.3.4 or 1.2.3.5):
+;
+; [sample.rules]
+; require = ANY
+; username[] = admin1
+; username[] = admin2
+; ipRegEx = "/1\.2\.3\.4|1\.2\.3\.5/"
+; ipRange[] = "1.2.3.4"
+; ipRange[] = "1.2.3.7-1.2.5.254"
+; permission = sample.permission
+;
+; List of permissions that you may wish to configure:
+;
+; access.AdminModule - Controls access to the admin panel (if enabled in config.ini)
+; access.EITModule - Controls access to the EBSCO EIT module (if active)
+; access.SummonExtendedResults - Controls visibility of protected Summon results
+
+; Default configuration for the EIT module; see EIT.ini for some notes on this.
+[default.EITModule]
+role = loggedin
+permission = access.EITModule
\ No newline at end of file
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 6a6e4e7147b17d00e3fa29dd6fc501fdc2631ba9..e39d27a8de70f74c3ff7297f0471fdb9a33f66bb 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -104,6 +104,9 @@ $config = array(
             'worldcat' => 'VuFind\Controller\WorldcatController',
             'worldcatrecord' => 'VuFind\Controller\WorldcatrecordController',
         ),
+        'initializers' => array(
+            'ZfcRbac\Initializer\AuthorizationServiceInitializer'
+        ),
     ),
     'controller_plugins' => array(
         'factories' => array(
@@ -652,6 +655,31 @@ $config = array(
             ),
         ),
     ),
+    // Authorization configuration:
+    'zfc_rbac' => array(
+        'identity_provider' => 'VuFind\AuthManager',
+        'guest_role' => 'guest',
+        'role_provider' => array(
+            'VuFind\Role\DynamicRoleProvider' => array(
+                'map_legacy_settings' => true,
+            ),
+        ),
+        'role_provider_manager' => array(
+            'factories' => array(
+                'VuFind\Role\DynamicRoleProvider' => 'VuFind\Role\DynamicRoleProviderFactory',
+            ),
+        ),
+        'vufind_permission_provider_manager' => array(
+            'factories' => array(
+                'ipRange' => 'VuFind\Role\PermissionProvider\Factory::getIpRange',
+                'ipRegEx' => 'VuFind\Role\PermissionProvider\Factory::getIpRegEx',
+                'username' => 'VuFind\Role\PermissionProvider\Factory::getUsername',
+            ),
+            'invokables' => array(
+                'role' => 'VuFind\Role\PermissionProvider\Role',
+            ),
+        ),
+    ),
 );
 
 // Define record view routes -- route name => controller
diff --git a/module/VuFind/src/VuFind/Auth/Manager.php b/module/VuFind/src/VuFind/Auth/Manager.php
index f0382c8e3d1eff438f38419465bf238f9ae8ea58..44eb99e55e43dc2b7e2712d062e61767ee824f9b 100644
--- a/module/VuFind/src/VuFind/Auth/Manager.php
+++ b/module/VuFind/src/VuFind/Auth/Manager.php
@@ -39,7 +39,7 @@ use VuFind\Db\Row\User as UserRow, VuFind\Db\Table\User as UserTable,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://www.vufind.org  Main Page
  */
-class Manager
+class Manager implements \ZfcRbac\Identity\IdentityProviderInterface
 {
     /**
      * Authentication modules
@@ -391,6 +391,16 @@ class Manager
         return $this->currentUser;
     }
 
+    /**
+     * Get the identity
+     *
+     * @return \ZfcRbac\Identity\IdentityInterface|null
+     */
+    public function getIdentity()
+    {
+        return ($user = $this->isLoggedIn()) ?: null;
+    }
+
     /**
      * Resets the session if the logged in user's credentials have expired.
      *
diff --git a/module/VuFind/src/VuFind/Config/Upgrade.php b/module/VuFind/src/VuFind/Config/Upgrade.php
index 77187d31435438d0de745ed85abfbfc273f1bf4c..0f40db360334e96e60bbd4c4dca98c9a39af7b09 100644
--- a/module/VuFind/src/VuFind/Config/Upgrade.php
+++ b/module/VuFind/src/VuFind/Config/Upgrade.php
@@ -110,6 +110,13 @@ class Upgrade
      */
     protected $inPlaceUpgrade;
 
+    /**
+     * Have we modified permissions.ini?
+     *
+     * @var bool
+     */
+    protected $permissionsModified = false;
+
     /**
      * Constructor
      *
@@ -154,6 +161,10 @@ class Upgrade
         $this->upgradeSummon();
         $this->upgradeWorldCat();
 
+        // The previous upgrade routines may have added values to permissions.ini,
+        // so we should save it last. It doesn't have its own upgrade routine.
+        $this->saveModifiedConfig('permissions.ini');
+
         // The following routines load special configurations that were not
         // explicitly loaded by loadConfigs:
         if ($this->from < 2) {  // some pieces only apply to 1.x upgrade!
@@ -280,7 +291,8 @@ class Upgrade
         // first so that getOldConfigPath can work properly!
         $configs = array(
             'config.ini', 'authority.ini', 'facets.ini', 'reserves.ini',
-            'searches.ini', 'Summon.ini', 'WorldCat.ini', 'sms.ini'
+            'searches.ini', 'Summon.ini', 'WorldCat.ini', 'sms.ini',
+            'permissions.ini'
         );
         foreach ($configs as $config) {
             // Special case for config.ini, since we may need to overlay extra
@@ -343,7 +355,11 @@ class Upgrade
         // If we're doing an in-place upgrade, and the source file is empty,
         // there is no point in upgrading anything (the file doesn't exist).
         if (empty($this->oldConfigs[$filename]) && $this->inPlaceUpgrade) {
-            return;
+            // Special case: if we set up custom permissions, we need to
+            // write the file even if it didn't previously exist.
+            if (!$this->permissionsModified || $filename !== 'permissions.ini') {
+                return;
+            }
         }
 
         // If target file already exists, back it up:
@@ -611,6 +627,9 @@ class Upgrade
             unset($newConfig['Syndetics']['url']);
         }
 
+        // Translate obsolete permission settings:
+        $this->upgradeAdminPermissions();
+
         // Deal with shard settings (which may have to be moved to another file):
         $this->upgradeShardSettings();
 
@@ -618,6 +637,39 @@ class Upgrade
         $this->saveModifiedConfig('config.ini');
     }
 
+    /**
+     * Translate obsolete permission settings.
+     *
+     * @return void
+     */
+    protected function upgradeAdminPermissions()
+    {
+        $config = & $this->newConfigs['config.ini'];
+        $permissions = & $this->newConfigs['permissions.ini'];
+
+        if (isset($config['AdminAuth'])) {
+            $permissions['access.AdminModule'] = [];
+            if (isset($config['AdminAuth']['ipRegEx'])) {
+                $permissions['access.AdminModule']['ipRegEx']
+                    = $config['AdminAuth']['ipRegEx'];
+            }
+            if (isset($config['AdminAuth']['userWhitelist'])) {
+                $permissions['access.AdminModule']['username']
+                    = $config['AdminAuth']['userWhitelist'];
+            }
+            // If no settings exist in config.ini, we grant access to everyone
+            // by allowing both logged-in and logged-out roles.
+            if (empty($permissions['access.AdminModule'])) {
+                $permissions['access.AdminModule']['role'] = ['guest', 'loggedin'];
+            }
+            $permissions['access.AdminModule']['permission'] = 'access.AdminModule';
+            $this->permissionsModified = true;
+
+            // Remove any old settings remaining in config.ini:
+            unset($config['AdminAuth']);
+        }
+    }
+
     /**
      * Upgrade facets.ini.
      *
@@ -856,12 +908,49 @@ class Upgrade
             }
         }
 
+        // update permission settings
+        $this->upgradeSummonPermissions();
+
         $this->upgradeSpellingSettings('Summon.ini');
 
         // save the file
         $this->saveModifiedConfig('Summon.ini');
     }
 
+    /**
+     * Translate obsolete permission settings.
+     *
+     * @return void
+     */
+    protected function upgradeSummonPermissions()
+    {
+        $config = & $this->newConfigs['Summon.ini'];
+        $permissions = & $this->newConfigs['permissions.ini'];
+        if (isset($config['Auth'])) {
+            $permissions['access.SummonExtendedResults'] = [];
+            if (isset($config['Auth']['check_login'])
+                && $config['Auth']['check_login']
+            ) {
+                $permissions['access.SummonExtendedResults']['role'] = ['loggedin'];
+            }
+            if (isset($config['Auth']['ip_range'])) {
+                $permissions['access.SummonExtendedResults']['ipRegEx']
+                    = $config['Auth']['ip_range'];
+            }
+            if (!empty($permissions['access.SummonExtendedResults'])) {
+                $permissions['access.SummonExtendedResults']['boolean'] = 'OR';
+                $permissions['access.SummonExtendedResults']['permission']
+                    = 'access.SummonExtendedResults';
+                $this->permissionsModified = true;
+            } else {
+                unset($permissions['access.SummonExtendedResults']);
+            }
+
+            // Remove any old settings remaining in config.ini:
+            unset($config['Auth']);
+        }
+    }
+
     /**
      * Upgrade WorldCat.ini.
      *
diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
index 3a5ea10e4222ddd2bd0ef0e3aac3027d06130bdf..2b163bfd200c48099f87e82ab5e921eeaa8fdafe 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -27,7 +27,13 @@
  * @link     http://vufind.org/wiki/vufind2:building_a_controller Wiki
  */
 namespace VuFind\Controller;
-use Zend\Mvc\Controller\AbstractActionController, Zend\View\Model\ViewModel;
+
+use VuFind\Exception\Forbidden as ForbiddenException,
+    Zend\Mvc\Controller\AbstractActionController,
+    Zend\Mvc\MvcEvent,
+    Zend\View\Model\ViewModel,
+    ZfcRbac\Service\AuthorizationServiceAwareInterface,
+    ZfcRbac\Service\AuthorizationServiceAwareTrait;
 
 /**
  * VuFind controller base class (defines some methods that can be shared by other
@@ -41,7 +47,54 @@ use Zend\Mvc\Controller\AbstractActionController, Zend\View\Model\ViewModel;
  * @SuppressWarnings(PHPMD.NumberOfChildren)
  */
 class AbstractBase extends AbstractActionController
+    implements AuthorizationServiceAwareInterface
 {
+    use AuthorizationServiceAwareTrait;
+
+    /**
+     * Permission that must be granted to access this module (false for no
+     * restriction)
+     *
+     * @var string|bool
+     */
+    protected $accessPermission = false;
+
+    /**
+     * preDispatch -- block access when appropriate.
+     *
+     * @param MvcEvent $e Event object
+     *
+     * @return void
+     */
+    public function preDispatch(MvcEvent $e)
+    {
+        // Make sure the current user has permission to access the module:
+        if ($this->accessPermission
+            && !$this->getAuthorizationService()->isGranted($this->accessPermission)
+        ) {
+            if (!$this->getUser()) {
+                $e->setResponse($this->forceLogin(null, array(), false));
+                return;
+            }
+            throw new ForbiddenException('Access denied.');
+        }
+    }
+
+    /**
+     * Register the default events for this controller
+     *
+     * @return void
+     */
+    protected function attachDefaultListeners()
+    {
+        parent::attachDefaultListeners();
+        // Attach preDispatch event if we need to check permissions.
+        if ($this->accessPermission) {
+            $events = $this->getEventManager();
+            $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 1000);
+        }
+    }
+
     /**
      * Constructor
      */
diff --git a/module/VuFind/src/VuFind/Controller/EITController.php b/module/VuFind/src/VuFind/Controller/EITController.php
index 0f28bc22eb461a7083602c72470ad40045e6769d..25c63320187c3c2c770a4b9a0d818815badf7967 100644
--- a/module/VuFind/src/VuFind/Controller/EITController.php
+++ b/module/VuFind/src/VuFind/Controller/EITController.php
@@ -43,6 +43,7 @@ class EITController extends AbstractSearch
      */
     public function __construct()
     {
+        $this->accessPermission = 'access.EITModule';
         $this->searchClassId = 'EIT';
         parent::__construct();
     }
@@ -77,14 +78,6 @@ class EITController extends AbstractSearch
      */
     public function searchAction()
     {
-        // We currently restrict EIT to logged in users.
-        // TODO: make this configurable, similar to what is found in
-        // \VuFind\Search\Factory\SummonBackendFactory::isAuthed().
-        $account = $this->getAuthManager();
-        if ($account->isLoggedIn() == false) {
-            return $this->forceLogin();
-        }
         return $this->resultsAction();
     }
-}
-
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Controller/EITrecordController.php b/module/VuFind/src/VuFind/Controller/EITrecordController.php
index de2e0b7351b60471cef379299861606c99331226..49a82660b44ae7d92e5f140b503efc9b3222b048 100644
--- a/module/VuFind/src/VuFind/Controller/EITrecordController.php
+++ b/module/VuFind/src/VuFind/Controller/EITrecordController.php
@@ -49,6 +49,7 @@ class EITrecordController extends AbstractRecord
     public function __construct()
     {
         // Override some defaults:
+        $this->accessPermission = 'access.EITModule';
         $this->searchClassId = 'EIT';
         $this->defaultTab = 'Description';
 
diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php
index 583f12f02a254733b091f07224132d3121e9f84f..f2f3d4dfbfb36b7a3b23e14a0ab1af3003ede929 100644
--- a/module/VuFind/src/VuFind/Db/Row/User.php
+++ b/module/VuFind/src/VuFind/Db/Row/User.php
@@ -42,7 +42,8 @@ use Zend\Db\Sql\Expression,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     http://vufind.org   Main Site
  */
-class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface
+class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface,
+    \ZfcRbac\Identity\IdentityInterface
 {
     use \VuFind\Db\Table\DbTableAwareTrait;
 
@@ -436,4 +437,14 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface
         ) . (time() % pow(10, 10));
         return $this->save();
     }
+
+    /**
+     * Get the list of roles of this identity
+     *
+     * @return string[]|\Rbac\Role\RoleInterface[]
+     */
+    public function getRoles()
+    {
+        return array('loggedin');
+    }
 }
diff --git a/module/VuFind/src/VuFind/Role/DynamicRoleProvider.php b/module/VuFind/src/VuFind/Role/DynamicRoleProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..c7ad23371b04e1a5ac340e049179343577616667
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/DynamicRoleProvider.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * VuFind dynamic role provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role;
+use ZfcRbac\Role\RoleProviderInterface;
+use Rbac\Role\Role;
+
+/**
+ * VuFind dynamic role provider.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class DynamicRoleProvider implements RoleProviderInterface
+{
+    /**
+     * Cache of role objects.
+     *
+     * @var array
+     */
+    protected $roles = false;
+
+    /**
+     * Permission provider manager
+     *
+     * @var PermissionProviderPluginManager
+     */
+    protected $manager;
+
+    /**
+     * Configuration for determining permissions.
+     *
+     * @var array
+     */
+    protected $config;
+
+    /**
+     * Constructor
+     *
+     * @param PermissionProvider\PluginManager $manager Permission provider manager
+     * @param array                            $config  Configuration for determining
+     * permissions
+     */
+    public function __construct(PermissionProvider\PluginManager $manager,
+        array $config
+    ) {
+        $this->manager = $manager;
+        $this->config = $config;
+    }
+
+    /**
+     * Get the roles from the provider
+     *
+     * @param  string[] $roleNames Role(s) to look up.
+     *
+     * @return \Rbac\Role\RoleInterface[]
+     */
+    public function getRoles(array $roleNames)
+    {
+        return array_map(array($this, 'getRole'), $roleNames);
+    }
+
+    /**
+     * Get a role object by name.
+     *
+     * @param string $name Role name
+     *
+     * @return Role
+     */
+    protected function getRole($name)
+    {
+        // Retrieve permissions from providers if not already done:
+        if (false === $this->roles) {
+            $this->populateRoles();
+        }
+
+        // Create role object if missing:
+        if (!isset($this->roles[$name])) {
+            $this->roles[$name] = new Role($name);
+        }
+
+        return $this->roles[$name];
+    }
+
+    /**
+     * Populate the internal role array.
+     *
+     * @return void
+     */
+    protected function populateRoles()
+    {
+        // Reset internal role array:
+        $this->roles = array();
+
+        // Map permission configuration to the expected output format.
+        foreach ($this->getPermissionsArray() as $roleName => $permissionArr) {
+            $role = $this->getRole($roleName);
+            foreach ($permissionArr as $permission) {
+                $role->addPermission($permission);
+            }
+        }
+    }
+
+    /**
+     * Get an associative array of role name => permissions using the provided
+     * configuration.
+     *
+     * @return array
+     */
+    protected function getPermissionsArray()
+    {
+        // Loop through all of the permissions:
+        $retVal = [];
+        foreach ($this->config as $settings) {
+            $current = $this->getRolesForSettings($settings);
+            foreach ($current['roles'] as $role) {
+                if (!isset($retVal[$role])) {
+                    $retVal[$role] = [];
+                }
+                foreach ($current['permissions'] as $permission) {
+                    $retVal[$role][] = $permission;
+                }
+            }
+        }
+        return $retVal;
+    }
+
+    /**
+     * Given a settings array, return the appropriate roles.
+     *
+     * @param array $settings Settings for finding roles that allow a permission
+     *
+     * @return array
+     */
+    protected function getRolesForSettings($settings)
+    {
+        // Extract require setting:
+        if (isset($settings['require'])) {
+            $mode = strtoupper(trim($settings['require']));
+            unset($settings['require']);
+        } else {
+            $mode = 'ALL';
+        }
+
+        // Extract permission setting:
+        $permissions = isset($settings['permission'])
+            ? (array)$settings['permission'] : [];
+        unset($settings['permission']);
+
+        // Process everything:
+        $roles = null;
+        foreach ($settings as $provider => $options) {
+            $providerObj = $this->manager->get($provider);
+            $currentRoles = $providerObj->getPermissions($options);
+            if ($roles === null) {
+                $roles = $currentRoles;
+            } else if ($mode == 'ANY') {
+                $roles = array_merge($roles, $currentRoles);
+            } else {
+                $roles = array_intersect($roles, $currentRoles);
+            }
+        }
+        return compact('permissions', 'roles');
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php b/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..623880becc0e9f97256b798b919c6cd7ce9442f8
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php
@@ -0,0 +1,191 @@
+<?php
+/**
+ * VuFind dynamic role provider factory.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role;
+use Zend\ServiceManager\Config;
+use Zend\ServiceManager\FactoryInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * VuFind dynamic role provider factory.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class DynamicRoleProviderFactory implements FactoryInterface
+{
+    /**
+     * Create the service.
+     *
+     * @param ServiceLocatorInterface $serviceLocator Service locator
+     *
+     * @return DynamicRoleProvider
+     */
+    public function createService(ServiceLocatorInterface $serviceLocator)
+    {
+        $config = $serviceLocator->getServiceLocator()->get('config');
+        $rbacConfig = $config['zfc_rbac'];
+        return new DynamicRoleProvider(
+            $this->getPermissionProviderPluginManager($serviceLocator, $rbacConfig),
+            $this->getPermissionConfiguration($serviceLocator, $rbacConfig)
+        );
+    }
+
+    /**
+     * Create the supporting plugin manager.
+     *
+     * @param ServiceLocatorInterface $serviceLocator Service locator
+     * @param array $rbacConfig ZfcRbac configuration
+     *
+     * @return PermissionProviderPluginManager
+     */
+    protected function getPermissionProviderPluginManager(
+        ServiceLocatorInterface $serviceLocator, array $rbacConfig
+    ) {
+        $pm = new PermissionProvider\PluginManager(
+            new Config($rbacConfig['vufind_permission_provider_manager'])
+        );
+        $pm->setServiceLocator($serviceLocator->getServiceLocator());
+        return $pm;
+    }
+
+    /**
+     * Get a configuration array.
+     *
+     * @param ServiceLocatorInterface $serviceLocator Service locator
+     * @param array $rbacConfig ZfcRbac configuration
+     *
+     * @return array
+     */
+    protected function getPermissionConfiguration(
+        ServiceLocatorInterface $serviceLocator, array $rbacConfig
+    ) {
+        // Get role provider settings from the ZfcRbac configuration:
+        $config = $rbacConfig['role_provider']['VuFind\Role\DynamicRoleProvider'];
+
+        // Load the permissions:
+        $configLoader = $serviceLocator->getServiceLocator()->get('VuFind\Config');
+        $permissions = $configLoader->get('permissions')->toArray();
+
+        // If we're configured to map legacy settings, do so now:
+        if (isset($config['map_legacy_settings'])
+            && $config['map_legacy_settings']
+        ) {
+            $permissions = $this->addLegacySettings($configLoader, $permissions);
+        }
+
+        return $permissions;
+    }
+
+    /**
+     * Map legacy VuFind settings into the permissions.ini setup.
+     *
+     * @param \VuFind\Config\PluginManager $loader      Config loader
+     * @param array                        $permissions Permissions to update
+     *
+     * @return array
+     */
+    protected function addLegacySettings(\VuFind\Config\PluginManager $loader,
+        array $permissions
+    ) {
+        // Add admin settings if they are absent:
+        if (!$this->permissionDefined($permissions, 'access.AdminModule')) {
+            $config = $loader->get('config')->toArray();
+            $permissions['legacy.AdminModule'] = [];
+            if (isset($config['AdminAuth']['ipRegEx'])) {
+                $permissions['legacy.AdminModule']['ipRegEx']
+                    = $config['AdminAuth']['ipRegEx'];
+            }
+            if (isset($config['AdminAuth']['userWhitelist'])) {
+                $permissions['legacy.AdminModule']['username']
+                    = $config['AdminAuth']['userWhitelist'];
+            }
+            // If no settings exist in config.ini, we grant access to everyone
+            // by allowing both logged-in and logged-out roles.
+            if (empty($permissions['legacy.AdminModule'])) {
+                $permissions['legacy.AdminModule']['role'] = ['guest', 'loggedin'];
+            }
+            $permissions['legacy.AdminModule']['permission'] = 'access.AdminModule';
+        }
+
+        // Add EIT settings if they are absent:
+        if (!$this->permissionDefined($permissions, 'access.EITModule')) {
+            $permissions['legacy.EITModule'] = [
+                'role' => 'loggedin',
+                'permission' => 'access.EITModule',
+            ];
+        }
+
+        // Add Summon settings if they are absent:
+        // Check based on login status
+        $defined = $this
+            ->permissionDefined($permissions, 'access.SummonExtendedResults');
+        if (!$defined) {
+            $config = $loader->get('Summon');
+            $permissions['legacy.SummonExtendedResults'] = [];
+            if (isset($config->Auth->check_login) && $config->Auth->check_login) {
+                $permissions['legacy.SummonExtendedResults']['role'] = ['loggedin'];
+            }
+            if (isset($config->Auth->ip_range)) {
+                $permissions['legacy.SummonExtendedResults']['ipRegEx']
+                    = $config->Auth->ip_range;
+            }
+            if (!empty($permissions['legacy.SummonExtendedResults'])) {
+                $permissions['legacy.SummonExtendedResults']['boolean'] = 'OR';
+                $permissions['legacy.SummonExtendedResults']['permission']
+                    = 'access.SummonExtendedResults';
+            } else {
+                unset($permissions['legacy.SummonExtendedResults']);
+            }
+        }
+
+        return $permissions;
+    }
+
+    /**
+     * Is the specified permission already defined in the provided configuration?
+     *
+     * @param array  $config     Configuration
+     * @param string $permission Permission to check
+     *
+     * @return bool
+     */
+    protected function permissionDefined(array $config, $permission)
+    {
+        foreach ($config as $current) {
+            if (isset($current['permission'])
+                && in_array($permission, (array)$current['permission'])
+            ) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/Factory.php b/module/VuFind/src/VuFind/Role/PermissionProvider/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..87a1af81e60650f4b0df3d949f25dc3a441034a1
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/Factory.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Permission Provider Factory Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:hierarchy_components Wiki
+ */
+namespace VuFind\Role\PermissionProvider;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Permission Provider Factory Class
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:hierarchy_components Wiki
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Factory for IpRange
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return IpRange
+     */
+    public static function getIpRange(ServiceManager $sm)
+    {
+        return new IpRange($sm->getServiceLocator()->get('Request'));
+    }
+
+    /**
+     * Factory for IpRegEx
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return IpRegEx
+     */
+    public static function getIpRegEx(ServiceManager $sm)
+    {
+        return new IpRegEx($sm->getServiceLocator()->get('Request'));
+    }
+
+    /**
+     * Factory for Username
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return Username
+     */
+    public static function getUsername(ServiceManager $sm)
+    {
+        return new Username(
+            $sm->getServiceLocator()->get('ZfcRbac\Service\AuthorizationService')
+        );
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/IpRange.php b/module/VuFind/src/VuFind/Role/PermissionProvider/IpRange.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4d081959b7c78ac0c1afaa6ac71ae24c9dfceab
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/IpRange.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * IpRange permission provider for VuFind.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role\PermissionProvider;
+use Zend\Http\PhpEnvironment\Request;
+
+/**
+ * IpRange permission provider for VuFind.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class IpRange implements PermissionProviderInterface
+{
+    /**
+     * Request object
+     *
+     * @var Request
+     */
+    protected $request;
+
+    /**
+     * Constructor
+     *
+     * @param Request              $request       Request object
+     */
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+    }
+
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options)
+    {
+        // Check if any regex matches....
+        $ip = $this->request->getServer()->get('REMOTE_ADDR');
+        if (checkIP($ip, $options)) {
+            // Match? Grant to all users (guest or logged in).
+            return ['guest', 'loggedin'];
+        }
+
+        //  No match? No permissions.
+        return [];
+    }
+
+   /**
+    * Return true or false
+    *
+    * @param ip adress 		$remoteIP 	ip adress of the user
+    * @param array 		$rangeIP 	ip and ranges of adresses
+    *
+    * @return boolean
+    */
+   // ToDo: Implementin IPv6 check
+   private function checkIP($remoteIP, $rangeIP) {
+        $mylist = array();
+        $count = 0;
+        $inList = false;
+        foreach ((array)$rangeIP as $range) {
+            if (preg_match('/-/',$range)) {
+                $tmp=preg_split('/-/',$range);
+                $mylist[$count]["start"]=$tmp[0];
+                $mylist[$count]["end"]=$tmp[1];
+            } else {
+                $mylist[$count]["start"]=$range;
+                $mylist[$count]["end"]=$range;
+            }
+            $count++;
+        }
+        foreach ($mylist as $check) {
+            if (ip2long($remoteIP) >= ip2long($check["start"]) && ip2long($remoteIP) <= ip2long($check["end"])) {
+                $inList=true;
+            }
+        }
+        return $inList;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/IpRegEx.php b/module/VuFind/src/VuFind/Role/PermissionProvider/IpRegEx.php
new file mode 100644
index 0000000000000000000000000000000000000000..a99c02fdaf8b1890c04ae84e9a175bb77d0ee819
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/IpRegEx.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * IpRegEx permission provider for VuFind.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role\PermissionProvider;
+use Zend\Http\PhpEnvironment\Request;
+
+/**
+ * IpRegEx permission provider for VuFind.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class IpRegEx implements PermissionProviderInterface
+{
+    /**
+     * Request object
+     *
+     * @var Request
+     */
+    protected $request;
+
+    /**
+     * Constructor
+     *
+     * @param Request              $request       Request object
+     */
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+    }
+
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options)
+    {
+        // Check if any regex matches....
+        $ip = $this->request->getServer()->get('REMOTE_ADDR');
+        foreach ((array)$options as $current) {
+            if (preg_match($current, $ip)) {
+                // Match? Grant to all users (guest or logged in).
+                return ['guest', 'loggedin'];
+            }
+        }
+
+        //  No match? No permissions.
+        return [];
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/PermissionProviderInterface.php b/module/VuFind/src/VuFind/Role/PermissionProvider/PermissionProviderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..25bea165376590644f6b800341210b0e646a32f8
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/PermissionProviderInterface.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Permission provider interface
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_a_related_record_module Wiki
+ */
+namespace VuFind\Role\PermissionProvider;
+
+/**
+ * Permission provider interface
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_a_related_record_module Wiki
+ */
+interface PermissionProviderInterface
+{
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options);
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/PluginManager.php b/module/VuFind/src/VuFind/Role/PermissionProvider/PluginManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..a4230ca1d6946a05cf30dcb891e573ded0c255f4
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/PluginManager.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Permission provider plugin manager
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_a_related_record_module Wiki
+ */
+namespace VuFind\Role\PermissionProvider;
+
+/**
+ * Permission provider plugin manager
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:building_a_related_record_module Wiki
+ */
+class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
+{
+    /**
+     * Return the name of the base class or interface that plug-ins must conform
+     * to.
+     *
+     * @return string
+     */
+    protected function getExpectedInterface()
+    {
+        return 'VuFind\Role\PermissionProvider\PermissionProviderInterface';
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/Role.php b/module/VuFind/src/VuFind/Role/PermissionProvider/Role.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8dd1159971e668b01f35616bbf13f575c5d4bb0
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/Role.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Role permission provider for VuFind.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role\PermissionProvider;
+
+/**
+ * Role permission provider for VuFind.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class Role implements PermissionProviderInterface
+{
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options)
+    {
+        // We should be receiving a role string or an array of roles; we should
+        // simply normalize it to an array and send it back.
+        return (array)$options;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/Username.php b/module/VuFind/src/VuFind/Role/PermissionProvider/Username.php
new file mode 100644
index 0000000000000000000000000000000000000000..d78a91981f2caefa82367dc5fad52a6258a4467b
--- /dev/null
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/Username.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Username permission provider for VuFind.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2007.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+namespace VuFind\Role\PermissionProvider;
+use ZfcRbac\Service\AuthorizationService;
+
+/**
+ * Username permission provider for VuFind.
+ *
+ * @category VuFind2
+ * @package  Authorization
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://www.vufind.org  Main Page
+ */
+class Username implements PermissionProviderInterface
+{
+    /**
+     * Authorization object
+     *
+     * @var AuthorizationService
+     */
+    protected $auth;
+
+    /**
+     * Constructor
+     *
+     * @param AuthorizationService $authorization Authorization service
+     */
+    public function __construct(AuthorizationService $authorization)
+    {
+        $this->auth = $authorization;
+    }
+
+    /**
+     * Return an array of roles which may be granted the permission based on
+     * the options.
+     *
+     * @param mixed $options Options provided from configuration.
+     *
+     * @return array
+     */
+    public function getPermissions($options)
+    {
+        // If no user is logged in, or the user doesn't match the passed-in
+        // whitelist, we can't grant the permission to any roles.
+        $user = $this->auth->getIdentity();
+        if (!$user || !in_array($user->username, (array)$options)) {
+            return [];
+        }
+
+        // If we got this far, we can grant the permission to the loggedin role.
+        return ['loggedin'];
+    }
+}
diff --git a/module/VuFind/src/VuFind/Search/Factory/SummonBackendFactory.php b/module/VuFind/src/VuFind/Search/Factory/SummonBackendFactory.php
index fcbf90ab66aafe09c5f52d9b827ced1b947fc325..b6e439e0b624f59731c26066535e94e4a89baf36 100644
--- a/module/VuFind/src/VuFind/Search/Factory/SummonBackendFactory.php
+++ b/module/VuFind/src/VuFind/Search/Factory/SummonBackendFactory.php
@@ -146,35 +146,8 @@ class SummonBackendFactory implements FactoryInterface
      */
     protected function isAuthed()
     {
-        // Check based on login status
-        if (isset($this->summonConfig->Auth->check_login)
-            && $this->summonConfig->Auth->check_login
-        ) {
-            $authManager = $this->serviceLocator->get('VuFind\AuthManager');
-            if ($authManager->isLoggedIn()) {
-                return true;
-            }
-        }
-
-        // Check based on IP range
-        if (isset($this->summonConfig->Auth->ip_range)) {
-            $request = $this->serviceLocator->get('Request');
-            $match = preg_match(
-                $this->summonConfig->Auth->ip_range,
-                $request->getServer()->get('REMOTE_ADDR')
-            );
-            if ($match === false) {
-                throw new \Exception(
-                    'Bad regular expression in Summon.ini [Auth] ip_range setting.'
-                );
-            }
-            if ($match) {
-                return true;
-            }
-        }
-
-        // If we got this far, we're not authenticated.
-        return false;
+        return $this->serviceLocator->get('ZfcRbac\Service\AuthorizationService')
+            ->isGranted('access.SummonExtendedResults');
     }
 
     /**
diff --git a/module/VuFind/tests/fixtures/configs/permissions/Summon.ini b/module/VuFind/tests/fixtures/configs/permissions/Summon.ini
new file mode 100644
index 0000000000000000000000000000000000000000..c869f53227a63483dcb5b04a060adae3bd03a9db
--- /dev/null
+++ b/module/VuFind/tests/fixtures/configs/permissions/Summon.ini
@@ -0,0 +1,3 @@
+[Auth]
+ip_range = "/1\.2\.3\.4|1\.2\.3\.5/"
+check_login = true
\ No newline at end of file
diff --git a/module/VuFind/tests/fixtures/configs/permissions/config.ini b/module/VuFind/tests/fixtures/configs/permissions/config.ini
new file mode 100644
index 0000000000000000000000000000000000000000..06718d6b570df235d7a8ccf7536c592657908ccc
--- /dev/null
+++ b/module/VuFind/tests/fixtures/configs/permissions/config.ini
@@ -0,0 +1,7 @@
+[AdminAuth]
+ipRegEx = "/1\.2\.3\.4|1\.2\.3\.5/"
+userWhitelist[] = username1
+userWhitelist[] = username2
+
+[Summon]
+apiKey = fake
\ No newline at end of file
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
index 2b3bf4fc01bff1ec6bb2ea005718f437a8761d80..87a86e2156f174a690434a1aba0c18b5e9a523b9 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
@@ -259,6 +259,42 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
         );
     }
 
+    /**
+     * Test permission upgrade
+     *
+     * @return void
+     */
+    public function testPermissionUpgrade()
+    {
+        $upgrader = $this->getUpgrader('permissions');
+        $upgrader->run();
+        $results = $upgrader->getNewConfigs();
+        $this->assertFalse(isset($results['config.ini']['AdminAuth']));
+        $this->assertFalse(isset($results['Summon.ini']['Auth']));
+        $adminConfig = [
+            'ipRegEx' => '/1\.2\.3\.4|1\.2\.3\.5/',
+            'username' => ['username1', 'username2'],
+            'permission' => 'access.AdminModule'
+        ];
+        $this->assertEquals(
+            $adminConfig, $results['permissions.ini']['access.AdminModule']
+        );
+        $summonConfig = [
+            'role' => ['loggedin'],
+            'ipRegEx' => '/1\.2\.3\.4|1\.2\.3\.5/',
+            'boolean' => 'OR',
+            'permission' => 'access.SummonExtendedResults'
+        ];
+        $this->assertEquals(
+            $summonConfig,
+            $results['permissions.ini']['access.SummonExtendedResults']
+        );
+        $eitConfig = ['role' => 'loggedin', 'permission' => 'access.EITModule'];
+        $this->assertEquals(
+            $eitConfig, $results['permissions.ini']['default.EITModule']
+        );
+    }
+
     /**
      * Test Google-related warnings.
      *
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd295a51c355e9c6522b8283dd30b7b642136fff
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Dynamic Role Provider Test Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
+ */
+namespace VuFindTest\Role;
+use VuFind\Role\DynamicRoleProvider, VuFind\Role\PermissionProvider\PluginManager;
+
+/**
+ * Dynamic Role Provider Test Class
+ *
+ * @category VuFind2
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
+ */
+class DynamicRoleProviderTest extends \VuFindTest\Unit\TestCase
+{
+    /**
+     * Test that configurations get processed correctly
+     *
+     * @return void
+     */
+    public function testConfiguration()
+    {
+        $config = [
+            'testRequireAny' => [
+                'require' => 'any',
+                'a' => 'foo',
+                'b' => 'bar',
+                'permission' => 'perm1',
+            ],
+            'testRequireAll' => [
+                'require' => 'all',
+                'a' => 'foo',
+                'b' => 'bar',
+                'permission' => 'perm2',
+            ],
+            'testAcceptArray' => [
+                'c' => [1, 2, 3],
+                'permission' => 'perm3',
+            ],
+        ];
+        $pm = $this->getFakePluginManager();
+        $pm->get('a')->expects($this->any())->method('getPermissions')->with($this->equalTo('foo'))->will($this->returnValue([]));
+        $pm->get('b')->expects($this->any())->method('getPermissions')->with($this->equalTo('bar'))->will($this->returnValue(['role']));
+        $pm->get('c')->expects($this->any())->method('getPermissions')->with($this->equalTo([1, 2, 3]))->will($this->returnValue(['role']));
+        $result = $this->getDynamicRoleProvider($pm, $config)->getRoles(['role']);
+        $this->assertEquals(1, count($result));
+        $this->assertEquals('role', $result[0]->getName());
+        $this->assertTrue($result[0]->hasPermission('perm1'));
+        $this->assertFalse($result[0]->hasPermission('perm2'));
+        $this->assertTrue($result[0]->hasPermission('perm3'));
+    }
+
+    /**
+     * Get the DynamicRoleProvider to test.
+     *
+     * @param PluginManager $pluginManager Permission provider plugin manager
+     * @param array         $config        Configuration
+     *
+     * @return DynamicRoleProvider
+     */
+    protected function getDynamicRoleProvider($pluginManager = null, $config = [])
+    {
+        if (null === $pluginManager) {
+            $pluginManager = $this->getFakePluginManager();
+        }
+        return new DynamicRoleProvider($pluginManager, $config);
+    }
+
+    /**
+     * Get a plugin manager populated with fake services to test.
+     *
+     * @return PluginManager
+     */
+    protected function getFakePluginManager()
+    {
+        $pm = new PluginManager();
+        foreach (['a', 'b', 'c'] as $name) {
+            $pm->setService($name, $this->getMock('VuFind\Role\PermissionProvider\PermissionProviderInterface'));
+        }
+        return $pm;
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/PluginManagerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/PluginManagerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7c5a2c16d64ea40aa5c64245b91dab37e5a46d60
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/PermissionProvider/PluginManagerTest.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * PermissionProvider Plugin Manager Test Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
+ */
+namespace VuFindTest\Role\PermissionProvider;
+use VuFind\Role\PermissionProvider\PluginManager;
+
+/**
+ * PermissionProvider Plugin Manager Test Class
+ *
+ * @category VuFind2
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/vufind2:unit_tests Wiki
+ */
+class PluginManagerTest extends \VuFindTest\Unit\TestCase
+{
+    /**
+     * Test results.
+     *
+     * @return void
+     */
+    public function testShareByDefault()
+    {
+        $pm = new PluginManager(null);
+        $this->assertTrue($pm->shareByDefault());
+    }
+
+    /**
+     * Test expected interface.
+     *
+     * @return void
+     * @expectedException Zend\ServiceManager\Exception\RuntimeException
+     * @expectedExceptionMessage Plugin ArrayObject does not belong to VuFind\Role\PermissionProvider\PermissionProviderInterface
+     */
+    public function testExpectedInterface()
+    {
+        $pm = new PluginManager(null);
+        $pm->validatePlugin(new \ArrayObject());
+    }
+}
\ No newline at end of file
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
index 3b5bdaeb72cb02daf645f328f9ac02b7f6508e41..d22a6274ecf6ef2785e80103237f66f5cfb11a89 100644
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
@@ -26,9 +26,7 @@
  * @link     http://www.vufind.org  Main Page
  */
 namespace VuFindAdmin\Controller;
-use VuFind\Exception\Forbidden as ForbiddenException,
-    Zend\Mvc\MvcEvent,
-    Zend\Stdlib\Parameters;
+use Zend\Mvc\MvcEvent;
 
 /**
  * VuFind Admin Controller Base
@@ -41,6 +39,15 @@ use VuFind\Exception\Forbidden as ForbiddenException,
  */
 class AbstractAdmin extends \VuFind\Controller\AbstractBase
 {
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->accessPermission = 'access.AdminModule';
+    }
+
     /**
      * preDispatch -- block access when appropriate.
      *
@@ -69,49 +76,10 @@ class AbstractAdmin extends \VuFind\Controller\AbstractBase
             return $redirectPlugin->toRoute('admin/disabled');
         }
 
-        // Block access by IP when IP checking is enabled:
-        if (isset($config->AdminAuth->ipRegEx)) {
-            $ipMatch = preg_match(
-                $config->AdminAuth->ipRegEx,
-                $this->getRequest()->getServer()->get('REMOTE_ADDR')
-            );
-            if (!$ipMatch) {
-                throw new ForbiddenException('Access denied.');
-            }
-        }
-
-        // Block access by username when user whitelist is enabled:
-        if (isset($config->AdminAuth->userWhitelist)) {
-            $user = $this->getUser();
-            if ($user == false) {
-                $e->setResponse($this->forceLogin(null, array(), false));
-                return;
-            }
-            $matchFound = false;
-            foreach ($config->AdminAuth->userWhitelist as $check) {
-                if ($check == $user->username) {
-                    $matchFound = true;
-                    break;
-                }
-            }
-            if (!$matchFound) {
-                throw new ForbiddenException('Access denied.');
-            }
-        }
+        // Call parent method to do permission checking:
+        parent::preDispatch($e);
     }
 
-    /**
-     * Register the default events for this controller
-     *
-     * @return void
-     */
-    protected function attachDefaultListeners()
-    {
-        parent::attachDefaultListeners();
-        $events = $this->getEventManager();
-        $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 1000);
-    }
-    
     /**
      * Display disabled message.
      *