001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.auth;
003
004import java.net.Authenticator;
005import java.net.PasswordAuthentication;
006import java.util.EnumMap;
007import java.util.Map;
008
009import org.openstreetmap.josm.Main;
010import org.openstreetmap.josm.io.OsmApi;
011
012/**
013 * This is the default authenticator used in JOSM. It delegates lookup of credentials
014 * for the OSM API and an optional proxy server to the currently configured {@link CredentialsManager}.
015 * @since 2641
016 */
017public final class DefaultAuthenticator extends Authenticator {
018    private static volatile DefaultAuthenticator instance;
019
020    /**
021     * Returns the unique instance
022     * @return The unique instance
023     */
024    public static DefaultAuthenticator getInstance() {
025        return instance;
026    }
027
028    /**
029     * Creates the unique instance
030     */
031    public static void createInstance() {
032        instance = new DefaultAuthenticator();
033    }
034
035    private final Map<RequestorType, Boolean> credentialsTried = new EnumMap<>(RequestorType.class);
036    private boolean enabled = true;
037
038    private DefaultAuthenticator() {
039    }
040
041    /**
042     * Called by the Java HTTP stack when either the OSM API server or a proxy requires authentication.
043     */
044    @Override
045    protected PasswordAuthentication getPasswordAuthentication() {
046        if (!enabled)
047            return null;
048        try {
049            if (getRequestorType().equals(Authenticator.RequestorType.SERVER) && OsmApi.isUsingOAuth()) {
050                // if we are working with OAuth we don't prompt for a password
051                return null;
052            }
053            boolean tried = credentialsTried.get(getRequestorType()) != null;
054            CredentialsAgentResponse response = CredentialsManager.getInstance().getCredentials(getRequestorType(), getRequestingHost(), tried);
055            if (response == null || response.isCanceled())
056                return null;
057            credentialsTried.put(getRequestorType(), Boolean.TRUE);
058            return new PasswordAuthentication(response.getUsername(), response.getPassword());
059        } catch (CredentialsAgentException e) {
060            Main.error(e);
061            return null;
062        }
063    }
064
065    public boolean isEnabled() {
066        return enabled;
067    }
068
069    public void setEnabled(boolean enabled) {
070        this.enabled = enabled;
071    }
072}