uk.ac.starlink.auth

## Class AuthManager

- java.lang.Object
- - uk.ac.starlink.auth.AuthManager

-     public class AuthManager
      extends java.lang.Object

  Manages authentication. In general there would be one JVM-wide instance of this class (obtained from `getInstance()`) used for all access to URLs that might require or allow authentication; it will intercept accesses as required and retain authentication information as required for use in subsequent HTTP(S) requests so that the user does not have to keep supplying credentials where they are already known.

  An application should typically call `setUserInterface` on the default instance with an appropriate value near startup and then use the same instance for all subsequent potentially authenticated URL accesses.

  To access (potentially) authenticated resources, client code will usually just call `openStream(URL)` or one of the various overloaded `connect` methods. These are all convenience aliases for calls to the `makeConnection` method that actually manages authentication and redirection for connecting to a given URL.

  Currently no attempt is made to handle proxy-authentication (407).

  Since:
    16 Jun 2020

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `AuthManager(UserInterface ui, AuthScheme[] schemes, Redirector dfltRedirector)` Constructor.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `AuthStatus` | `authcheck(java.net.URL authcheckUrl, boolean isHead, boolean isForceLogin)` Attempts to establish authentication for an authcheck-type URL.
    `void` | `clear()` Clears all authentication state from this manager.
    `java.net.URLConnection` | `connect(java.net.URL url)` Opens a URL connection to a given URL, negotiating authentication and with default handling of 3xx redirection.
    `java.net.URLConnection` | `connect(java.net.URL url, UrlConnector connector)` Opens a URL connection to a given URL with specified configuration, negotiating authentication and with default handling of 3xx redirection.
    `java.net.URLConnection` | `connect(java.net.URL url, UrlConnector connector, Redirector redirector)` Opens a URL connection to a given URL with specified configuration, negotiating authentication and with configurable handling of 3xx redirection.
    `java.net.URLConnection` | `followRedirects(java.net.URLConnection conn, UrlConnector connector, Redirector redirector)` Follows 3xx redirects, applying authentication as required.
    `static AuthManager` | `getInstance()` Returns the default instance of this class.
    `java.util.List<AuthScheme>` | `getSchemes()` Returns a mutable ordered list of authentication schemes known by this manager.
    `UserInterface` | `getUserInterface()` Returns the object that controls how the user is queried for credentials.
    `AuthConnection` | `makeConnection(java.net.URL url, UrlConnector connector, Redirector redirector)` Opens a URL connection to a given URL with specified configuration, negotiating authentication and with configurable handling of 3xx redirection.
    `java.io.InputStream` | `openStream(java.net.URL url)` Returns the content stream acquired by opening a URL.
    `static void` | `setDefaultInstance(AuthManager authManager)` Resets the default AuthManager instance.
    `void` | `setUserInterface(UserInterface ui)` Sets the object that controls how the user is queried for credentials.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### AuthManager

          public AuthManager(UserInterface ui,
                             AuthScheme[] schemes,
                             Redirector dfltRedirector)

      Constructor. Note that in most cases best practice would be to use the `getInstance()` method instead.
      Parameters:
        `ui` - user interface implementation; if null, no authentication management is attempted
        `schemes` - list of known authentication schemes, ordered by preference
        `dfltRedirector` - handles default 3xx redirection behaviour

  - ### Method Detail

    - #### setUserInterface

          public void setUserInterface(UserInterface ui)

      Sets the object that controls how the user is queried for credentials. If the value is null, then this object will not attempt any authentication management, and it will simply defer to normal JVM behaviour.
      Parameters:
        `ui` - user interface to use if null, no authentication management is attempted

    - #### getUserInterface

          public UserInterface getUserInterface()

      Returns the object that controls how the user is queried for credentials. If the value is null, then this object will not attempt any authentication management, and it will simply defer to normal JVM behaviour.
      Returns:
        user interface in use if null, no authentication management is attempted

    - #### getSchemes

          public java.util.List<AuthScheme> getSchemes()

      Returns a mutable ordered list of authentication schemes known by this manager. Schemes earlier in this list are preferred over later ones.

      As well as being mutable this list is thread-safe.

      Returns:
        mutable list of schemes

    - #### clear

          public void clear()

      Clears all authentication state from this manager. Any subsequent accesses to protected resources will require new credential acquisition.

    - #### connect

          public java.net.URLConnection connect(java.net.URL url)
                                         throws java.io.IOException

      Opens a URL connection to a given URL, negotiating authentication and with default handling of 3xx redirection. The return value is an open connection, that is one on which `connect()` has been called.

      An IOException is only thrown in unexpected circumstances; connection failure is usually indicated by the status of the returned connection object.

      Parameters:
        `url` - target URL
      Returns:
        open connection to URL, with authentication in place if applicable and possible
      Throws:
        `java.io.IOException`

    - #### connect

          public java.net.URLConnection connect(java.net.URL url,
                                                UrlConnector connector)
                                         throws java.io.IOException

      Opens a URL connection to a given URL with specified configuration, negotiating authentication and with default handling of 3xx redirection. The return value is an open connection, that is one on which `connect()` has been called.

      An IOException is only thrown in unexpected circumstances; connection failure is usually indicated by the status of the returned connection object.

      Parameters:
        `url` - target URL
        `connector` - obtains a connection from a URL; may be null for default behaviour
      Returns:
        open connection to URL, with authentication in place if applicable and possible
      Throws:
        `java.io.IOException`

    - #### connect

          public java.net.URLConnection connect(java.net.URL url,
                                                UrlConnector connector,
                                                Redirector redirector)
                                         throws java.io.IOException

      Opens a URL connection to a given URL with specified configuration, negotiating authentication and with configurable handling of 3xx redirection. The return value is an open connection, that is one on which `connect()` has been called.

      An IOException is only thrown in unexpected circumstances; connection failure is usually indicated by the status of the returned connection object.

      Parameters:
        `url` - target URL
        `connector` - obtains a connection from a URL; may be null for default behaviour
        `redirector` - controls handling of 3xx redirection
      Returns:
        open connection to URL, with authentication in place if applicable and possible
      Throws:
        `java.io.IOException`

    - #### makeConnection

          public AuthConnection makeConnection(java.net.URL url,
                                               UrlConnector connector,
                                               Redirector redirector)
                                        throws java.io.IOException

      Opens a URL connection to a given URL with specified configuration, negotiating authentication and with configurable handling of 3xx redirection. The return value is an AuthConnection which aggregates an open connection, that is one on which `connect()` has been called, and the AuthContext which was used to open it.

      An IOException is only thrown in unexpected circumstances; connection failure is usually indicated by the status of the returned connection object.

      Parameters:
        `url` - target URL
        `connector` - obtains a connection from a URL; may be null for default behaviour
        `redirector` - controls handling of 3xx redirection
      Returns:
        object containing an open URLConnection with authentication in place if applicable and possible, and the AuthContext used to connect
      Throws:
        `java.io.IOException`

    - #### openStream

          public java.io.InputStream openStream(java.net.URL url)
                                         throws java.io.IOException

      Returns the content stream acquired by opening a URL. This convenience method is shorthand for `connect(url).getInputStream()`.
      Parameters:
        `url` - target URL
      Returns:
        an input stream for reading from the URL connection
      Throws:
        `java.io.IOException` - in case of failure, including authentication failure

    - #### followRedirects

          public java.net.URLConnection followRedirects(java.net.URLConnection conn,
                                                        UrlConnector connector,
                                                        Redirector redirector)
                                                 throws java.io.IOException

      Follows 3xx redirects, applying authentication as required.
      Parameters:
        `conn` - initial URL connection
        `connector` - obtains a connection from a URL; may be null for default behaviour
        `redirector` - defines how redirection is done
      Returns:
        connected connection following redirects; in case of no redirection, this will be the same as the input connection
      Throws:
        `java.io.IOException`

    - #### authcheck

          public AuthStatus authcheck(java.net.URL authcheckUrl,
                                      boolean isHead,
                                      boolean isForceLogin)
                               throws java.io.IOException

      Attempts to establish authentication for an authcheck-type URL. If it has not already been done for the domain in question, this method may (depending on the `isForceLogin` parameter) query the user for credentials as required, and has the side-effect of setting up authentication to related URLs for subsequent communication.

      Setting the `isForceLogin` parameter affects whether user interaction will take place. If true, then any previous credentials for challenges received are disregarded, and either a 200 or a 401/403 response will trigger user interaction (request for credentials), as long as challenges are present. If false, any existing credentials are used where applicable, and user interaction only takes place on a 401/403 response; so a request for credentials only takes place if it can't be avoided.

      The expected behaviour of this authcheck endpoint is as follows, in accordance with the (draft at time of writing) "SSO_next" proposal. Briefly, it behaves as other endpoints in the service except that a service allowing both authenticated and anonymous access should accompany 200 responses to anonymous access with an RFC7235 challenge. In more detail: if authenticated or unauthenticated access is attempted, it should provoke a 200/401/403 response, following normal HTTP rules, matching the behaviour that a similarly authenticated request would see when using the associated VO service. However, in the case of a service that permits both authenticated and anonymous access on the same endpoint, an anonymous request should provoke a 200 response with an accompanying WWW-Authenticate header (an authentication Challenge as defined in RFC7235 sec 4.1). Thus clients attempting authenticated or unauthenticated access must be prepared for

      - 200 with or without a challenge
      - 401 with a challenge
      - 403 with or without a challenge
      - 404
      Additionally, the response SHOULD contain an `X-VO-Authenticated` header giving the authenticated user ID if authentication has been established. The response body is not defined by this proposal.
      Parameters:
        `authcheckUrl` - URL at which an authcheck endpoint may be present
        `isHead` - if true use a HEAD request, if false use GET
        `isForceLogin` - whether to force a new login where it could be avoided
      Returns:
        characterisation of authentication status that has been established for the given URL, and will be used for compatible URLs in future if suitable
      Throws:
        `java.io.IOException`

    - #### getInstance

          public static AuthManager getInstance()

      Returns the default instance of this class. Note that the initial state of this instance has no user interface, meaning there is no change to normal JVM behaviour. To get this instance to manage authentication, it is necessary first to call `setUserInterface(uk.ac.starlink.auth.UserInterface)`.
      Returns:
        default instance

    - #### setDefaultInstance

          public static void setDefaultInstance(AuthManager authManager)

      Resets the default AuthManager instance.
      Parameters:
        `authManager` - new default instance