001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.auth;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.net.Authenticator.RequestorType;
008import java.net.PasswordAuthentication;
009import java.util.Objects;
010
011import javax.swing.text.html.HTMLEditorKit;
012
013import org.openstreetmap.josm.data.oauth.OAuthToken;
014import org.openstreetmap.josm.gui.widgets.HtmlPanel;
015import org.openstreetmap.josm.io.DefaultProxySelector;
016import org.openstreetmap.josm.io.OsmApi;
017import org.openstreetmap.josm.spi.preferences.Config;
018
019/**
020 * This is the default credentials agent in JOSM. It keeps username and password for both
021 * the OSM API and an optional HTTP proxy in the JOSM preferences file.
022 * @since 2641
023 */
024public class JosmPreferencesCredentialAgent extends AbstractCredentialsAgent {
025
026    /**
027     * @see CredentialsAgent#lookup
028     */
029    @Override
030    public PasswordAuthentication lookup(RequestorType requestorType, String host) throws CredentialsAgentException {
031        if (requestorType == null)
032            return null;
033        String user;
034        String password;
035        switch(requestorType) {
036        case SERVER:
037            if (Objects.equals(OsmApi.getOsmApi().getHost(), host)) {
038                user = Config.getPref().get("osm-server.username", null);
039                password = Config.getPref().get("osm-server.password", null);
040            } else if (host != null) {
041                user = Config.getPref().get("server.username."+host, null);
042                password = Config.getPref().get("server.password."+host, null);
043            } else {
044                user = null;
045                password = null;
046            }
047            if (user == null)
048                return null;
049            return new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
050        case PROXY:
051            user = Config.getPref().get(DefaultProxySelector.PROXY_USER, null);
052            password = Config.getPref().get(DefaultProxySelector.PROXY_PASS, null);
053            if (user == null)
054                return null;
055            return new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
056        }
057        return null;
058    }
059
060    /**
061     * @see CredentialsAgent#store
062     */
063    @Override
064    public void store(RequestorType requestorType, String host, PasswordAuthentication credentials) throws CredentialsAgentException {
065        if (requestorType == null)
066            return;
067        switch(requestorType) {
068        case SERVER:
069            if (Objects.equals(OsmApi.getOsmApi().getHost(), host)) {
070                Config.getPref().put("osm-server.username", credentials.getUserName());
071                if (credentials.getPassword() == null) {
072                    Config.getPref().put("osm-server.password", null);
073                } else {
074                    Config.getPref().put("osm-server.password", String.valueOf(credentials.getPassword()));
075                }
076            } else if (host != null) {
077                Config.getPref().put("server.username."+host, credentials.getUserName());
078                if (credentials.getPassword() == null) {
079                    Config.getPref().put("server.password."+host, null);
080                } else {
081                    Config.getPref().put("server.password."+host, String.valueOf(credentials.getPassword()));
082                }
083            }
084            break;
085        case PROXY:
086            Config.getPref().put(DefaultProxySelector.PROXY_USER, credentials.getUserName());
087            if (credentials.getPassword() == null) {
088                Config.getPref().put(DefaultProxySelector.PROXY_PASS, null);
089            } else {
090                Config.getPref().put(DefaultProxySelector.PROXY_PASS, String.valueOf(credentials.getPassword()));
091            }
092            break;
093        }
094    }
095
096    /**
097     * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
098     * Access Token is currently managed by this CredentialManager.
099     *
100     * @return the current OAuth Access Token to access the OSM server.
101     * @throws CredentialsAgentException if something goes wrong
102     */
103    @Override
104    public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
105        String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);
106        String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);
107        if (accessTokenKey == null && accessTokenSecret == null)
108            return null;
109        return new OAuthToken(accessTokenKey, accessTokenSecret);
110    }
111
112    /**
113     * Stores the OAuth Access Token <code>accessToken</code>.
114     *
115     * @param accessToken the access Token. null, to remove the Access Token.
116     * @throws CredentialsAgentException if something goes wrong
117     */
118    @Override
119    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
120        if (accessToken == null) {
121            Config.getPref().put("oauth.access-token.key", null);
122            Config.getPref().put("oauth.access-token.secret", null);
123        } else {
124            Config.getPref().put("oauth.access-token.key", accessToken.getKey());
125            Config.getPref().put("oauth.access-token.secret", accessToken.getSecret());
126        }
127    }
128
129    @Override
130    public Component getPreferencesDecorationPanel() {
131        HtmlPanel pnlMessage = new HtmlPanel();
132        HTMLEditorKit kit = (HTMLEditorKit) pnlMessage.getEditorPane().getEditorKit();
133        kit.getStyleSheet().addRule(
134                ".warning-body {background-color:rgb(253,255,221);padding: 10pt; " +
135                "border-color:rgb(128,128,128);border-style: solid;border-width: 1px;}");
136        pnlMessage.setText(tr(
137                        "<html><body>"
138                        + "<p class=\"warning-body\">"
139                        + "<strong>Warning:</strong> The password is stored in plain text in the JOSM preferences file. "
140                        + "Furthermore, it is transferred <strong>unencrypted</strong> in every request sent to the OSM server. "
141                        + "<strong>Do not use a valuable password.</strong>"
142                        + "</p>"
143                        + "</body></html>"
144                )
145        );
146        return pnlMessage;
147    }
148
149    @Override
150    public String getSaveUsernameAndPasswordCheckboxText() {
151        return tr("Save user and password (unencrypted)");
152    }
153}