001package org.jsoup.helper;
002
003import org.jsoup.Connection;
004import org.jspecify.annotations.Nullable;
005
006import java.net.Authenticator;
007import java.net.PasswordAuthentication;
008import java.net.URL;
009
010/**
011 A {@code RequestAuthenticator} is used in {@link Connection} to authenticate if required to proxies and web
012 servers. See {@link Connection#auth(RequestAuthenticator)}.
013 */
014@FunctionalInterface
015public interface RequestAuthenticator {
016
017    /**
018     Provide authentication credentials for the provided Request Context.
019     * @param auth the request context including URL, type (Server or Proxy), and realm.
020     * @return credentials for the request. May return {@code null} if they are not applicable -- but the request will
021     * likely fail, as this method is only called if the request asked for authentication.
022     */
023    @Nullable
024    PasswordAuthentication authenticate(Context auth);
025
026    /**
027     Provides details for the request, to determine the appropriate credentials to return.
028     */
029    class Context {
030        private final URL url;
031        private final Authenticator.RequestorType type;
032        private final String realm;
033
034        Context(URL url, Authenticator.RequestorType type, String realm) {
035            this.url = url;
036            this.type = type;
037            this.realm = realm;
038        }
039
040        /**
041         Get he URL that is being requested.
042         * @return URL
043         */
044        public URL url() {
045            return url;
046        }
047
048        /**
049         Get the requestor type: {@link Authenticator.RequestorType#PROXY PROXY} if a proxy is requesting
050         authentication, or {@link Authenticator.RequestorType#SERVER SERVER} if the URL's server is requesting.
051         * @return requestor type
052         */
053        public Authenticator.RequestorType type() {
054            return type;
055        }
056
057        /**
058         Get the realm of the authentication request.
059         * @return realm of the authentication request
060         */
061        public String realm() {
062            return realm;
063        }
064
065        /**
066         Gets if the authentication request is for a proxy.
067         * @return true if type==proxy.
068         */
069        public boolean isProxy() {
070            return type == Authenticator.RequestorType.PROXY;
071        }
072
073        /**
074         Gets if the authentication request is for a server.
075         * @return true if type==server.
076         */
077        public boolean isServer() {
078            return type == Authenticator.RequestorType.SERVER;
079        }
080
081        /**
082         Helper method to return a PasswordAuthentication object.
083         * @param username username credential
084         * @param password password credential
085         * @return a constructed PasswordAuthentication
086         */
087        public PasswordAuthentication credentials(String username, String password) {
088            return new PasswordAuthentication(username, password.toCharArray());
089        }
090    }
091
092}