source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java@ 18828

Last change on this file since 18828 was 18828, checked in by taylor.smock, 9 months ago

See #22810: OSM OAuth 1.0a/Basic auth deprecation and removal

This prevents users from using Basic Authentication or OAuth 1.0a unless one of the following is true:

  • They were previously using the authentication method
  • They have enabled Expert Mode
  • They are not using the default OSM API
  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.server;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.FlowLayout;
8import java.awt.GridBagConstraints;
9import java.awt.GridBagLayout;
10import java.awt.Insets;
11import java.awt.event.ItemEvent;
12import java.awt.event.ItemListener;
13import java.beans.PropertyChangeEvent;
14import java.beans.PropertyChangeListener;
15
16import javax.swing.ButtonGroup;
17import javax.swing.JPanel;
18import javax.swing.JRadioButton;
19
20import org.openstreetmap.josm.actions.ExpertToggleAction;
21import org.openstreetmap.josm.data.UserIdentityManager;
22import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
23import org.openstreetmap.josm.data.oauth.OAuthVersion;
24import org.openstreetmap.josm.data.preferences.JosmUrls;
25import org.openstreetmap.josm.gui.help.HelpUtil;
26import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
27import org.openstreetmap.josm.io.OsmApi;
28import org.openstreetmap.josm.io.auth.CredentialsManager;
29import org.openstreetmap.josm.spi.preferences.Config;
30import org.openstreetmap.josm.tools.GBC;
31import org.openstreetmap.josm.tools.Logging;
32
33/**
34 * This is the preference panel for the authentication method and the authentication parameters.
35 * @since 2745
36 */
37public class AuthenticationPreferencesPanel extends VerticallyScrollablePanel implements PropertyChangeListener {
38
39 /** indicates whether we use basic authentication */
40 private final JRadioButton rbBasicAuthentication = new JRadioButton();
41 /** indicates whether we use OAuth 1.0a as authentication scheme */
42 private final JRadioButton rbOAuth = new JRadioButton();
43 /** indicates whether we use OAuth 2.0 as authentication scheme */
44 private final JRadioButton rbOAuth20 = new JRadioButton();
45 /** the panel which contains the authentication parameters for the respective authentication scheme */
46 private final JPanel pnlAuthenticationParameters = new JPanel(new BorderLayout());
47 /** the panel for the basic authentication parameters */
48 private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences;
49 /** the panel for the OAuth 1.0a authentication parameters */
50 private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;
51 /** the panel for the OAuth 2.0 authentication parameters */
52 private OAuthAuthenticationPreferencesPanel pnlOAuth20Preferences;
53
54 /** Used to determine which API we are using for disabling/enabling Basic Auth/OAuth 1.0a */
55 private String apiUrl = OsmApi.getOsmApi().getServerUrl();
56 /** ExpertToggleAction uses weak references; we don't want this listener to be garbage collected */
57 private final ExpertToggleAction.ExpertModeChangeListener expertModeChangeListener = isExpert -> {
58 final String authMethod = OsmApi.getAuthMethod();
59 final boolean defaultApi = JosmUrls.getInstance().getDefaultOsmApiUrl().equals(apiUrl);
60 rbBasicAuthentication.setEnabled(rbBasicAuthentication.isSelected() || "basic".equals(authMethod) || isExpert || !defaultApi);
61 rbOAuth.setEnabled(rbOAuth.isSelected() || "oauth".equals(authMethod) || isExpert || !defaultApi);
62 };
63
64 /**
65 * Constructs a new {@code AuthenticationPreferencesPanel}.
66 */
67 public AuthenticationPreferencesPanel() {
68 build();
69 initFromPreferences();
70 HelpUtil.setHelpContext(this, HelpUtil.ht("/Preferences/Connection#AuthenticationSettings"));
71 }
72
73 /**
74 * builds the UI
75 */
76 protected final void build() {
77 setLayout(new GridBagLayout());
78
79 AuthenticationMethodChangeListener authChangeListener = new AuthenticationMethodChangeListener();
80
81 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
82 // -- radio button for basic authentication
83 buttonPanel.add(rbBasicAuthentication);
84 rbBasicAuthentication.setText(tr("Use Basic Authentication"));
85 rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password"));
86 rbBasicAuthentication.addItemListener(authChangeListener);
87
88 //-- radio button for OAuth 1.0a
89 buttonPanel.add(rbOAuth);
90 rbOAuth.setText(tr("Use OAuth {0}", "1.0a"));
91 rbOAuth.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "1.0a"));
92 rbOAuth.addItemListener(authChangeListener);
93
94 //-- radio button for OAuth 2.0
95 buttonPanel.add(rbOAuth20);
96 rbOAuth20.setText(tr("Use OAuth {0}", "2.0"));
97 rbOAuth20.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "2.0"));
98 rbOAuth20.addItemListener(authChangeListener);
99
100 add(buttonPanel, GBC.eol());
101 //-- radio button for OAuth
102 ButtonGroup bg = new ButtonGroup();
103 bg.add(rbBasicAuthentication);
104 bg.add(rbOAuth);
105 bg.add(rbOAuth20);
106
107 //-- add the panel which will hold the authentication parameters
108 GridBagConstraints gc = new GridBagConstraints();
109 gc.anchor = GridBagConstraints.NORTHWEST;
110 gc.insets = new Insets(0, 0, 0, 3);
111 gc.gridx = 0;
112 gc.gridy = 1;
113 gc.gridwidth = 2;
114 gc.fill = GridBagConstraints.BOTH;
115 gc.weightx = 1.0;
116 gc.weighty = 1.0;
117 add(pnlAuthenticationParameters, gc);
118
119 //-- the two panels for authentication parameters
120 pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel();
121 pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth10a);
122 pnlOAuth20Preferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth20);
123
124 ExpertToggleAction.addExpertModeChangeListener(expertModeChangeListener, true);
125
126 rbOAuth20.setSelected(true);
127 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER);
128 }
129
130 /**
131 * Initializes the panel from preferences
132 */
133 public final void initFromPreferences() {
134 final String authMethod = OsmApi.getAuthMethod();
135 switch (authMethod) {
136 case "basic":
137 rbBasicAuthentication.setSelected(true);
138 break;
139 case "oauth":
140 rbOAuth.setSelected(true);
141 break;
142 case "oauth20":
143 rbOAuth20.setSelected(true);
144 break;
145 default:
146 Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.",
147 "osm-server.auth-method", authMethod));
148 rbBasicAuthentication.setSelected(true);
149 }
150 pnlBasicAuthPreferences.initFromPreferences();
151 pnlOAuthPreferences.initFromPreferences();
152 pnlOAuth20Preferences.initFromPreferences();
153 }
154
155 /**
156 * Saves the current values to the preferences
157 */
158 public final void saveToPreferences() {
159 // save the authentication method
160 String authMethod;
161 if (rbBasicAuthentication.isSelected()) {
162 authMethod = "basic";
163 } else if (rbOAuth.isSelected()) {
164 authMethod = "oauth";
165 } else if (rbOAuth20.isSelected()) {
166 authMethod = "oauth20";
167 } else {
168 throw new IllegalStateException("One of OAuth 2.0, OAuth 1.0a, or Basic authentication must be checked");
169 }
170 final boolean initUser = Config.getPref().put("osm-server.auth-method", authMethod);
171 if ("basic".equals(authMethod)) {
172 // save username and password and clear the OAuth token
173 pnlBasicAuthPreferences.saveToPreferences();
174 OAuthAccessTokenHolder.getInstance().clear();
175 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
176 } else if ("oauth".equals(authMethod)) {
177 // clear the password in the preferences
178 pnlBasicAuthPreferences.clearPassword();
179 pnlBasicAuthPreferences.saveToPreferences();
180 pnlOAuthPreferences.saveToPreferences();
181 } else { // oauth20
182 // clear the password in the preferences
183 pnlBasicAuthPreferences.clearPassword();
184 pnlBasicAuthPreferences.saveToPreferences();
185 pnlOAuth20Preferences.saveToPreferences();
186 }
187 if (initUser) {
188 if ("basic".equals(authMethod)) {
189 UserIdentityManager.getInstance().initFromPreferences();
190 } else {
191 UserIdentityManager.getInstance().initFromOAuth();
192 }
193 }
194 ExpertToggleAction.removeExpertModeChangeListener(this.expertModeChangeListener);
195 }
196
197 /**
198 * Listens to changes in the authentication method
199 */
200 class AuthenticationMethodChangeListener implements ItemListener {
201 @Override
202 public void itemStateChanged(ItemEvent e) {
203 pnlAuthenticationParameters.removeAll();
204 if (rbBasicAuthentication.isSelected()) {
205 pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
206 pnlBasicAuthPreferences.revalidate();
207 } else if (rbOAuth.isSelected()) {
208 pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER);
209 pnlOAuthPreferences.saveToPreferences();
210 pnlOAuthPreferences.initFromPreferences();
211 pnlOAuthPreferences.revalidate();
212 } else if (rbOAuth20.isSelected()) {
213 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER);
214 pnlOAuth20Preferences.saveToPreferences();
215 pnlOAuth20Preferences.initFromPreferences();
216 pnlOAuth20Preferences.revalidate();
217 }
218 repaint();
219 }
220 }
221
222 @Override
223 public void propertyChange(PropertyChangeEvent evt) {
224 if (pnlOAuthPreferences != null) {
225 pnlOAuthPreferences.propertyChange(evt);
226 }
227 if (pnlOAuth20Preferences != null) {
228 pnlOAuth20Preferences.propertyChange(evt);
229 }
230 if (OsmApiUrlInputPanel.API_URL_PROP.equals(evt.getPropertyName())) {
231 this.apiUrl = (String) evt.getNewValue();
232 this.expertModeChangeListener.expertChanged(ExpertToggleAction.isExpert());
233 }
234 }
235}
Note: See TracBrowser for help on using the repository browser.