Details
-
Improvement
-
Status: Closed
-
Normal
-
Resolution: Fixed
-
None
-
None
-
None
Description
The new RepositoryAuthenticationProvider is a replacement for the now deprecated JcrAuthenticationProvider and HippoAuthenticationProvider implementations (the latter used to be the default).
Instead of querying and leveraging the brXM security model directly this provider makes use of the now standard feature of HippoSession.getUser().getUserRoles() and based on the configuration can map (some of) them to Role principals.
To implement this more efficiently, the AuthenticationProvider interface is extended with method Set<Role> getRolesByUser(User user), with a default delegation to the now deprecated Set<Role> getRolesByUsername(String username) method.
The RepositoryAuthenticationProvider implements this new method and thereby removes the need to (again) lookup the user data when provided the User object as was returned from the User authenticate(String userName, char [] password) method call. This User object (implementation class TransientUser) namely holds the (detachted) HippoSession SessionUser.
The configuration parameters thereafter used for filtering and mapping the SessionUser.getUserRoles() to Role principals are:
- requiredUserRole(String): when not empty both the authenticate(String, char[]) and getRolesByUser(User) methods will check and require the user to have at least the specified userrole. Default: empty.
- excludedUserRolePrefixes(String): a String of one or more prefixes (delimited by excludedUserRolePrefixesDelimiter(String)) to exclude the userroles which name starts with such prefix(es). When blank or null, no userrole name prefix exclusion will be applied. Default: empty.
- excludedUserRolePrefixesDelimiter(String): the delimiter (string) to split the prefixes provided through excludedUserRolePrefixes(String). Default: "," (comma).
- includedUserRolePrefix(String): the userrole name prefix required for all userroles to be included. When blank or null, all not-yet-excluded userroles will be included. Default: empty.
- stripIncludedUserRolePrefix(boolean): when includedUserRolePrefix(String) is non-empty, strip that prefix from the included userroles when mapping to a Role. Default: true.
- rolePrefix(String): When not empty all included userroles will be mapped to a Role with this prefix to their name. Default: empty.
- defaultRoleName(String): When not empty, adds a predefined Role with this name to the Set<Roles> result from method getRolesByUser(User)
The above configuration parameters all can be set through the following Spring bean (which will become the standard provided setup, later):
<bean id="org.hippoecm.hst.security.AuthenticationProvider" class="org.hippoecm.hst.security.impl.RepositoryAuthenticationProvider"> <meta key="org.hippoecm.hst.site.container.SpringComponentManager.registerCondition" value="config.containsKey('java.security.auth.login.config')" /> <!-- System repository to retrieve roles for user. --> <constructor-arg index="0" ref="javax.jcr.Repository" /> <!-- System repository credentials to retrieve roles for user. --> <constructor-arg index="1" ref="javax.jcr.Credentials.hstconfigreader" /> <!-- User authentication repository against which each user will be authenticated. --> <constructor-arg index="2" ref="javax.jcr.Repository.delegating" /> <property name="requiredUserRole" value="${security.authentication.required.userrole}" /> <property name="excludedUserRolePrefixes" value="${security.authentication.excluded.userrole.prefixes}" /> <property name="excludedUserRolePrefixesDelimiter" value="${security.authentication.excluded.userrole.prefixes.delimiter}" /> <property name="includedUserRolePrefix" value="${security.authentication.included.userrole.prefix}" /> <property name="stripIncludedUserRolePrefix" value="${security.authentication.strip.included.userrole.prefix}" /> <property name="rolePrefix" value="${security.authentication.role.prefix}" /> <!-- Default role to be provided always (if not already provided) --> <property name="defaultRoleName" value="${security.authentication.default.role}" /> </bean>
and the following default hst-config.properties:
### Hippo Login Module Authentication Provider configurations ### # optional required userrole to be allowed to be authenticated security.authentication.required.userrole = # default excluded standard provided userroles (prefixed with xm-) security.authentication.excluded.userrole.prefixes = xm- # , delimiter separating multiple excluded userrole prefixes security.authentication.excluded.userrole.prefixes.delimiter= , # default include only standard provided userroles (prefixed with xm-): effectively by default don't include any! security.authentication.included.userrole.prefix = # by default strip the userrole prefix (if any) from the produced role name security.authentication.strip.included.userrole.prefix = true # prefix to be added to produced role names (default no prefix added) security.authentication.role.prefix = # default role to be added to anyone authenticated (if not already added): to be specified *without* possible role.prefix security.authentication.default.role = everybody
The above default configuration effectively will map no userroles (both excluded and include prefix are by default "xm-"), but will always add/return default Role "everybody".
Therefore to effectively make use of the role mapping (besides the authentication) feature, a project will need to customize/override a few of these configuration properties!
Example usage
In the hippo-testsuite project a (minimal) example setup is used with the following configuration overrides:
security.authentication.required.userrole = hst-site-user security.authentication.included.userrole.prefix = site-
This will require everybody logging in through a site to have at least the userrole hst-site-user assigned, and only will filter/map userroles of the authenticated user to role principals which userrole name starts with "site-"
In the testsuite the following example configuration is used to set this up:
definitions: config: /hippo:configuration/hippo:userroles: /hst-site-user: jcr:primaryType: hipposys:userrole /site-admin: jcr:primaryType: hipposys:userrole /xm-cms-user: hipposys:userroles: operation: add value: [hst-site-user] /hippo:configuration/hippo:users/admin: hipposys:userroles: operation: add value: [site-admin] /hippo:configuration/hippo:groups/admin: hipposys:userroles: operation: add value: [site-admin]
The above yaml bootstrap configuration defines:
- the hst-site-user and site-admin userroles
- allows users with the xm-cms-user userrole to authenticate through the site
- the admin user and admin group users are given the site-admin userrole, which will be mapped to role principal admin
Now, with the above setup, finally HST role security can be used and enforced, for example for access to a specific sitemap item like:
definitions:
config:
/hst:hst/hst:configurations/demosite/hst:sitemap:
jcr:primaryType: hst:sitemap
/mashup:
jcr:primaryType: hst:sitemapitem
hst:authenticated: true
hst:roles: [admin]
The above example sitemap item /mashup will require authentication and only a user with the admin role principal (mapped from the site-admin userrole) will be allowed to access it.
Multi-site use-cases
When a project uses multiple site modules (wars) using/needing separate hst security configuration (e.g. distinct sets of roles and/or required.userrole), each site module can use independent configuration overrides.
For example to use and map distinct sets of userroles per site module, you can define and use a different required userrole like hst-siteA-user and hst-siteB-user, and distinct and mutably exclusive userrole prefixes like siteA- and siteB- to achieve this.