The default user management implementation stores user/group information in the content repository. In contrast to Jackrabbit 2.x, which by default used a single, dedicated workspace for user/group data, this data will as of Oak 1.0 be stored separately for each JCR workspace.
Consequently the UserManager associated with the editing sessions, performs all actions with this editing session. This corresponds to the behavior as defined the alternative implementation present with Jackrabbit 2.x ((see Jackrabbit 2.x UserPerWorkspaceUserManager).
A summary of all changes with respect to the former implementation present with Jackrabbit 2.x is present in the corresponding section.
The setup of builtin user and group accounts is triggered by the configured WorkspaceInitializer associated with the user management configuration (see Configuration section below).
The default user management implementation in OAK comes with an initializer that creates the following builtin user accounts:
The admin user is always being created. The ID of this user is retrieved from the user configuration parameter PARAM_ADMIN_ID, which defaults to admin.
As of OAK 1.0 however the administrator user might be created without initial password forcing the application to set the password upon start (see PARAM_OMIT_ADMIN_PW configuration parameter).
In contrast to Jackrabbit 2.x the anonymous (or guest) user is optional. Creation will be skipped if the value of the PARAM_ANONYMOUS_ID configuration parameter is null or empty.
Note, that the anonymous user will always be created without specifying a password in order to prevent regular login with SimpleCredentials. The proper way to obtain a guest session is:
Repository#login(new GuestCredentials(), wspName);
See section Authentication for further information about guest login.
The default user management implementation in Oak contains special handling for the optional group that represents the everyone principal, which is marked by the reserved principal name and by definition has all other principals as members.
This special group always contains all users/groups as member and cannot be edited with user management API. As of OAK this fact is consistently reflected in all group membership related methods. See also Principal Management.
Oak 1.0 comes with a default XPATH based implementation of the QueryBuilder interface which is passed to the query upon calling UserManager#findAuthorizables(Query).
See section Group Membership for details.
Due to the nature of the UserManager (see above) we decided to drop the auto-save behavior in the default implementation present with OAK. Consequently,
See also PARAM_SUPPORT_AUTOSAVE below; while this should not be needed if application code has been written against the Jackrabbit API (and thus testing if auto-save mode is enabled or not) this configuration option can be used as last resort.
As of Oak 1.0 user and group nodes can be imported both with Session and Workspace import. Other differences compared to Jackrabbit 2.x:
Since Oak 1.1.0 the default user management and authentication implementation provides password expiry and initial password change.
By default these features are disabled. See section Password Expiry and Force Initial Password Change for details.
Since Oak 1.3.3 the default user management implementation provides password history support. By default this feature is disabled.
See section Password History for details.
The following block lists the built-in node types related to user management tasks:
[rep:Authorizable] > mix:referenceable, nt:hierarchyNode abstract + * (nt:base) = nt:unstructured VERSION - rep:principalName (STRING) protected mandatory - rep:authorizableId (STRING) protected /* @since oak 1.0 */ - * (UNDEFINED) - * (UNDEFINED) multiple [rep:User] > rep:Authorizable, rep:Impersonatable + rep:pwd (rep:Password) = rep:Password protected /* @since oak 1.1.0 */ - rep:password (STRING) protected - rep:disabled (STRING) protected [rep:SystemUser] > rep:User /* @since oak 1.1.0 */ [rep:Impersonatable] mixin - rep:impersonators (STRING) protected multiple /* @since oak 1.1.0 */ [rep:Password] - * (UNDEFINED) protected - * (UNDEFINED) protected multiple [rep:Group] > rep:Authorizable, rep:MemberReferences + rep:members (rep:Members) = rep:Members multiple protected VERSION /* @deprecated since oak 1.0 */ + rep:membersList (rep:MemberReferencesList) = rep:MemberReferencesList protected COPY /* @since oak 1.0 */ [rep:AuthorizableFolder] > nt:hierarchyNode + * (rep:Authorizable) = rep:User VERSION + * (rep:AuthorizableFolder) = rep:AuthorizableFolder VERSION /* @since oak 1.0 */ [rep:MemberReferences] - rep:members (WEAKREFERENCE) protected multiple < 'rep:Authorizable' /* @since oak 1.0 */ [rep:MemberReferencesList] + * (rep:MemberReferences) = rep:MemberReferences protected COPY /* @deprecated since oak 1.0 */ [rep:Members] orderable + * (rep:Members) = rep:Members protected multiple - * (WEAKREFERENCE) protected < 'rep:Authorizable'
The consistency of this content structure is asserted by a dedicated UserValidator. The corresponding errors are all of type Constraint with the following codes:
Code | Message |
---|---|
0020 | Admin user cannot be disabled |
0021 | Invalid jcr:uuid for authorizable (creation) |
0022 | Changing Id, principal name after creation |
0023 | Invalid jcr:uuid for authorizable (mod) |
0024 | Password may not be plain text |
0025 | Attempt to remove id, principalname or pw |
0026 | Mandatory property rep:principalName missing |
0027 | The admin user cannot be removed |
0028 | Attempt to create outside of configured scope |
0029 | Intermediate folders not rep:AuthorizableFolder |
0030 | Missing uuid for group (check for cyclic membership) |
0032 | Attempt to set password with system user |
0033 | Attempt to add rep:pwd node to a system user |
The following user management specific methods are present with the UserConfiguration as of OAK 1.0:
Parameter | Type | Default |
---|---|---|
PARAM_ADMIN_ID | String | “admin” |
PARAM_OMIT_ADMIN_PW | boolean | false |
PARAM_ANONYMOUS_ID | String | “anonymous” (nullable) |
PARAM_USER_PATH | String | “/rep:security/rep:authorizables/rep:users” |
PARAM_GROUP_PATH | String | “/rep:security/rep:authorizables/rep:groups” |
PARAM_DEFAULT_DEPTH | int | 2 |
PARAM_PASSWORD_HASH_ALGORITHM | String | “SHA-256” |
PARAM_PASSWORD_HASH_ITERATIONS | int | 1000 |
PARAM_PASSWORD_SALT_SIZE | int | 8 |
PARAM_AUTHORIZABLE_NODE_NAME | AuthorizableNodeName | AuthorizableNodeName#DEFAULT |
PARAM_AUTHORIZABLE_ACTION_PROVIDER | AuthorizableActionProvider | DefaultAuthorizableActionProvider |
PARAM_SUPPORT_AUTOSAVE | boolean | false |
PARAM_IMPORT_BEHAVIOR | String (“abort”, “ignore”, “besteffort”) | “ignore” |
PARAM_PASSWORD_MAX_AGE | int | 0 |
PARAM_PASSWORD_INITIAL_CHANGE | boolean | false |
PARAM_PASSWORD_HISTORY_SIZE | int (upper limit: 1000) | 0 |
PARAM_CACHE_EXPIRATION | long | 0 |
PARAM_ENABLE_RFC7613_USERCASE_MAPPED_PROFILE | boolean | false |
The following configuration parameters present with the default implementation in Jackrabbit 2.x are no longer supported and will be ignored:
The optional cacheExpiration configuration option listed above is discussed in detail in section Caching Results of Principal Resolution. It is not related to user management s.str. but affects the implementation specific PrincipalProvider implementation exposed by UserConfiguration.getUserPrincipalProvider.
Within the default user management implementation the following parts can be modified or extended at runtime by providing corresponding OSGi services or passing appropriate configuration parameters exposing the custom implementations:
Since Oak 1.1.5 the default user management implementation allows to configure and thus replace the default UserAuthenticationFactory, which links the user management implementation with the authentication (specifically the uid/pw-login) as it exposes the Authentication implementation to be used for verification of the specified credentials according to details provided by a given user management implementation.
@Component() @Service(UserAuthenticationFactory.class) public class MyUserAuthenticationFactory implements UserAuthenticationFactory { private Set<String> ids = Collections.emptySet(); public MyUserAuthenticationFactory() {} //--------------------------------------< UserAuthenticationFactory >--- @Override Authentication getAuthentication(@Nonnull UserConfiguration configuration, @Nonnull Root root, @Nullable String userId) { final boolean canAuthenticate = (userId != null && ids.contains(userId)); return new Authentication() { @Override public boolean authenticate(@Nullable Credentials credentials) { return canAuthenticate; } }; } //------------------------------------------------< SCR Integration >--- @Activate private void activate(Map<String, Object> properties) { ids = ImmutableSet.copyOf(PropertiesUtil.toStringArray(properties.get("ids"), new String[0])); } }