/*******************************************************************************
 *
 * Copyright (c) 2004-2010, Oracle Corporation
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 *
 *
 *
 *******************************************************************************/ 

package hudson.security;

import java.io.IOException;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;

/**
 * Handles authentication for CLI commands.
 *
 * <p> {@link CliAuthenticator} is used to authenticate an invocation of the CLI
 * command, so that the thread carries the correct {@link Authentication} that
 * represents the user who's invoking the command.
 *
 * <h2>Lifecycle</h2> <p> Each time a CLI command is invoked,
 * {@link SecurityRealm#createCliAuthenticator(CLICommand)} is called to
 * allocate a fresh {@link CliAuthenticator} object.
 *
 * <p> The {@link Option} and {@link Argument} annotations on the returned
 * {@link CliAuthenticator} instance are scanned and added into the
 * {@link CmdLineParser}, then that parser is used to parse command line
 * arguments. This means subtypes can define fields/setters with those
 * annotations to define authentication-specific options to CLI commands.
 *
 * <p> Once the arguments and options are parsed and populated,
 * {@link #authenticate()} method is called to perform the authentications. If
 * the authentication succeeds, this method returns an {@link Authentication}
 * instance that represents the user. If the authentication fails, this method
 * throws {@link AuthenticationException}. To authenticate, the method can use
 * parsed argument/option values, as well as interacting with the client via
 * {@link CLICommand} by using its stdin/stdout and its channel (for example, if
 * you want to interactively prompt a password, you can do so by using
 * {@link CLICommand#channel}.)
 *
 * <p> If no explicit credential is provided, or if the {@link SecurityRealm}
 * depends on a mode of authentication that doesn't involve in explicit password
 * (such as Kerberos), it's also often useful to fall back to
 * {@link CLICommand#getTransportAuthentication()}, in case the user is
 * authenticated at the transport level.
 *
 * <p> Many commands do not require any authentication (for example, the "help"
 * command), and still more commands can be run successfully with the anonymous
 * permission. So the authenticator should normally allow unauthenticated CLI
 * command invocations. For those, return {@link Hudson#ANONYMOUS} from the
 * {@link #authenticate()} method.
 *
 * <h2>Example</h2> <p> For a complete example, see the implementation of
 * {@link AbstractPasswordBasedSecurityRealm#createCliAuthenticator(CLICommand)}
 *
 * @author Kohsuke Kawaguchi
 * @since 1.350
 */
public abstract class CliAuthenticator {

    /**
     * Authenticates the CLI invocation. See class javadoc for the semantics.
     *
     * @throws AuthenticationException If the authentication failed and hence
     * the processing shouldn't proceed.
     * @throws IOException Can be thrown if the {@link CliAuthenticator} fails
     * to interact with the client. This exception is treated as a failure of
     * authentication. It's just that allowing this would often simplify the
     * callee.
     * @throws InterruptedException Same motivation as {@link IOException}.
     * Treated as an authentication failure.
     */
    public abstract Authentication authenticate() throws AuthenticationException, IOException, InterruptedException;
}
