Server-side authentication context. Instances of this class are used to perform all authentication and re-authorization
operations that involve the usage of an identity in a
SecurityDomain.
There are various effective states, described as follows:
- The inactive state.
-
The unassigned states:
- The assigned state
-
The authorized states:
- Anonymous-authorized
- Authorized
- Authorized-authenticated
-
The terminal states:
When an instance of this class is first constructed, it is in the inactive state. In this state, the context retains
a captured
SecurityIdentity and contains a reference to a
MechanismConfigurationSelector. The captured identity may be used for various
context-sensitive authorization decisions. Additional mechanism information can be supplied to this state so that when
authentication begins an appropriate
MechanismConfiguration can be selected.
Once authentication commences the state will automatically transition to the initial state. In this state, the
context retains an captured
SecurityIdentity and a
MechanismConfiguration
which was resolved from the information supplied to the inactive state. The captured identity may be
used for various context-sensitive authorization decisions. The mechanism configuration is used to associate
an authentication mechanism-specific configuration, including rewriters,
MechanismRealmConfiguration,
server credential factories, and more.
When an authentication mechanism is "realm-aware" (that is, it has a notion of realms that is specific to that particular
authentication mechanism, e.g. the DIGEST-MD5 SASL mechanism), it
is necessary for the mechanism to relay the realm selection. This is done by way of the
#setMechanismRealmName(String)method. Calling this method in the initial state causes a transition to the realm-assigned state,
in which the method may be reinvoked idempotently as long as it is called with the same name (calling the method with
a different name will result in an exception).
The realm-assigned state is nearly identical to the initial state, except that from this state, the
mechanism realm-specific configuration is applied to all subsequent operation.
From these unassigned states, several possible actions may be taken, depending on the necessary progression
of the authentication:
-
A name may be assigned by way of the
#setAuthenticationName(String) method. The name is
NameRewriter and
RealmMapper according to the
domain settings, the mechanism configuration, and/or the mechanism realm configuration. The
SecurityRealm that is the resultant target of the mapping is queried for a
RealmIdentity. The realm identity may or may not be
existent; this status will affect the outcome of certain operations in subsequent states (as described below).
After the realm identity is selected, any final rewrite operations which are configured are applied,
and the resultant name is transformed into a
NamePrincipal, and associated as the
#getAuthenticationPrincipal() which may subsequently be queried.
-
A principal may be assigned using the
#setAuthenticationPrincipal(Principal) method. The
principal is
PrincipalDecoder according to the configuration of the security domain (see
the method documentation for input requirements and failure conditions). Once a name is decoded from the
principal, it is assigned as described above.
-
A unit of
Evidence may be verified. This is mostly described below in the
context of the assigned state, but with the important distinction the evidence is first examined
to locate the corresponding evidence, in the following steps:
-
Firstly, the evidence is examined to determine whether it
Evidence#getPrincipal().
If so, the principal name is first established using the procedure described above, and then the normal
evidence verification procedure described below commences.
-
Secondly, the evidence is socialized to each realm in turn, to see if a realm can recognize
and
SecurityRealm#getRealmIdentity(Principal) an identity based on
the evidence. If so, the realm identity is
RealmIdentity#getRealmIdentityPrincipal()for an authentication principal, which is then decoded and established as described above. Once this
is done successfully, the evidence verification procedure described below commences.
- Finally, if none of these steps succeeds, the verification fails and no state transition occurs.
-
An identity may be
#importIdentity(SecurityIdentity). In this process,
a
SecurityIdentity instance is examined to determine whether it can be used to complete an implicit
authentication operation which would yield an authorized identity. The
SecurityIdentity may
be from the same domain or from a different one.
If the identity being imported is from the same security domain as this context, then the identity
is implicitly authorized for usage, entering the authorized state described below.
If the identity being imported is not from the same security domain, then the principal is extracted
from the identity and used to assign a realm identity in the same manner as
#setAuthenticationPrincipal(Principal).
The domain is then
SecurityDomain.Builder#setTrustedSecurityDomainPredicate(Predicate)to determine whether the target identity's source domain is trusted. If so, a normal
authorization is carried out as described below for the assigned state, resulting in an
authorized-authenticated state. If not, then the realm of the realm identity is
compared against the realm of the identity being imported. If they are the same, the
identity is imported and a normal authorization is carried out as described below.
-
An anonymous authorization may be carried out by way of the
#authorizeAnonymous() method.
If the
SecurityDomain#getAnonymousSecurityIdentity() has the
LoginPermission granted to it, the context will transition into the anonymous-authorized
state; otherwise no state transition occurs.
-
An external authorization may be carried out using the
#authorize() method. The
captured identity (which may be anonymous) is queried for the presence of the
LoginPermission; if present, the context will transition into the authorized or
anonymous-authorized state (depending on whether the captured identity is anonymous);
otherwise no state transition occurs.
-
An external run-as authorization may be carried out using the
#authorize(String) method.
First, the given name is rewritten in the same manner as the
#setAuthenticationName(String)method. Then, the captured identity (which may be anonymous) is queried for the presence of a
RunAsPrincipalPermission for the target name. If present, the authentication name is assigned
as described above, and the resultant realm identity is queried for
LoginPermission. If present,
the context will transition to the authorized-authenticated state. If any step fails, no state transition
occurs.
-
The authentication may be failed by way of the
#fail() method. This method will dispose
of all authentication resources and transition to the failed state.
In the name-assigned (or, for brevity, assigned) state, the following actions may be performed:
-
A name or principal may be assigned as above, however the resultant decoded and rewritten name
and realm identity must be identical to the previously selected name and identity.
-
Evidence may be verified. The realm identity is queried directly and no state transitions
will occur. Evidence verification will fail if the evidence has an evidence principal which does
not result in the same realm identity as the current one after decoding and rewriting.
-
An authorization may be performed via the
#authorize() method. If the selected realm identity
possesses the
LoginPermission, then the context transitions to the authorized-authenticated state,
otherwise no state transition occurs.
-
A run-as authorization may be performed via the
#authorize(String) method.
First, the given name is rewritten in the same manner as the
#setAuthenticationName(String) method.
The current identity is then authorized as described above, and then the authorized identity
is tested for a
RunAsPrincipalPermission for the rewritten target name. If authorized,
the context transitions to the authorized state for the realm identity corresponding to the
rewritten name; otherwise no state transition occurs.
-
The authentication may be failed by way of the
#fail() method. This method will dispose
of all authentication resources and transition to the failed state.
There are three states related to authorization: the anonymous-authorized state, the authorized state,
and the authorized-authenticated state. In all three states, the following actions may be taken:
-
As above, a name or principal may be assigned so long as it matches the existing identity. In particular,
for the anonymous-authorized state, all names are rejected, and only the
AnonymousPrincipalis accepted.
-
An authorization may be performed via the
#authorize() method. Since the identity is
always authorized, this is generally a no-op.
-
A run-as authorization may be performed via the
#authorize(String) method. The given
name is rewritten as previously described, and then the authorized identity
is tested for a
RunAsPrincipalPermission for the rewritten target name. If authorized,
the context transitions to the authorized state for the realm identity corresponding to the
rewritten name; otherwise no state transition occurs.
-
The authentication may be completed by way of the
#succeed() method. This method will
dispose of all authentication resources and transition to the complete state.
-
The authentication may be failed by way of the
#fail() method. This method will dispose
of all authentication resources and transition to the failed state.
The
authorized-authenticated state has the additional capability of verifying credentials as described above for
the
assigned state.
The complete state has only one capability: the retrieval of the final authorized identity by way
of the
#getAuthorizedIdentity() method.
The failed state has no capabilities and retains no reference to any identities or objects used during
authentication.