Class ServerAuthenticationContext

  • All Implemented Interfaces:
    AutoCloseable

    public final class ServerAuthenticationContext
    extends Object
    implements AutoCloseable
    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 security domain.

    There are various effective states, described as follows:

    • The inactive state.
    • The unassigned states:
      • Initial
      • Realm-assigned
    • The assigned state
    • The authorized states:
      • Anonymous-authorized
      • Authorized
      • Authorized-authenticated
    • The terminal states:
      • Complete
      • Failed

    When an instance of this class is first constructed, it is in the inactive state. In this state, the context retains a captured identity 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 identity and a mechanism configuration 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, mechanism realms, 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() 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 rewritten and mapped to a realm according to the domain settings, the mechanism configuration, and/or the mechanism realm configuration. The realm that is the resultant target of the mapping is queried for a realm identity. 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 authentication principal which may subsequently be queried.
    • A principal may be assigned using the setAuthenticationPrincipal(Principal) method. The principal is decoded 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 contains a principal. 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 locate an identity based on the evidence. If so, the realm identity is queried 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 imported. 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 queried 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 anonymous identity 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 anonymous principal is 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.

    Author:
    David M. Lloyd, Darran Lofthouse
    • Method Detail

      • setMechanismInformation

        public void setMechanismInformation​(MechanismInformation mechanismInformation)
                                     throws IllegalStateException
        Set information about the current mechanism and request for this authentication attempt. If the mechanism information cannot be resolved to a mechanism configuration, an exception is thrown.
        Parameters:
        mechanismInformation - the mechanism information about the current authentication attempt.
        Throws:
        IllegalStateException - if the mechanism information about the current authentication attempt cannot be resolved to a mechanism configuration
      • authorizeAnonymous

        public boolean authorizeAnonymous()
                                   throws IllegalStateException
        Set the authentication to anonymous, completing the authentication process.
        Throws:
        IllegalStateException - if the authentication is already complete
      • authorizeAnonymous

        public boolean authorizeAnonymous​(boolean requireLoginPermission)
                                   throws IllegalStateException
        Set the authentication to anonymous, completing the authentication process.
        Parameters:
        requireLoginPermission - true if LoginPermission is required and false otherwise
        Throws:
        IllegalStateException - if the authentication is already complete
      • setAuthenticationName

        public void setAuthenticationName​(String name,
                                          boolean exclusive)
                                   throws IllegalArgumentException,
                                          RealmUnavailableException,
                                          IllegalStateException
        Set the authentication name for this authentication. If the name is already set, then the new name must be equal to the old name, or else an exception is thrown.
        Parameters:
        name - the authentication name
        exclusive - true if exclusive access to the backing identity is required
        Throws:
        IllegalArgumentException - if the name is syntactically invalid
        RealmUnavailableException - if the realm is not available or if exclusive access to the backing identity is required but could not be granted
        IllegalStateException - if the authentication name was already set and there is a mismatch
      • fail

        public void fail()
                  throws IllegalStateException
        Mark this authentication as "failed". The context cannot be used after this method is called.
        Throws:
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • authorize

        public boolean authorize()
                          throws RealmUnavailableException,
                                 IllegalStateException
        Attempt to authorize an authentication attempt. If the authorization is successful, true is returned and the context is placed in the "authorized" state with the new authorization identity. If the authorization fails, false is returned and the state of the context is unchanged.
        Returns:
        true if the authorization succeeded, false otherwise
        Throws:
        RealmUnavailableException - if the realm is not available
        IllegalStateException - if the authentication name was not set or authentication was already complete
      • authorize

        public boolean authorize​(String name)
                          throws IllegalArgumentException,
                                 RealmUnavailableException,
                                 IllegalStateException
        Attempt to authorize a change to a new user (possibly including an authentication attempt). If the authorization is successful, true is returned and the context is placed in the "authorized" state with the new authorization identity. If the authorization fails, false is returned and the state of the context is unchanged.
        Parameters:
        name - the authorization name (must not be null)
        Returns:
        true if the authorization succeeded, false otherwise
        Throws:
        IllegalArgumentException - if the name is syntactically invalid
        RealmUnavailableException - if the realm is not available
        IllegalStateException - if the authentication name was not set or authentication was already complete
      • authorize

        public boolean authorize​(Principal principal)
                          throws IllegalArgumentException,
                                 RealmUnavailableException,
                                 IllegalStateException
        Attempt to authorize a change to a new user (possibly including an authentication attempt). If the authorization is successful, true is returned and the context is placed in the "authorized" state with the new authorization identity. If the authorization fails, false is returned and the state of the context is unchanged.
        Parameters:
        principal - the authorization principal (must not be null)
        Returns:
        true if the authorization succeeded, false otherwise
        Throws:
        IllegalArgumentException - if the principal is syntactically invalid
        RealmUnavailableException - if the realm is not available
        IllegalStateException - if the authentication principal was not set or authentication was already complete
      • isDone

        public boolean isDone()
        Determine if authentication was already completed on this context.
        Returns:
        true if authentication was completed; false otherwise
      • getAuthenticationPrincipal

        public Principal getAuthenticationPrincipal()
        Get the principal associated with the current authentication name. Only valid during authentication process.
        Returns:
        the principal
        Throws:
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredentialAcquireSupport

        public SupportLevel getCredentialAcquireSupport​(Class<? extends Credential> credentialType,
                                                        String algorithmName,
                                                        AlgorithmParameterSpec parameterSpec)
                                                 throws RealmUnavailableException
        Determine whether a given credential is definitely obtainable, possibly obtainable, or definitely not obtainable. If an authentication identity is established this will be for that identity, otherwise this will be the general level of support advertised by the security domain.
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name, or null if any algorithm is acceptable or the credential type does not support algorithm names
        parameterSpec - the algorithm parameters to match, or null if any parameters are acceptable or the credential type does not support algorithm parameters
        Returns:
        the level of support for this credential type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredentialAcquireSupport

        public SupportLevel getCredentialAcquireSupport​(Class<? extends Credential> credentialType,
                                                        String algorithmName)
                                                 throws RealmUnavailableException
        Determine whether a given credential is definitely obtainable, possibly obtainable, or definitely not obtainable. If an authentication identity is established this will be for that identity, otherwise this will be the general level of support advertised by the security domain.
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name, or null if any algorithm is acceptable or the credential type does not support algorithm names
        Returns:
        the level of support for this credential type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredentialAcquireSupport

        public SupportLevel getCredentialAcquireSupport​(Class<? extends Credential> credentialType)
                                                 throws RealmUnavailableException
        Determine whether a given credential is definitely obtainable, possibly obtainable, or definitely not obtainable. If an authentication identity is established this will be for that identity, otherwise this will be the general level of support advertised by the security domain.
        Parameters:
        credentialType - the credential type class (must not be null)
        Returns:
        the level of support for this credential type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getEvidenceVerifySupport

        public SupportLevel getEvidenceVerifySupport​(Class<? extends Evidence> evidenceType,
                                                     String algorithmName)
                                              throws RealmUnavailableException
        Determine whether a given piece of evidence is definitely verifiable, possibly verifiable, or definitely not verifiable. If an authentication identity is established this will be for that identity, otherwise this will be the general level of support advertised by the security domain.
        Parameters:
        evidenceType - the evidence type class (must not be null)
        algorithmName - the algorithm name, or null if any algorithm is acceptable or the evidence type does not support algorithm names
        Returns:
        the level of support for this credential type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getEvidenceVerifySupport

        public SupportLevel getEvidenceVerifySupport​(Class<? extends Evidence> evidenceType)
                                              throws RealmUnavailableException
        Determine whether a given piece of evidence is definitely verifiable, possibly verifiable, or definitely not verifiable. If an authentication identity is established this will be for that identity, otherwise this will be the general level of support advertised by the security domain.
        Parameters:
        evidenceType - the evidence type class (must not be null)
        Returns:
        the level of support for this credential type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredential

        public <C extends Credential> C getCredential​(Class<C> credentialType,
                                                      String algorithmName,
                                                      AlgorithmParameterSpec parameterSpec)
                                               throws RealmUnavailableException
        Acquire a credential of the given type. The credential type is defined by its Class and an optional algorithmName. If the algorithm name is not given, then the query is performed for any algorithm of the given type.
        Type Parameters:
        C - the credential type
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name, or null if any algorithm is acceptable or the credential type does not support algorithm names
        parameterSpec - the algorithm parameters to match, or null if any parameters are acceptable or the credential type does not support algorithm parameters
        Returns:
        the credential, or null if the principal has no credential of that type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredential

        public <C extends Credential> C getCredential​(Class<C> credentialType,
                                                      String algorithmName)
                                               throws RealmUnavailableException
        Acquire a credential of the given type. The credential type is defined by its Class and an optional algorithmName. If the algorithm name is not given, then the query is performed for any algorithm of the given type.
        Type Parameters:
        C - the credential type
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name, or null if any algorithm is acceptable or the credential type does not support algorithm names
        Returns:
        the credential, or null if the principal has no credential of that type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • getCredential

        public <C extends Credential> C getCredential​(Class<C> credentialType)
                                               throws RealmUnavailableException
        Acquire a credential of the given type. The credential type is defined by its Class and an optional algorithmName. If the algorithm name is not given, then the query is performed for any algorithm of the given type.
        Type Parameters:
        C - the credential type
        Parameters:
        credentialType - the credential type class (must not be null)
        Returns:
        the credential, or null if the principal has no credential of that type
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • applyToCredential

        public <C extends Credential,​R> R applyToCredential​(Class<C> credentialType,
                                                                  Function<C,​R> function)
                                                           throws RealmUnavailableException
        Apply the given function to the acquired credential, if it is set and of the given type.
        Type Parameters:
        C - the credential type
        R - the return type
        Parameters:
        credentialType - the credential type class (must not be null)
        function - the function to apply (must not be null)
        Returns:
        the result of the function, or null if the criteria are not met
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • applyToCredential

        public <C extends Credential,​R> R applyToCredential​(Class<C> credentialType,
                                                                  String algorithmName,
                                                                  Function<C,​R> function)
                                                           throws RealmUnavailableException
        Apply the given function to the acquired credential, if it is set and of the given type and algorithm.
        Type Parameters:
        C - the credential type
        R - the return type
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name
        function - the function to apply (must not be null)
        Returns:
        the result of the function, or null if the criteria are not met
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • applyToCredential

        public <C extends Credential,​R> R applyToCredential​(Class<C> credentialType,
                                                                  String algorithmName,
                                                                  AlgorithmParameterSpec parameterSpec,
                                                                  Function<C,​R> function)
                                                           throws RealmUnavailableException
        Apply the given function to the acquired credential, if it is set and of the given type and algorithm.
        Type Parameters:
        C - the credential type
        R - the return type
        Parameters:
        credentialType - the credential type class (must not be null)
        algorithmName - the algorithm name
        parameterSpec - the algorithm parameters to match, or null if any parameters are acceptable or the credential type does not support algorithm parameters
        function - the function to apply (must not be null)
        Returns:
        the result of the function, or null if the criteria are not met
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • verifyEvidence

        public boolean verifyEvidence​(Evidence evidence)
                               throws RealmUnavailableException
        Verify the given evidence.
        Parameters:
        evidence - the evidence to verify
        Returns:
        true if verification was successful, false otherwise
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
        IllegalStateException - if no authentication has been initiated or authentication is already completed
      • addPublicCredential

        public void addPublicCredential​(Credential credential)
        Add a public credential to the identity being authenticated.
        Parameters:
        credential - the credential to add (must not be null)
      • addPrivateCredential

        public void addPrivateCredential​(Credential credential)
        Add a private credential to the identity being authenticated. This credential may be forwarded to outbound authentication mechanisms.
        Parameters:
        credential - the credential to add (must not be null)
      • importIdentity

        public boolean importIdentity​(SecurityIdentity identity)
                               throws RealmUnavailableException
        Attempt to import the given security identity as a trusted identity. If this method returns true, the context will be in an authorized state, and the new identity can be retrieved.
        Parameters:
        identity - the identity to import (must not be null)
        Returns:
        true if the identity is authorized, false otherwise
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
      • setMechanismRealmName

        public void setMechanismRealmName​(String realmName)
                                   throws IllegalStateException,
                                          IllegalArgumentException
        Set the mechanism realm name to be equal to the given name. If no mechanism realms are configured, the realm name is ignored.
        Parameters:
        realmName - the selected realm name
        Throws:
        IllegalStateException - if a realm name was already selected or it is too late to choose a realm
        IllegalArgumentException - if the selected realm name was not offered
      • updateCredential

        public void updateCredential​(Credential credential)
                              throws RealmUnavailableException
        Update the credential for the current authentication identity.
        Parameters:
        credential - the new credential (must not be null)
        Throws:
        RealmUnavailableException - if the realm is not able to handle requests for any reason
      • close

        public void close()
        Close the server authentication context, failing any in-progress authentication and releasing any associated resources.
        Specified by:
        close in interface AutoCloseable