...
Shiro can use multi-realm authentication and authorization - for example, authentication and authorization against a shiro.ini account and an LDAP account and one or more LDAP accounts or against one or more LDAP accounts. Realms can also be grouped together and logical operators used to regulate authentication.
Scope
This article describes multi-realm authentication in detail - example simple configurations showing multi-realm authentication and authorization have already been presented in the Authentication and Authorization - Configuration and LDAP Configuration articles.
...
A Basic Multi-Realm Example
Consider the case of a user account that is registered configured for both the Shiro ini realm and an LDAP realmrealms. An Such a simple example configuration is shown in the listing below. A publicly accessible LDAP server (hosted by here, the server from forumsys.com) is used in this configuration example to allow the configuration to be implemented by 'cut and paste' and a minimum of modification. The LDAP server has
Both the realms in the example have an account with the name 'newton', password 'password' and this account belongs to the group 'scientists'. In the configuration below members of the 'scientists' LDAP group are assigned the (Shiro) 'it_operator' role. The ini realm 'newton' account has been given the same password as the LDAP realm account. newton. In the Shiro ini realm this account is assigned the administrator role and in the LDAP realm it is assigned the it_operator role by way of the realm group roles mapping publicLdapRealm.groupRolesMap = scientists : it_operator
(The newton account is configured as a member of the scientists group on the LDAP server.)
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
[users] newton = $shiro1$SHA-512$500000$wsJJJJ7cbBpoVi0C...JJ5U5pter6Q==,administrator [main] publicLdapRealm = com.sos.auth.shiro.SOSLdapAuthorizingRealm publicLdapRealm.userDnTemplate = uid={0},dc=example,dc=com publicLdapRealm.searchBase = dc=example,dc=com publicLdapRealm.contextFactory.url = ldap://ldap.forumsys.com:389 publicLdapRealm.groupNameAttribute = ou publicLdapRealm.userNameAttribute = uid publicLdapRealm.rolePermissionResolver = $rolePermissionResolver publicLdapRealm.userSearchFilter = (uniqueMember=uid=%s,dc=example,dc=com) publicLdapRealm.groupRolesMap = \ scientists : it_operator, \ mathematicians: all rolePermissionResolver = com.sos.auth.shiro.SOSPermissionResolverAdapter rolePermissionResolver.ini = $iniRealm securityManager.realms = $publicLdapRealm, $iniRealm cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager securityManager.cacheManager = $cacheManager |
Realm Selection
In this the example above:
- If the
securityManager.realms
parameter is specified ( Explicit realm ordering):- The authorization information provided by the user logging in will be only be checked against the realms listed in the
securityManager.realms
parameter. Realms configured in the [main] section but not listed in thesecurityManager.realms
parameter will be ignored. - The authorization information provided by the user logging in will be checked against each realm account in the order in which realms are specified in a the
securityManager.realms
parameter.(explicit ordering). In the example, this would be first thepublicLdapRealm
and then theiniRealm
.
- The authorization information provided by the user logging in will be only be checked against the realms listed in the
- If the
securityManager.realms
parameter had not been specified ( implicit realm ordering):- The authorization information provided by the user logging in would have been checked against each realm account in the order in which realms were listed in the [main] section of the shiro.ini file.(implicit ordering). In the example, this would be first the
iniRealm
and then thepublicLdapRealm
.
- The authorization information provided by the user logging in would have been checked against each realm account in the order in which realms were listed in the [main] section of the shiro.ini file.(implicit ordering). In the example, this would be first the
Note that Explicit and implicit realm ordering is described in more detail in the 'Realm Authentication' section of on the Shiro Authentication web site.
...
By default, Shiro authentication uses the authcStrategy = org.apache.shiro.authc.pam.AtLeastOneSuccessful
strategyAtLeastOneSuccessfulStrategy
. This strategy causes a login to be attempted for all the realms listed in the securityManager.realms
parameter or, if this is not set, in all the realms listen in the shiro.ini configuration file.
Note that roles from the iniRealm
for authenticated LDAP realm user accounts of the same name are always merged to the list of roles, regardless of whether or not the same password is used for both realm accounts.
The roleAssignmentFromIni = false
LDAP realm parameter (default setting is true) can be used to stop this happening, In the example listed above this parameter would then be configured for the publicLdapRealm
as:
publicLdapRealm.
roleAssignmentFromIni = false
Multi-Realm Authentication and Authorization up to Release 1.12.3
However, note the behavior described below if one of the realms configured is the iniRealm
.
The authcStrategy
is configured as follows:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
authcStrategy = org.apache.shiro.authc.pam.AtLeastOneSuccessful
securityManager.authenticator.authenticationStrategy = $authcStrategy |
Authentication and Authorization with the FirstSuccessfulStrategy
configured
The FirstSuccessfulStrategy
strategy is incorrectly implemented in Shiro and Note that the FirstSuccessfulStrategy
strategy is incorrectly implemented and that a login will be attempted for all the realms, even after a successful login has been noted. Login In addition login attempts carried out after a successful login has been noted will be logged at the [error]
level. See issue JOC-437 for more information.
...
A new (SOS) authenticator is included in release 1.12.4 onwards
...
The to replace the default Shiro authenticator can be replaced by one written by the SOS. This authenticator stops the authentication process once a successful login has taken place when the First Successful strategy has been configured.. The SOS authenticator is called configured using the following lines of code:
Code Block | ||
---|---|---|
| ||
authenticator = com.sos.auth.shiro.SOSAuthenticator
securityManager.authenticator=$authenticator
# Please note that you have to assign the realms to the authenticator instead to the securityManager.realms
authenticator.realms = $iniRealm, $ldapRealm
|
The SOS authenticator stops attempting to authenticate when the FirstSuccessfulStrategy
strategy is specified and a successful login has taken place.Note: roles from the iniRealm
for authenticated users are always merged to the list of roles regardless of the strategy specified (This seems to be an error in Shiro.)can be used with all three behavior strategies but it only causes the behavior of the First Successful strategy to be modified,
Passive Authentication and Authorization
When an LDAP realm user account is authenticated and there is an iniRealm
with the same user name but this realm is not listed in the securityManager.realms
parameter, then by default, role(s) configured for the ini realm account will be merged together with those of the LDAP realm account. Note that this will occur regardless of whether or not the same password is used for both realm accounts.
The roleAssignmentFromIni = false
LDAP realm parameter (default setting is true) can be used to suppress this behavior, In the example listed above this parameter would then be configured for the publicLdapRealm as:
publicLdapRealm.
roleAssignmentFromIni = false
Note that this parameter has to be defined for each realm individually.
Anchor | ||||
---|---|---|---|---|
|
The following points apply for a multi-realm environment, where one of the realms is the iniRealm ini realm and when the user accounts have a common name but different passwords:
...
- If the authorization occurs through the ini realm then the user account will only be assigned the roles specified for the ini realm. The LDAP realm(s) will be ignored.
- If the authorization occurs through an LDAP realm then, regardless of whether or not the same password is used in each realm:
- The user account will be assigned the role(s) specified for the account in the (first) authorizing realm.
- The user account will also be assigned the role(s) specified for the account in the ini realm.
- This behavior ensures that a login is possible in the event of problems with the LDAP realm(s).
- The order in which the realms are specified in the
securityManager.realms
parameter is not significant here. - The ldap.roleAssignmentFromIni=false setting (default true) can be used to modify the behavior of the First Successful strategy so that roles from the ini realm are not assigned. See the Suppressing assignment of the ini Realm section below.
Suppressing assignment of the ini Realm
Display feature availability | ||
---|---|---|
|
When the First Successful strategy is used when an ini Realm and one or more LDAP Realms have accounts with common user names and separate passwords, the roles for the ini Realm will be assigned by default when the login is carried out for one of the LDAP Realms. This behavior can be suppressed by setting the roleAssignmentFromIni property to false for the LDAP Realms in the environment. This is shown in the code example below:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
[users]
newton = $shiro1$SHA-512$500000$wsJJJJ7cbBpoVi0C...JJ5U5pter6Q==,administrator
[main]
publicLdapRealm = com.sos.auth.shiro.SOSLdapAuthorizingRealm
publicLdapRealm.userDnTemplate = uid={0},dc=example,dc=com
publicLdapRealm.searchBase = dc=example,dc=com
publicLdapRealm.contextFactory.url = ldap://ldap.forumsys.com:389
publicLdapRealm.groupNameAttribute = ou
publicLdapRealm.userNameAttribute = uid
publicLdapRealm.rolePermissionResolver = $rolePermissionResolver
publicLdapRealm.userSearchFilter = (uniqueMember=uid=%s,dc=example,dc=com)
publicLdapRealm.groupRolesMap = \
scientists : it_operator, \
mathematicians: all
publicLdapRealm.roleAssignmentFromIni = false
rolePermissionResolver = com.sos.auth.shiro.SOSPermissionResolverAdapter
rolePermissionResolver.ini = $iniRealm
authcStrategy = org.apache.shiro.authc.pam.SOSFirstSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
securityManager.realms = $publicLdapRealm, $iniRealm
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager |
With the above configuration:
- When the user name newton is used together with the password for the ini realm then the account will be assigned the administrator role.
- When the user name newton is used together with the password for the LDAP realm then the account will be assigned the it_operator role.
Realm Group/Role Mappings
Display feature availability | ||
---|---|---|
|
Use of group strategies can be configured. These strategies determine, for example, that an account will only be authenticated for one realm when it can also be authenticated for all the realms in that group.
Configuration
The group strategy has to be configured - the following four strategies are available:
- SOSFirstSuccessfulGroupStrategy
- SOSAllSuccessfulGroupStrategy
- SOSAllSuccessfulFirstGroupStrategy
- SOSAtLeastOneSuccessfulGroupStrategy
The strategy to be followed is specified by adding, for example, the following to the [main]
section of the Shiro ini file:
authcStrategy = com.sos.auth.shiro.SOSFirstSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
For the grouping of strategies a naming convention has to be followed that includes to separate the group form the Realm name by a hashtag, for example
A#Ldap1
Example
The following example uses two Groups "A" and "B", each with two Realms each. Roles "r1" and "r2" are configured per Realm by the groups/roles mapping instruction:
Code Block | ||||
---|---|---|---|---|
| ||||
[main]
A#Ldap1 = com.sos.auth.shiro.SOSLdapAuthorizingRealm
A#Ldap1.userDnTemplate = uid={0},dc=example,dc=com
A#Ldap1.searchBase = dc=example,dc=com
A#Ldap1.contextFactory.url = ldap://ldap.forumsys.com:389
A#Ldap1.groupNameAttribute = ou
A#Ldap1.userNameAttribute = uid
A#Ldap1.rolePermissionResolver = $rolePermissionResolver
A#Ldap1.userSearchFilter = (uniqueMember=uid=%s,dc=example,dc=com)
A#Ldap1.groupRolesMap = \
scientists : r1, \
mathematicians: r2
A#Ldap1.roleAssignmentFromIni = false
A#Ldap2 = com.sos.auth.shiro.SOSLdapAuthorizingRealm
...
B#Ldap1 = com.sos.auth.shiro.SOSLdapAuthorizingRealm
...
B#Ldap2 = com.sos.auth.shiro.SOSLdapAuthorizingRealm
...
rolePermissionResolver = com.sos.auth.shiro.SOSPermissionResolverAdapter
rolePermissionResolver.ini = $iniRealm
authcStrategy = org.apache.shiro.authc.pam.SOSFirstSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
securityManager.realms = $A#Ldap1,$A#Ldap2,$B#Ldap1,$B#Ldap2
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager |
Find a number of examples for the behavior with different strategies from the following chapters.
SOSFirstSuccessfulGroupStrategy
Code Block |
---|
authcStrategy = org.apache.shiro.authc.pam.SOSFirstSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy |
Explanation
- All Realms with the same group will be checked group-wise.
- In every group there must be one Realm that can be authenticated, otherwise authentication will fail for all groups.
- The roles from the first Realm per group will be added to the roles the user is assigned.
Authentication Matrix
A#Ldap1 | A#Ldap2 | B#Ldap1 | B#Ldap2 | Resulting Role Assignments |
---|---|---|---|---|
x | x | x | x | A#Ldap1, B#Ldap1 |
x | x | x | A#Ldap1, B#Ldap1 | |
x | x | x | A#Ldap1, B#Ldap2 | |
x | x | x | A#Ldap1, B#Ldap1 | |
x | x | x | A#Ldap2, B#Ldap1 | |
x | x | fail | ||
x | x | A#Ldap1, B#Ldap1 | ||
x | x | A#Ldap1, B#Ldap2 | ||
x | x | A#Ldap2, B#Ldap1 | ||
x | x | A#Ldap2, B#Ldap2 | ||
x | x | fail | ||
x | fail | |||
x | fail | |||
x | fail | |||
x | fail | |||
fail |
SOSAllSuccessfulGroupStrategy
Code Block |
---|
authcStrategy = org.apache.shiro.authc.pam.SOSAllSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy |
Explanation
- All realms with the same group will be checked group-wise.
- In at least one group all Realms must be authenticated.
- The roles from Realms in groups where all Realms can be authenticated will be merged to the roles the user is assigned.
Authentication Matrix
A#Ldap1 | A#Ldap2 | B#Ldap1 | B#Ldap2 | Resulting Role Assignments |
---|---|---|---|---|
x | x | x | x | A#Ldap1, A#Ldap2, B#Ldap1, B#Ldap2 |
x | x | x | B#Ldap1, B#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2 | |
x | x | x | B#Ldap1, B#Ldap2 | |
x | x | A#Ldap1, A#Ldap2 | ||
x | x | fail | ||
x | x | fail | ||
x | x | fail | ||
x | x | fail | ||
x | x | B#Ldap1, B#Ldap2 | ||
x | fail | |||
x | fail | |||
x | fail | |||
x | fail | |||
fail |
SOSAllSuccessfulFirstGroupStrategy
Code Block |
---|
authcStrategy = org.apache.shiro.authc.pam.SOSAllSuccessfulFirstGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy |
Explanation
- All Realms with the same group will be checked group-wise.
- In at least one group all Realms must be authenticated.
- The roles from Realms in the first group where all Realms can be authenticated will be merged with other roles the user is assigned.
Authentication Matrix
A#Ldap1 | A#Ldap2 | B#Ldap1 | B#Ldap2 | Resulting Role Assignments |
---|---|---|---|---|
x | x | x | x | A#Ldap1, A#Ldap2 |
x | x | x | B#Ldap1, B#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2 | |
x | x | x | B#Ldap1, B#Ldap2 | |
x | x | A#Ldap1, A#Ldap2 | ||
x | x | fail | ||
x | x | fail | ||
x | x | fail | ||
x | x | fail | ||
x | x | B#Ldap1, B#Ldap2 | ||
x | fail | |||
x | fail | |||
x | fail | |||
x | fail | |||
fail |
SOSAtLeastOneSuccessfulGroupStrategy
Code Block |
---|
authcStrategy = org.apache.shiro.authc.pam.SOSAtLeastOneSuccessfulGroupStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy |
Explanation
- All Realms with the same group will be checked group-wise.
- At least one Realm must be authenticated in every group.
- The roles from Realms that have been authenticated will be merged with other roles the user is assigned.
Authentication Matrix
A#Ldap1 | A#Ldap2 | B#Ldap1 | B#Ldap2 | Resulting Role Assignments |
---|---|---|---|---|
x | x | x | x | A#Ldap1, A#Ldap2, B#Ldap1, B#Ldap2 |
x | x | x | A#Ldap1, B#Ldap1, B#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2, B#Ldap2 | |
x | x | x | A#Ldap1, A#Ldap2, B#Ldap1 | |
x | x | x | A#Ldap2, B#Ldap1, B#Ldap2 | |
x | x | fail | ||
x | x | A#Ldap1, B#Ldap1 | ||
x | x | A#Ldap1, B#Ldap2 | ||
x | x | A#Ldap2, B#Ldap1 | ||
x | x | A#Ldap2, B#Ldap2 | ||
x | x | fail | ||
x | fail | |||
x | fail | |||
x | fail | |||
x | fail | |||
fail |