Changeset 18650 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2023-02-08T18:31:58+01:00 (22 months ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 13 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java
r18211 r18650 6 6 import java.text.MessageFormat; 7 7 8 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;9 8 import org.openstreetmap.josm.data.osm.User; 10 9 import org.openstreetmap.josm.data.osm.UserInfo; … … 69 68 if (instance == null) { 70 69 instance = new UserIdentityManager(); 71 if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() && 72 !NetworkManager.isOffline(OnlineResource.OSM_API)) { 70 if (OsmApi.isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi()) && !NetworkManager.isOffline(OnlineResource.OSM_API)) { 73 71 try { 74 72 instance.initFromOAuth(); … … 306 304 break; 307 305 default: // Do nothing 308 } 306 if (evt.getKey() != null && evt.getKey().equals("oauth.access-token.parameters.OAuth20." + OsmApi.getOsmApi().getHost())) { 307 accessTokenKeyChanged = true; 308 accessTokenSecretChanged = true; 309 } 310 } 311 // oauth.access-token.parameters.OAuth20.api.openstreetmap.org 309 312 310 313 if (accessTokenKeyChanged && accessTokenSecretChanged) { -
trunk/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
r13173 r18650 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.net.URI; 7 import java.util.EnumMap; 8 import java.util.HashMap; 9 import java.util.Map; 10 import java.util.Objects; 11 import java.util.Optional; 12 6 13 import org.openstreetmap.josm.io.auth.CredentialsAgent; 7 14 import org.openstreetmap.josm.io.auth.CredentialsAgentException; 15 import org.openstreetmap.josm.io.auth.CredentialsManager; 8 16 import org.openstreetmap.josm.spi.preferences.Config; 9 17 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 32 40 private String accessTokenSecret; 33 41 42 private final Map<String, Map<OAuthVersion, IOAuthToken>> tokenMap = new HashMap<>(); 43 34 44 /** 35 45 * Replies true if current access token should be saved to the preferences file. … … 101 111 return null; 102 112 return new OAuthToken(accessTokenKey, accessTokenSecret); 113 } 114 115 /** 116 * Replies the access token. 117 * @param api The api the token is for 118 * @param version The OAuth version the token is for 119 * @return the access token, can be {@code null} 120 * @since 18650 121 */ 122 public IOAuthToken getAccessToken(String api, OAuthVersion version) { 123 api = URI.create(api).getHost(); 124 if (this.tokenMap.containsKey(api)) { 125 Map<OAuthVersion, IOAuthToken> map = this.tokenMap.get(api); 126 return map.get(version); 127 } 128 try { 129 IOAuthToken token = CredentialsManager.getInstance().lookupOAuthAccessToken(api); 130 // We *do* want to set the API token to null, if it doesn't exist. Just to avoid unnecessary lookups. 131 this.setAccessToken(api, token); 132 return token; 133 } catch (CredentialsAgentException exception) { 134 Logging.trace(exception); 135 } 136 return null; 103 137 } 104 138 … … 126 160 this.accessTokenKey = token.getKey(); 127 161 this.accessTokenSecret = token.getSecret(); 162 } 163 } 164 165 /** 166 * Sets the access token hold by this holder. 167 * 168 * @param api The api the token is for 169 * @param token the access token. Can be null to clear the content in this holder. 170 * @since 18650 171 */ 172 public void setAccessToken(String api, IOAuthToken token) { 173 Objects.requireNonNull(api, "api url"); 174 // Sometimes the api might be sent as the host 175 api = Optional.ofNullable(URI.create(api).getHost()).orElse(api); 176 if (token == null) { 177 if (this.tokenMap.containsKey(api)) { 178 this.tokenMap.get(api).clear(); 179 } 180 } else { 181 this.tokenMap.computeIfAbsent(api, key -> new EnumMap<>(OAuthVersion.class)).put(token.getOAuthType(), token); 128 182 } 129 183 } … … 176 230 if (!saveToPreferences) { 177 231 cm.storeOAuthAccessToken(null); 232 for (String host : this.tokenMap.keySet()) { 233 cm.storeOAuthAccessToken(host, null); 234 } 178 235 } else { 179 cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret)); 236 if (this.accessTokenKey != null && this.accessTokenSecret != null) { 237 cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret)); 238 } 239 for (Map.Entry<String, Map<OAuthVersion, IOAuthToken>> entry : this.tokenMap.entrySet()) { 240 if (entry.getValue().isEmpty()) { 241 cm.storeOAuthAccessToken(entry.getKey(), null); 242 continue; 243 } 244 for (OAuthVersion version : OAuthVersion.values()) { 245 if (entry.getValue().containsKey(version)) { 246 cm.storeOAuthAccessToken(entry.getKey(), entry.getValue().get(version)); 247 } 248 } 249 } 180 250 } 181 251 } catch (CredentialsAgentException e) { -
trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
r15009 r18650 2 2 package org.openstreetmap.josm.data.oauth; 3 3 4 import java.io.BufferedReader; 5 import java.io.IOException; 6 import java.net.URL; 4 7 import java.util.Objects; 5 8 9 import javax.json.Json; 10 import javax.json.JsonObject; 11 import javax.json.JsonReader; 12 import javax.json.JsonStructure; 13 import javax.json.JsonValue; 14 15 import org.openstreetmap.josm.io.OsmApi; 16 import org.openstreetmap.josm.io.auth.CredentialsAgentException; 17 import org.openstreetmap.josm.io.auth.CredentialsManager; 6 18 import org.openstreetmap.josm.spi.preferences.Config; 7 19 import org.openstreetmap.josm.spi.preferences.IUrls; 8 20 import org.openstreetmap.josm.tools.CheckParameterUtil; 21 import org.openstreetmap.josm.tools.HttpClient; 22 import org.openstreetmap.josm.tools.Logging; 9 23 import org.openstreetmap.josm.tools.Utils; 10 24 … … 16 30 * @since 2747 17 31 */ 18 public class OAuthParameters {32 public class OAuthParameters implements IOAuthParameters { 19 33 20 34 /** … … 47 61 */ 48 62 public static OAuthParameters createDefault(String apiUrl) { 63 return (OAuthParameters) createDefault(apiUrl, OAuthVersion.OAuth10a); 64 } 65 66 /** 67 * Replies a set of default parameters for a consumer accessing an OSM server 68 * at the given API url. URL parameters are only set if the URL equals {@link IUrls#getDefaultOsmApiUrl} 69 * or references the domain "dev.openstreetmap.org", otherwise they may be <code>null</code>. 70 * 71 * @param apiUrl The API URL for which the OAuth default parameters are created. If null or empty, the default OSM API url is used. 72 * @param oAuthVersion The OAuth version to create default parameters for 73 * @return a set of default parameters for the given {@code apiUrl} 74 * @since 18650 75 */ 76 public static IOAuthParameters createDefault(String apiUrl, OAuthVersion oAuthVersion) { 77 if (!Utils.isValidUrl(apiUrl)) { 78 apiUrl = null; 79 } 80 81 switch (oAuthVersion) { 82 case OAuth10a: 83 return getDefaultOAuth10Parameters(apiUrl); 84 case OAuth20: 85 case OAuth21: // For now, OAuth 2.1 (draft) is just OAuth 2.0 with mandatory extensions, which we implement. 86 return getDefaultOAuth20Parameters(apiUrl); 87 default: 88 throw new IllegalArgumentException("Unknown OAuth version: " + oAuthVersion); 89 } 90 } 91 92 /** 93 * Get the default OAuth 2.0 parameters 94 * @param apiUrl The API url 95 * @return The default parameters 96 */ 97 private static OAuth20Parameters getDefaultOAuth20Parameters(String apiUrl) { 98 final String clientId; 99 final String clientSecret; 100 final String redirectUri; 101 final String baseUrl; 102 if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) { 103 clientId = ""; 104 clientSecret = ""; 105 baseUrl = apiUrl; 106 HttpClient client = null; 107 redirectUri = ""; 108 // Check if the server is RFC 8414 compliant 109 try { 110 client = HttpClient.create(new URL(apiUrl + (apiUrl.endsWith("/") ? "" : "/") + ".well-known/oauth-authorization-server")); 111 HttpClient.Response response = client.connect(); 112 if (response.getResponseCode() == 200) { 113 try (BufferedReader reader = response.getContentReader(); 114 JsonReader jsonReader = Json.createReader(reader)) { 115 JsonStructure structure = jsonReader.read(); 116 if (structure.getValueType() == JsonValue.ValueType.OBJECT) { 117 return parseAuthorizationServerMetadataResponse(clientId, clientSecret, apiUrl, 118 redirectUri, structure.asJsonObject()); 119 } 120 } 121 } 122 } catch (IOException | OAuthException e) { 123 Logging.trace(e); 124 } finally { 125 if (client != null) client.disconnect(); 126 } 127 } else { 128 clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI"; 129 // We don't actually use the client secret in our authorization flow. 130 clientSecret = null; 131 baseUrl = "https://www.openstreetmap.org/oauth2"; 132 redirectUri = "http://127.0.0.1:8111/oauth_authorization"; 133 apiUrl = OsmApi.getOsmApi().getBaseUrl(); 134 } 135 return new OAuth20Parameters(clientId, clientSecret, baseUrl, apiUrl, redirectUri); 136 } 137 138 /** 139 * Parse the response from <a href="https://www.rfc-editor.org/rfc/rfc8414.html">RFC 8414</a> 140 * (OAuth 2.0 Authorization Server Metadata) 141 * @return The parameters for the server metadata 142 */ 143 private static OAuth20Parameters parseAuthorizationServerMetadataResponse(String clientId, String clientSecret, 144 String apiUrl, String redirectUri, 145 JsonObject serverMetadata) 146 throws OAuthException { 147 final String authorizationEndpoint = serverMetadata.getString("authorization_endpoint", null); 148 final String tokenEndpoint = serverMetadata.getString("token_endpoint", null); 149 // This may also have additional documentation like what the endpoints allow (e.g. scopes, algorithms, etc.) 150 if (authorizationEndpoint == null || tokenEndpoint == null) { 151 throw new OAuth20Exception("Either token endpoint or authorization endpoints are missing"); 152 } 153 return new OAuth20Parameters(clientId, clientSecret, tokenEndpoint, authorizationEndpoint, apiUrl, redirectUri); 154 } 155 156 /** 157 * Get the default OAuth 1.0a parameters 158 * @param apiUrl The api url 159 * @return The default parameters 160 */ 161 private static OAuthParameters getDefaultOAuth10Parameters(String apiUrl) { 49 162 final String consumerKey; 50 163 final String consumerSecret; 51 164 final String serverUrl; 52 53 if (!Utils.isValidUrl(apiUrl)) {54 apiUrl = null;55 }56 165 57 166 if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) { … … 82 191 */ 83 192 public static OAuthParameters createFromApiUrl(String apiUrl) { 84 OAuthParameters parameters = createDefault(apiUrl); 85 return new OAuthParameters( 86 Config.getPref().get("oauth.settings.consumer-key", parameters.getConsumerKey()), 87 Config.getPref().get("oauth.settings.consumer-secret", parameters.getConsumerSecret()), 88 Config.getPref().get("oauth.settings.request-token-url", parameters.getRequestTokenUrl()), 89 Config.getPref().get("oauth.settings.access-token-url", parameters.getAccessTokenUrl()), 90 Config.getPref().get("oauth.settings.authorise-url", parameters.getAuthoriseUrl()), 91 Config.getPref().get("oauth.settings.osm-login-url", parameters.getOsmLoginUrl()), 92 Config.getPref().get("oauth.settings.osm-logout-url", parameters.getOsmLogoutUrl())); 193 return (OAuthParameters) createFromApiUrl(apiUrl, OAuthVersion.OAuth10a); 194 } 195 196 /** 197 * Replies a set of parameters as defined in the preferences. 198 * 199 * @param oAuthVersion The OAuth version to use. 200 * @param apiUrl the API URL. Must not be {@code null}. 201 * @return the parameters 202 * @since 18650 203 */ 204 public static IOAuthParameters createFromApiUrl(String apiUrl, OAuthVersion oAuthVersion) { 205 IOAuthParameters parameters = createDefault(apiUrl, oAuthVersion); 206 switch (oAuthVersion) { 207 case OAuth10a: 208 OAuthParameters oauth10aParameters = (OAuthParameters) parameters; 209 return new OAuthParameters( 210 Config.getPref().get("oauth.settings.consumer-key", oauth10aParameters.getConsumerKey()), 211 Config.getPref().get("oauth.settings.consumer-secret", oauth10aParameters.getConsumerSecret()), 212 Config.getPref().get("oauth.settings.request-token-url", oauth10aParameters.getRequestTokenUrl()), 213 Config.getPref().get("oauth.settings.access-token-url", oauth10aParameters.getAccessTokenUrl()), 214 Config.getPref().get("oauth.settings.authorise-url", oauth10aParameters.getAuthoriseUrl()), 215 Config.getPref().get("oauth.settings.osm-login-url", oauth10aParameters.getOsmLoginUrl()), 216 Config.getPref().get("oauth.settings.osm-logout-url", oauth10aParameters.getOsmLogoutUrl())); 217 case OAuth20: 218 case OAuth21: // Right now, OAuth 2.1 will work with our OAuth 2.0 implementation 219 OAuth20Parameters oAuth20Parameters = (OAuth20Parameters) parameters; 220 try { 221 IOAuthToken storedToken = CredentialsManager.getInstance().lookupOAuthAccessToken(apiUrl); 222 return storedToken != null ? storedToken.getParameters() : oAuth20Parameters; 223 } catch (CredentialsAgentException e) { 224 Logging.trace(e); 225 } 226 return oAuth20Parameters; 227 default: 228 throw new IllegalArgumentException("Unknown OAuth version: " + oAuthVersion); 229 } 93 230 } 94 231 … … 96 233 * Remembers the current values in the preferences. 97 234 */ 235 @Override 98 236 public void rememberPreferences() { 99 237 Config.getPref().put("oauth.settings.consumer-key", getConsumerKey()); … … 183 321 * @return The access token URL 184 322 */ 323 @Override 185 324 public String getAccessTokenUrl() { 186 325 return accessTokenUrl; 187 326 } 188 327 328 @Override 329 public String getAuthorizationUrl() { 330 return this.authoriseUrl; 331 } 332 333 @Override 334 public OAuthVersion getOAuthVersion() { 335 return OAuthVersion.OAuth10a; 336 } 337 338 @Override 339 public String getClientId() { 340 return this.consumerKey; 341 } 342 343 @Override 344 public String getClientSecret() { 345 return this.consumerSecret; 346 } 347 189 348 /** 190 349 * Gets the authorise URL. … … 192 351 */ 193 352 public String getAuthoriseUrl() { 194 return authoriseUrl;353 return this.getAuthorizationUrl(); 195 354 } 196 355 -
trunk/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java
r16553 r18650 4 4 import java.util.Objects; 5 5 6 import org.openstreetmap.josm.data.oauth.IOAuthParameters; 6 7 import org.openstreetmap.josm.data.oauth.OAuthParameters; 7 8 import org.openstreetmap.josm.data.oauth.OAuthToken; 9 import org.openstreetmap.josm.data.oauth.OAuthVersion; 8 10 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; 9 11 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 21 23 22 24 private String apiUrl; 23 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel( );25 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(OAuthVersion.OAuth10a); 24 26 private transient OAuthToken accessToken; 25 27 … … 80 82 * @return the current set of advanced OAuth parameters in this UI 81 83 */ 82 public OAuthParameters getOAuthParameters() {84 public IOAuthParameters getOAuthParameters() { 83 85 return pnlAdvancedProperties.getAdvancedParameters(); 84 86 } -
trunk/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java
r15586 r18650 16 16 import javax.swing.JOptionPane; 17 17 18 import org.openstreetmap.josm.data.oauth.IOAuthParameters; 19 import org.openstreetmap.josm.data.oauth.OAuth20Parameters; 18 20 import org.openstreetmap.josm.data.oauth.OAuthParameters; 21 import org.openstreetmap.josm.data.oauth.OAuthVersion; 19 22 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 20 23 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; … … 52 55 private final JosmTextField tfOsmLoginURL = new JosmTextField(); 53 56 private final JosmTextField tfOsmLogoutURL = new JosmTextField(); 57 private final OAuthVersion oauthVersion; 54 58 private transient UseDefaultItemListener ilUseDefault; 55 59 private String apiUrl; … … 57 61 /** 58 62 * Constructs a new {@code AdvancedOAuthPropertiesPanel}. 59 */ 60 public AdvancedOAuthPropertiesPanel() { 63 * @param oauthVersion The OAuth version to make the panel for 64 */ 65 public AdvancedOAuthPropertiesPanel(OAuthVersion oauthVersion) { 66 this.oauthVersion = oauthVersion; 61 67 build(); 62 68 } … … 71 77 gc.weightx = 1.0; 72 78 gc.insets = new Insets(0, 0, 3, 3); 73 gc.gridwidth = 2;79 gc.gridwidth = 3; 74 80 add(cbUseDefaults, gc); 75 81 … … 78 84 gc.weightx = 0.0; 79 85 gc.gridwidth = 1; 80 add(new JLabel(tr("Consumer Key:")), gc); 86 if (this.oauthVersion == OAuthVersion.OAuth10a) { 87 add(new JLabel(tr("Consumer Key:")), gc); 88 } else { 89 add(new JLabel(tr("Client ID:")), gc); 90 } 81 91 82 92 gc.gridx = 1; … … 86 96 87 97 // -- consumer secret 88 gc.gridy = 2;98 gc.gridy++; 89 99 gc.gridx = 0; 90 100 gc.weightx = 0.0; 91 add(new JLabel(tr("Consumer Secret:")), gc); 101 if (this.oauthVersion == OAuthVersion.OAuth10a) { 102 add(new JLabel(tr("Consumer Secret:")), gc); 103 } else { 104 add(new JLabel(tr("Client Secret:")), gc); 105 } 92 106 93 107 gc.gridx = 1; … … 97 111 98 112 // -- request token URL 99 gc.gridy = 3;113 gc.gridy++; 100 114 gc.gridx = 0; 101 115 gc.weightx = 0.0; 102 add(new JLabel(tr("Request Token URL:")), gc); 116 if (this.oauthVersion == OAuthVersion.OAuth10a) { 117 add(new JLabel(tr("Request Token URL:")), gc); 118 } else { 119 add(new JLabel(tr("Redirect URL:")), gc); 120 } 103 121 104 122 gc.gridx = 1; … … 108 126 109 127 // -- access token URL 110 gc.gridy = 4;128 gc.gridy++; 111 129 gc.gridx = 0; 112 130 gc.weightx = 0.0; … … 119 137 120 138 // -- authorise URL 121 gc.gridy = 5;139 gc.gridy++; 122 140 gc.gridx = 0; 123 141 gc.weightx = 0.0; … … 129 147 SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL); 130 148 131 // -- OSM login URL 132 gc.gridy = 6; 133 gc.gridx = 0; 134 gc.weightx = 0.0; 135 add(new JLabel(tr("OSM login URL:")), gc); 136 137 gc.gridx = 1; 138 gc.weightx = 1.0; 139 add(tfOsmLoginURL, gc); 140 SelectAllOnFocusGainedDecorator.decorate(tfOsmLoginURL); 141 142 // -- OSM logout URL 143 gc.gridy = 7; 144 gc.gridx = 0; 145 gc.weightx = 0.0; 146 add(new JLabel(tr("OSM logout URL:")), gc); 147 148 gc.gridx = 1; 149 gc.weightx = 1.0; 150 add(tfOsmLogoutURL, gc); 151 SelectAllOnFocusGainedDecorator.decorate(tfOsmLogoutURL); 149 if (this.oauthVersion == OAuthVersion.OAuth10a) { 150 // -- OSM login URL 151 gc.gridy++; 152 gc.gridx = 0; 153 gc.weightx = 0.0; 154 add(new JLabel(tr("OSM login URL:")), gc); 155 156 gc.gridx = 1; 157 gc.weightx = 1.0; 158 add(tfOsmLoginURL, gc); 159 SelectAllOnFocusGainedDecorator.decorate(tfOsmLoginURL); 160 161 // -- OSM logout URL 162 gc.gridy++; 163 gc.gridx = 0; 164 gc.weightx = 0.0; 165 add(new JLabel(tr("OSM logout URL:")), gc); 166 167 gc.gridx = 1; 168 gc.weightx = 1.0; 169 add(tfOsmLogoutURL, gc); 170 SelectAllOnFocusGainedDecorator.decorate(tfOsmLogoutURL); 171 } 152 172 153 173 ilUseDefault = new UseDefaultItemListener(); … … 192 212 protected void resetToDefaultSettings() { 193 213 cbUseDefaults.setSelected(true); 194 OAuthParameters params = OAuthParameters.createDefault(apiUrl); 195 tfConsumerKey.setText(params.getConsumerKey()); 196 tfConsumerSecret.setText(params.getConsumerSecret()); 197 tfRequestTokenURL.setText(params.getRequestTokenUrl()); 198 tfAccessTokenURL.setText(params.getAccessTokenUrl()); 199 tfAuthoriseURL.setText(params.getAuthoriseUrl()); 200 tfOsmLoginURL.setText(params.getOsmLoginUrl()); 201 tfOsmLogoutURL.setText(params.getOsmLogoutUrl()); 214 IOAuthParameters iParams = OAuthParameters.createDefault(apiUrl, this.oauthVersion); 215 switch (this.oauthVersion) { 216 case OAuth10a: 217 OAuthParameters params = (OAuthParameters) iParams; 218 tfConsumerKey.setText(params.getConsumerKey()); 219 tfConsumerSecret.setText(params.getConsumerSecret()); 220 tfRequestTokenURL.setText(params.getRequestTokenUrl()); 221 tfAccessTokenURL.setText(params.getAccessTokenUrl()); 222 tfAuthoriseURL.setText(params.getAuthoriseUrl()); 223 tfOsmLoginURL.setText(params.getOsmLoginUrl()); 224 tfOsmLogoutURL.setText(params.getOsmLogoutUrl()); 225 break; 226 case OAuth20: 227 case OAuth21: 228 OAuth20Parameters params20 = (OAuth20Parameters) iParams; 229 tfConsumerKey.setText(params20.getClientId()); 230 tfConsumerSecret.setText(params20.getClientSecret()); 231 tfAccessTokenURL.setText(params20.getAccessTokenUrl()); 232 tfAuthoriseURL.setText(params20.getAuthorizationUrl()); 233 tfRequestTokenURL.setText(params20.getRedirectUri()); 234 } 202 235 203 236 setChildComponentsEnabled(false); … … 217 250 * @return the OAuth parameters 218 251 */ 219 public OAuthParameters getAdvancedParameters() {252 public IOAuthParameters getAdvancedParameters() { 220 253 if (cbUseDefaults.isSelected()) 221 return OAuthParameters.createDefault(apiUrl); 222 return new OAuthParameters( 223 tfConsumerKey.getText(), 224 tfConsumerSecret.getText(), 225 tfRequestTokenURL.getText(), 226 tfAccessTokenURL.getText(), 227 tfAuthoriseURL.getText(), 228 tfOsmLoginURL.getText(), 229 tfOsmLogoutURL.getText()); 254 return OAuthParameters.createDefault(apiUrl, this.oauthVersion); 255 if (this.oauthVersion == OAuthVersion.OAuth10a) { 256 return new OAuthParameters( 257 tfConsumerKey.getText(), 258 tfConsumerSecret.getText(), 259 tfRequestTokenURL.getText(), 260 tfAccessTokenURL.getText(), 261 tfAuthoriseURL.getText(), 262 tfOsmLoginURL.getText(), 263 tfOsmLogoutURL.getText()); 264 } 265 return new OAuth20Parameters( 266 tfConsumerKey.getText(), 267 tfConsumerSecret.getText(), 268 tfAuthoriseURL.getText(), 269 tfAccessTokenURL.getText(), 270 tfRequestTokenURL.getText() 271 ); 230 272 } 231 273 … … 236 278 * @throws IllegalArgumentException if parameters is null. 237 279 */ 238 public void setAdvancedParameters( OAuthParameters parameters) {280 public void setAdvancedParameters(IOAuthParameters parameters) { 239 281 CheckParameterUtil.ensureParameterNotNull(parameters, "parameters"); 240 if (parameters.equals(OAuthParameters.createDefault(apiUrl ))) {282 if (parameters.equals(OAuthParameters.createDefault(apiUrl, parameters.getOAuthVersion()))) { 241 283 cbUseDefaults.setSelected(true); 242 284 setChildComponentsEnabled(false); … … 244 286 cbUseDefaults.setSelected(false); 245 287 setChildComponentsEnabled(true); 246 tfConsumerKey.setText(parameters.getConsumerKey() == null ? "" : parameters.getConsumerKey()); 247 tfConsumerSecret.setText(parameters.getConsumerSecret() == null ? "" : parameters.getConsumerSecret()); 248 tfRequestTokenURL.setText(parameters.getRequestTokenUrl() == null ? "" : parameters.getRequestTokenUrl()); 249 tfAccessTokenURL.setText(parameters.getAccessTokenUrl() == null ? "" : parameters.getAccessTokenUrl()); 250 tfAuthoriseURL.setText(parameters.getAuthoriseUrl() == null ? "" : parameters.getAuthoriseUrl()); 251 tfOsmLoginURL.setText(parameters.getOsmLoginUrl() == null ? "" : parameters.getOsmLoginUrl()); 252 tfOsmLogoutURL.setText(parameters.getOsmLogoutUrl() == null ? "" : parameters.getOsmLogoutUrl()); 288 if (parameters instanceof OAuthParameters) { 289 OAuthParameters parameters10 = (OAuthParameters) parameters; 290 tfConsumerKey.setText(parameters10.getConsumerKey() == null ? "" : parameters10.getConsumerKey()); 291 tfConsumerSecret.setText(parameters10.getConsumerSecret() == null ? "" : parameters10.getConsumerSecret()); 292 tfRequestTokenURL.setText(parameters10.getRequestTokenUrl() == null ? "" : parameters10.getRequestTokenUrl()); 293 tfAccessTokenURL.setText(parameters10.getAccessTokenUrl() == null ? "" : parameters10.getAccessTokenUrl()); 294 tfAuthoriseURL.setText(parameters10.getAuthoriseUrl() == null ? "" : parameters10.getAuthoriseUrl()); 295 tfOsmLoginURL.setText(parameters10.getOsmLoginUrl() == null ? "" : parameters10.getOsmLoginUrl()); 296 tfOsmLogoutURL.setText(parameters10.getOsmLogoutUrl() == null ? "" : parameters10.getOsmLogoutUrl()); 297 } else if (parameters instanceof OAuth20Parameters) { 298 OAuth20Parameters parameters20 = (OAuth20Parameters) parameters; 299 tfConsumerKey.setText(parameters20.getClientId()); 300 tfConsumerSecret.setText(parameters20.getClientSecret()); 301 tfAccessTokenURL.setText(parameters20.getAccessTokenUrl()); 302 tfAuthoriseURL.setText(parameters20.getAuthorizationUrl()); 303 tfRequestTokenURL.setText(parameters20.getRedirectUri()); 304 } 253 305 } 254 306 } -
trunk/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java
r17333 r18650 29 29 import javax.swing.text.html.HTMLEditorKit; 30 30 31 import org.openstreetmap.josm.data.oauth.OAuthParameters; 31 32 import org.openstreetmap.josm.data.oauth.OAuthToken; 32 33 import org.openstreetmap.josm.gui.HelpAwareOptionPane; … … 385 386 FullyAutomaticAuthorizationUI.this, 386 387 getApiUrl(), 387 getAdvancedPropertiesPanel().getAdvancedParameters(),388 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(), 388 389 getAccessToken() 389 390 )); … … 438 439 + "Please check your advanced setting and try again." 439 440 + "</html>", 440 getAdvancedPropertiesPanel().getAdvancedParameters().getAuthoriseUrl()),441 ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getAuthoriseUrl()), 441 442 tr("OAuth authorization failed"), 442 443 JOptionPane.ERROR_MESSAGE, … … 446 447 447 448 protected void alertLoginFailed() { 448 final String loginUrl = getAdvancedPropertiesPanel().getAdvancedParameters().getOsmLoginUrl();449 final String loginUrl = ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getOsmLoginUrl(); 449 450 HelpAwareOptionPane.showOptionDialog( 450 451 FullyAutomaticAuthorizationUI.this, … … 480 481 getProgressMonitor().setTicksCount(3); 481 482 OsmOAuthAuthorizationClient authClient = new OsmOAuthAuthorizationClient( 482 getAdvancedPropertiesPanel().getAdvancedParameters()483 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters() 483 484 ); 484 485 OAuthToken requestToken = authClient.getRequestToken( -
trunk/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java
r15662 r18650 26 26 27 27 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 28 import org.openstreetmap.josm.data.oauth.OAuthParameters; 28 29 import org.openstreetmap.josm.data.oauth.OAuthToken; 29 30 import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator; … … 233 234 ManualAuthorizationUI.this, 234 235 getApiUrl(), 235 getAdvancedPropertiesPanel().getAdvancedParameters(),236 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(), 236 237 getAccessToken() 237 238 ); -
trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
r17600 r18650 256 256 */ 257 257 public OAuthParameters getOAuthParameters() { 258 return getCurrentAuthorisationUI().getOAuthParameters();258 return (OAuthParameters) getCurrentAuthorisationUI().getOAuthParameters(); 259 259 } 260 260 -
trunk/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java
r17333 r18650 23 23 24 24 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 25 import org.openstreetmap.josm.data.oauth.OAuthParameters; 25 26 import org.openstreetmap.josm.data.oauth.OAuthToken; 26 27 import org.openstreetmap.josm.gui.util.GuiHelper; … … 79 80 protected void transitionToRetrieveAccessToken() { 80 81 OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient( 81 getAdvancedPropertiesPanel().getAdvancedParameters()82 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters() 82 83 ); 83 84 String authoriseUrl = client.getAuthoriseUrl(requestToken); … … 184 185 + "''{1}''.</html>", 185 186 tr("Retrieve Request Token"), 186 getAdvancedPropertiesPanel().getAdvancedParameters().getRequestTokenUrl()187 ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getRequestTokenUrl() 187 188 )); 188 189 pnl.add(h, gc); … … 391 392 final RetrieveRequestTokenTask task = new RetrieveRequestTokenTask( 392 393 SemiAutomaticAuthorizationUI.this, 393 getAdvancedPropertiesPanel().getAdvancedParameters()394 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters() 394 395 ); 395 396 executor.execute(task); … … 419 420 final RetrieveAccessTokenTask task = new RetrieveAccessTokenTask( 420 421 SemiAutomaticAuthorizationUI.this, 421 getAdvancedPropertiesPanel().getAdvancedParameters(),422 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(), 422 423 requestToken 423 424 ); … … 451 452 SemiAutomaticAuthorizationUI.this, 452 453 getApiUrl(), 453 getAdvancedPropertiesPanel().getAdvancedParameters(),454 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(), 454 455 getAccessToken() 455 456 ); -
trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java
r17768 r18650 236 236 Map<String, Setting<?>> orig = Preferences.main().getAllSettings(); 237 237 Map<String, Setting<?>> defaults = tmpPrefs.getAllDefaults(); 238 orig.remove("osm-server.password");239 defaults.remove("osm-server.password");238 Preferences.main().getSensitive().forEach(orig::remove); 239 tmpPrefs.getSensitive().forEach(defaults::remove); 240 240 if (tmpPrefs != Preferences.main()) { 241 241 loaded = tmpPrefs.getAllSettings(); -
trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java
r17333 r18650 5 5 6 6 import java.awt.BorderLayout; 7 import java.awt.FlowLayout; 7 8 import java.awt.GridBagConstraints; 8 9 import java.awt.GridBagLayout; … … 18 19 19 20 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 21 import org.openstreetmap.josm.data.oauth.OAuthVersion; 20 22 import org.openstreetmap.josm.gui.help.HelpUtil; 21 23 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; … … 23 25 import org.openstreetmap.josm.io.auth.CredentialsManager; 24 26 import org.openstreetmap.josm.spi.preferences.Config; 27 import org.openstreetmap.josm.tools.GBC; 25 28 import org.openstreetmap.josm.tools.Logging; 26 29 … … 33 36 /** indicates whether we use basic authentication */ 34 37 private final JRadioButton rbBasicAuthentication = new JRadioButton(); 35 /** indicates whether we use OAuth as authentication scheme */38 /** indicates whether we use OAuth 1.0a as authentication scheme */ 36 39 private final JRadioButton rbOAuth = new JRadioButton(); 40 /** indicates whether we use OAuth 2.0 as authentication scheme */ 41 private final JRadioButton rbOAuth20 = new JRadioButton(); 37 42 /** the panel which contains the authentication parameters for the respective authentication scheme */ 38 43 private final JPanel pnlAuthenticationParameters = new JPanel(new BorderLayout()); 39 44 /** the panel for the basic authentication parameters */ 40 45 private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences; 41 /** the panel for the OAuth authentication parameters */46 /** the panel for the OAuth 1.0a authentication parameters */ 42 47 private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences; 48 /** the panel for the OAuth 2.0 authentication parameters */ 49 private OAuthAuthenticationPreferencesPanel pnlOAuth20Preferences; 43 50 44 51 /** … … 56 63 protected final void build() { 57 64 setLayout(new GridBagLayout()); 58 GridBagConstraints gc = new GridBagConstraints();59 65 60 66 AuthenticationMethodChangeListener authChangeListener = new AuthenticationMethodChangeListener(); 61 67 68 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); 62 69 // -- radio button for basic authentication 63 gc.anchor = GridBagConstraints.NORTHWEST; 64 gc.fill = GridBagConstraints.HORIZONTAL; 65 gc.gridx = 1; 66 gc.weightx = 1.0; 67 gc.insets = new Insets(0, 0, 0, 3); 68 add(rbBasicAuthentication, gc); 70 buttonPanel.add(rbBasicAuthentication); 69 71 rbBasicAuthentication.setText(tr("Use Basic Authentication")); 70 72 rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password")); 71 73 rbBasicAuthentication.addItemListener(authChangeListener); 72 74 73 //-- radio button for OAuth 74 gc.gridx = 0; 75 gc.weightx = 0.0; 76 add(rbOAuth, gc); 77 rbOAuth.setText(tr("Use OAuth")); 78 rbOAuth.setToolTipText(tr("Select to use OAuth as authentication mechanism")); 75 //-- radio button for OAuth 1.0a 76 buttonPanel.add(rbOAuth); 77 rbOAuth.setText(tr("Use OAuth {0}", "1.0a")); 78 rbOAuth.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "1.0a")); 79 79 rbOAuth.addItemListener(authChangeListener); 80 80 81 //-- radio button for OAuth 2.0 82 buttonPanel.add(rbOAuth20); 83 rbOAuth20.setText(tr("Use OAuth {0}", "2.0")); 84 rbOAuth20.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "2.0")); 85 rbOAuth20.addItemListener(authChangeListener); 86 87 add(buttonPanel, GBC.eol()); 81 88 //-- radio button for OAuth 82 89 ButtonGroup bg = new ButtonGroup(); 83 90 bg.add(rbBasicAuthentication); 84 91 bg.add(rbOAuth); 92 bg.add(rbOAuth20); 85 93 86 94 //-- add the panel which will hold the authentication parameters 95 GridBagConstraints gc = new GridBagConstraints(); 96 gc.anchor = GridBagConstraints.NORTHWEST; 97 gc.insets = new Insets(0, 0, 0, 3); 87 98 gc.gridx = 0; 88 99 gc.gridy = 1; … … 95 106 //-- the two panels for authentication parameters 96 107 pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel(); 97 pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(); 108 pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth10a); 109 pnlOAuth20Preferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth20); 98 110 99 111 rbBasicAuthentication.setSelected(true); … … 110 122 } else if ("oauth".equals(authMethod)) { 111 123 rbOAuth.setSelected(true); 124 } else if ("oauth20".equals(authMethod)) { 125 rbOAuth20.setSelected(true); 112 126 } else { 113 127 Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.", … … 117 131 pnlBasicAuthPreferences.initFromPreferences(); 118 132 pnlOAuthPreferences.initFromPreferences(); 133 pnlOAuth20Preferences.initFromPreferences(); 119 134 } 120 135 … … 127 142 if (rbBasicAuthentication.isSelected()) { 128 143 authMethod = "basic"; 144 } else if (rbOAuth.isSelected()) { 145 authMethod = "oauth"; 146 } else if (rbOAuth20.isSelected()) { 147 authMethod = "oauth20"; 129 148 } else { 130 authMethod = "oauth";149 throw new IllegalStateException("One of OAuth 2.0, OAuth 1.0a, or Basic authentication must be checked"); 131 150 } 132 151 Config.getPref().put("osm-server.auth-method", authMethod); … … 141 160 pnlBasicAuthPreferences.saveToPreferences(); 142 161 pnlOAuthPreferences.saveToPreferences(); 162 } else { // oauth20 163 // clear the password in the preferences 164 pnlBasicAuthPreferences.clearPassword(); 165 pnlBasicAuthPreferences.saveToPreferences(); 166 pnlOAuth20Preferences.saveToPreferences(); 143 167 } 144 168 } … … 150 174 @Override 151 175 public void itemStateChanged(ItemEvent e) { 176 pnlAuthenticationParameters.removeAll(); 152 177 if (rbBasicAuthentication.isSelected()) { 153 pnlAuthenticationParameters.removeAll();154 178 pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER); 155 179 pnlBasicAuthPreferences.revalidate(); 156 } else { 157 pnlAuthenticationParameters.removeAll(); 180 } else if (rbOAuth.isSelected()) { 158 181 pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER); 159 182 pnlOAuthPreferences.revalidate(); 183 } else if (rbOAuth20.isSelected()) { 184 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER); 185 pnlOAuth20Preferences.revalidate(); 160 186 } 161 187 repaint(); -
trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java
r17607 r18650 24 24 25 25 import org.openstreetmap.josm.actions.ExpertToggleAction; 26 import org.openstreetmap.josm.data.oauth.IOAuthToken; 27 import org.openstreetmap.josm.data.oauth.OAuth20Authorization; 28 import org.openstreetmap.josm.data.oauth.OAuth20Token; 26 29 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 27 30 import org.openstreetmap.josm.data.oauth.OAuthParameters; 28 31 import org.openstreetmap.josm.data.oauth.OAuthToken; 32 import org.openstreetmap.josm.data.oauth.OAuthVersion; 33 import org.openstreetmap.josm.data.oauth.osm.OsmScopes; 29 34 import org.openstreetmap.josm.gui.MainApplication; 30 35 import org.openstreetmap.josm.gui.oauth.AdvancedOAuthPropertiesPanel; … … 32 37 import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard; 33 38 import org.openstreetmap.josm.gui.oauth.TestAccessTokenTask; 39 import org.openstreetmap.josm.gui.util.GuiHelper; 34 40 import org.openstreetmap.josm.gui.widgets.JMultilineLabel; 35 41 import org.openstreetmap.josm.gui.widgets.JosmTextField; 36 42 import org.openstreetmap.josm.io.OsmApi; 37 43 import org.openstreetmap.josm.io.auth.CredentialsManager; 44 import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 38 45 import org.openstreetmap.josm.tools.GBC; 39 46 import org.openstreetmap.josm.tools.ImageProvider; … … 42 49 43 50 /** 44 * The preferences panel for the OAuth preferences. This just a summary panel51 * The preferences panel for the OAuth 1.0a preferences. This just a summary panel 45 52 * showing the current Access Token Key and Access Token Secret, if the 46 53 * user already has an Access Token. 47 * 54 * <br> 48 55 * For initial authorisation see {@link OAuthAuthorizationWizard}. 49 56 * @since 2745 … … 54 61 private final JCheckBox cbSaveToPreferences = new JCheckBox(tr("Save to preferences")); 55 62 private final JPanel pnlAuthorisationMessage = new JPanel(new BorderLayout()); 56 private final NotYetAuthorisedPanel pnlNotYetAuthorised = new NotYetAuthorisedPanel(); 57 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(); 58 private final AlreadyAuthorisedPanel pnlAlreadyAuthorised = new AlreadyAuthorisedPanel(); 63 private final NotYetAuthorisedPanel pnlNotYetAuthorised; 64 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties; 65 private final AlreadyAuthorisedPanel pnlAlreadyAuthorised; 66 private final OAuthVersion oAuthVersion; 59 67 private String apiUrl; 60 68 61 69 /** 62 * Create the panel 70 * Create the panel. Uses {@link OAuthVersion#OAuth10a}. 63 71 */ 64 72 public OAuthAuthenticationPreferencesPanel() { 73 this(OAuthVersion.OAuth10a); 74 } 75 76 /** 77 * Create the panel. 78 * @param oAuthVersion The OAuth version to use 79 */ 80 public OAuthAuthenticationPreferencesPanel(OAuthVersion oAuthVersion) { 81 this.oAuthVersion = oAuthVersion; 82 // These must come after we set the oauth version 83 this.pnlNotYetAuthorised = new NotYetAuthorisedPanel(); 84 this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(this.oAuthVersion); 85 this.pnlAlreadyAuthorised = new AlreadyAuthorisedPanel(); 65 86 build(); 66 refreshView();67 87 } 68 88 … … 118 138 protected void refreshView() { 119 139 pnlAuthorisationMessage.removeAll(); 120 if (OAuthAccessTokenHolder.getInstance().containsAccessToken()) { 140 if ((this.oAuthVersion == OAuthVersion.OAuth10a && 141 OAuthAccessTokenHolder.getInstance().containsAccessToken()) 142 || OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) { 121 143 pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER); 122 144 pnlAlreadyAuthorised.refreshView(); … … 181 203 182 204 // Action for authorising now 183 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol()); 205 if (oAuthVersion == OAuthVersion.OAuth10a) { 206 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol()); 207 } 184 208 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.SEMI_AUTOMATIC)), GBC.eol()); 185 JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY)); 186 add(authManually, GBC.eol()); 187 ExpertToggleAction.addVisibilitySwitcher(authManually); 209 if (oAuthVersion == OAuthVersion.OAuth10a) { 210 JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY)); 211 add(authManually, GBC.eol()); 212 ExpertToggleAction.addVisibilitySwitcher(authManually); 213 } 188 214 189 215 // filler - grab remaining space … … 254 280 // -- action buttons 255 281 JPanel btns = new JPanel(new FlowLayout(FlowLayout.LEFT)); 256 btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC))); 257 btns.add(new JButton(new TestAuthorisationAction())); 282 if (oAuthVersion == OAuthVersion.OAuth10a) { 283 // these want the OAuth 1.0 token information 284 btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC))); 285 btns.add(new JButton(new TestAuthorisationAction())); 286 } 287 btns.add(new JButton(new RemoveAuthorisationAction())); 258 288 gc.gridy = 4; 259 289 gc.gridx = 0; … … 278 308 279 309 protected final void refreshView() { 280 String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey(); 281 tfAccessTokenKey.setText(v == null ? "" : v); 282 v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret(); 283 tfAccessTokenSecret.setText(v == null ? "" : v); 310 switch (oAuthVersion) { 311 case OAuth10a: 312 String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey(); 313 tfAccessTokenKey.setText(v == null ? "" : v); 314 v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret(); 315 tfAccessTokenSecret.setText(v == null ? "" : v); 316 tfAccessTokenSecret.setVisible(true); 317 break; 318 case OAuth20: 319 case OAuth21: 320 String token = ""; 321 if (apiUrl != null) { 322 OAuth20Token bearerToken = (OAuth20Token) OAuthAccessTokenHolder.getInstance().getAccessToken(apiUrl, oAuthVersion); 323 token = bearerToken == null ? "" : bearerToken.getBearerToken(); 324 } 325 tfAccessTokenKey.setText(token == null ? "" : token); 326 tfAccessTokenSecret.setVisible(false); 327 } 284 328 cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences()); 285 329 } … … 296 340 putValue(NAME, tr("{0} ({1})", tr("Authorize now"), procedure.getText())); 297 341 putValue(SHORT_DESCRIPTION, procedure.getDescription()); 298 if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC) { 342 if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC 343 || OAuthAuthenticationPreferencesPanel.this.oAuthVersion != OAuthVersion.OAuth10a) { 299 344 new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this); 300 345 } … … 303 348 @Override 304 349 public void actionPerformed(ActionEvent arg0) { 305 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard( 306 OAuthAuthenticationPreferencesPanel.this, 307 procedure, 308 apiUrl, 309 MainApplication.worker); 310 try { 311 wizard.showDialog(); 312 } catch (UserCancelException ignore) { 313 Logging.trace(ignore); 314 return; 315 } 316 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters()); 350 if (OAuthAuthenticationPreferencesPanel.this.oAuthVersion == OAuthVersion.OAuth10a) { 351 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard( 352 OAuthAuthenticationPreferencesPanel.this, 353 procedure, 354 apiUrl, 355 MainApplication.worker); 356 try { 357 wizard.showDialog(); 358 } catch (UserCancelException ignore) { 359 Logging.trace(ignore); 360 return; 361 } 362 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters()); 363 refreshView(); 364 } else { 365 final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get()); 366 // TODO: Ask user if they want to start remote control? 367 if (!remoteControlIsRunning) { 368 RemoteControl.start(); 369 } 370 new OAuth20Authorization().authorize(OAuthParameters.createDefault(OsmApi.getOsmApi().getServerUrl(), oAuthVersion), token -> { 371 if (!remoteControlIsRunning) { 372 RemoteControl.stop(); 373 } 374 // Clean up old token/password 375 OAuthAccessTokenHolder.getInstance().setAccessToken(null); 376 OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), token); 377 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 378 GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView); 379 }, OsmScopes.read_gpx, OsmScopes.write_gpx, 380 OsmScopes.read_prefs, OsmScopes.write_prefs, 381 OsmScopes.write_api, OsmScopes.write_notes); 382 } 383 } 384 } 385 386 /** 387 * Remove the OAuth authorization token 388 */ 389 private class RemoveAuthorisationAction extends AbstractAction { 390 RemoveAuthorisationAction() { 391 putValue(NAME, tr("Remove token")); 392 putValue(SHORT_DESCRIPTION, tr("Remove token from JOSM. This does not revoke the token.")); 393 new ImageProvider("cancel").getResource().attachImageIcon(this); 394 } 395 396 @Override 397 public void actionPerformed(ActionEvent e) { 398 if (oAuthVersion == OAuthVersion.OAuth10a) { 399 OAuthAccessTokenHolder.getInstance().setAccessToken(null); 400 } else { 401 OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, (IOAuthToken) null); 402 } 403 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 317 404 refreshView(); 318 405 } -
trunk/src/org/openstreetmap/josm/io/MessageNotifier.java
r18211 r18650 11 11 12 12 import org.openstreetmap.josm.data.UserIdentityManager; 13 import org.openstreetmap.josm.data.oauth.OAuthVersion; 13 14 import org.openstreetmap.josm.data.osm.UserInfo; 14 15 import org.openstreetmap.josm.data.preferences.BooleanProperty; … … 144 145 try { 145 146 if (JosmPreferencesCredentialAgent.class.equals(credManager.getCredentialsAgentClass())) { 146 if (OsmApi.isUsingOAuth( )) {147 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) { 147 148 return credManager.lookupOAuthAccessToken() != null; 149 } else if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) { 150 return credManager.lookupOAuthAccessToken(OsmApi.getOsmApi().getHost()) != null; 151 } else if (OsmApi.isUsingOAuth()) { 152 // Ensure we do not forget to update this section 153 throw new IllegalStateException("Unknown oauth version: " + OsmApi.getAuthMethod()); 148 154 } else { 149 155 String username = Config.getPref().get("osm-server.username", null); -
trunk/src/org/openstreetmap/josm/io/OsmApi.java
r18532 r18650 30 30 import org.openstreetmap.josm.data.coor.LatLon; 31 31 import org.openstreetmap.josm.data.notes.Note; 32 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 33 import org.openstreetmap.josm.data.oauth.OAuthVersion; 32 34 import org.openstreetmap.josm.data.osm.Changeset; 33 35 import org.openstreetmap.josm.data.osm.IPrimitive; … … 83 85 84 86 private static final ListenerList<OsmApiInitializationListener> listeners = ListenerList.create(); 87 /** This is used to make certain we have set osm-server.auth-method to the "right" default */ 88 private static boolean oauthCompatibilitySwitch; 85 89 86 90 private URL url; … … 646 650 */ 647 651 public static boolean isUsingOAuth() { 648 return "oauth".equals(getAuthMethod()); 652 return isUsingOAuth(OAuthVersion.OAuth10a) 653 || isUsingOAuth(OAuthVersion.OAuth20) 654 || isUsingOAuth(OAuthVersion.OAuth21); 655 } 656 657 /** 658 * Determines if JOSM is configured to access OSM API via OAuth 659 * @param version The OAuth version 660 * @return {@code true} if JOSM is configured to access OSM API via OAuth, {@code false} otherwise 661 * @since 18650 662 */ 663 public static boolean isUsingOAuth(OAuthVersion version) { 664 if (version == OAuthVersion.OAuth10a) { 665 return "oauth".equalsIgnoreCase(getAuthMethod()); 666 } else if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) { 667 return "oauth20".equalsIgnoreCase(getAuthMethod()); 668 } 669 return false; 670 } 671 672 /** 673 * Ensure that OAuth is set up 674 * @param api The api for which we need OAuth keys 675 * @return {@code true} if we are using OAuth and there are keys for the specified API 676 */ 677 public static boolean isUsingOAuthAndOAuthSetUp(OsmApi api) { 678 if (OsmApi.isUsingOAuth()) { 679 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) { 680 return OAuthAccessTokenHolder.getInstance().containsAccessToken(); 681 } 682 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20)) { 683 return OAuthAccessTokenHolder.getInstance().getAccessToken(api.getBaseUrl(), OAuthVersion.OAuth20) != null; 684 } 685 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) { 686 return OAuthAccessTokenHolder.getInstance().getAccessToken(api.getBaseUrl(), OAuthVersion.OAuth21) != null; 687 } 688 } 689 return false; 649 690 } 650 691 … … 654 695 */ 655 696 public static String getAuthMethod() { 656 return Config.getPref().get("osm-server.auth-method", "oauth"); 697 setCurrentAuthMethod(); 698 return Config.getPref().get("osm-server.auth-method", "oauth20"); 699 } 700 701 /** 702 * This is a compatibility method for users who currently use OAuth 1.0 -- we are changing the default from oauth to oauth20, 703 * but since oauth was the default, pre-existing users will suddenly be switched to oauth20. 704 * This should be removed whenever {@link OAuthVersion#OAuth10a} support is removed. 705 */ 706 private static void setCurrentAuthMethod() { 707 if (!oauthCompatibilitySwitch) { 708 oauthCompatibilitySwitch = true; 709 final String prefKey = "osm-server.auth-method"; 710 if ("oauth20".equals(Config.getPref().get(prefKey, "oauth20")) 711 && !isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi()) 712 && OAuthAccessTokenHolder.getInstance().containsAccessToken()) { 713 Config.getPref().put(prefKey, "oauth"); 714 } 715 } 657 716 } 658 717 -
trunk/src/org/openstreetmap/josm/io/OsmConnection.java
r16643 r18650 11 11 import java.util.Base64; 12 12 import java.util.Objects; 13 13 import java.util.concurrent.TimeUnit; 14 import java.util.concurrent.atomic.AtomicBoolean; 15 import java.util.function.Consumer; 16 17 import javax.swing.JOptionPane; 18 19 import org.openstreetmap.josm.data.oauth.IOAuthParameters; 20 import org.openstreetmap.josm.data.oauth.IOAuthToken; 21 import org.openstreetmap.josm.data.oauth.OAuth20Authorization; 14 22 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 15 23 import org.openstreetmap.josm.data.oauth.OAuthParameters; 24 import org.openstreetmap.josm.data.oauth.OAuthVersion; 25 import org.openstreetmap.josm.data.oauth.osm.OsmScopes; 26 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil; 27 import org.openstreetmap.josm.gui.MainApplication; 28 import org.openstreetmap.josm.gui.util.GuiHelper; 16 29 import org.openstreetmap.josm.io.auth.CredentialsAgentException; 17 30 import org.openstreetmap.josm.io.auth.CredentialsAgentResponse; 18 31 import org.openstreetmap.josm.io.auth.CredentialsManager; 32 import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 19 33 import org.openstreetmap.josm.tools.HttpClient; 20 34 import org.openstreetmap.josm.tools.JosmRuntimeException; … … 37 51 protected HttpClient activeConnection; 38 52 protected OAuthParameters oauthParameters; 53 protected IOAuthParameters oAuth20Parameters; 39 54 40 55 /** … … 172 187 OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true); 173 188 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 174 } catch (MalformedURLException | In terruptedException | InvocationTargetException e) {189 } catch (MalformedURLException | InvocationTargetException e) { 175 190 throw new MissingOAuthAccessTokenException(e); 191 } catch (InterruptedException e) { 192 Thread.currentThread().interrupt(); 193 throw new MissingOAuthAccessTokenException(e); 194 } 195 } 196 197 /** 198 * Obtains an OAuth access token for the connection. 199 * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}. 200 * @throws MissingOAuthAccessTokenException if the process cannot be completed successfully 201 */ 202 private void obtainOAuth20Token() throws MissingOAuthAccessTokenException { 203 if (!Boolean.TRUE.equals(GuiHelper.runInEDTAndWaitAndReturn(() -> 204 ConditionalOptionPaneUtil.showConfirmationDialog("oauth.oauth20.obtain.automatically", 205 MainApplication.getMainFrame(), 206 tr("Obtain OAuth 2.0 token for authentication?"), 207 tr("Obtain authentication to OSM servers"), 208 JOptionPane.YES_NO_CANCEL_OPTION, 209 JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_OPTION)))) { 210 return; // User doesn't want to perform auth 211 } 212 final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get()); 213 if (!remoteControlIsRunning) { 214 RemoteControl.start(); 215 } 216 AtomicBoolean done = new AtomicBoolean(); 217 Consumer<IOAuthToken> consumer = authToken -> { 218 if (!remoteControlIsRunning) { 219 RemoteControl.stop(); 220 } 221 // Clean up old token/password 222 OAuthAccessTokenHolder.getInstance().setAccessToken(null); 223 OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), authToken); 224 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 225 synchronized (done) { 226 done.set(true); 227 done.notifyAll(); 228 } 229 }; 230 new OAuth20Authorization().authorize(oAuth20Parameters, 231 consumer, OsmScopes.read_gpx, OsmScopes.write_gpx, 232 OsmScopes.read_prefs, OsmScopes.write_prefs, 233 OsmScopes.write_api, OsmScopes.write_notes); 234 synchronized (done) { 235 // Only wait at most 5 minutes 236 int counter = 0; 237 while (!done.get() && counter < 5) { 238 try { 239 done.wait(TimeUnit.MINUTES.toMillis(1)); 240 } catch (InterruptedException e) { 241 Thread.currentThread().interrupt(); 242 Logging.trace(e); 243 consumer.accept(null); 244 throw new MissingOAuthAccessTokenException(e); 245 } 246 counter++; 247 } 248 } 249 } 250 251 /** 252 * Signs the connection with an OAuth authentication header 253 * 254 * @param connection the connection 255 * 256 * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured 257 * @throws OsmTransferException if signing fails 258 */ 259 protected void addOAuth20AuthorizationHeader(HttpClient connection) throws OsmTransferException { 260 if (this.oAuth20Parameters == null) { 261 this.oAuth20Parameters = OAuthParameters.createFromApiUrl(connection.getURL().getHost(), OAuthVersion.OAuth20); 262 } 263 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance(); 264 IOAuthToken token = holder.getAccessToken(connection.getURL().toExternalForm(), OAuthVersion.OAuth20); 265 if (token == null) { 266 obtainOAuth20Token(); 267 token = holder.getAccessToken(connection.getURL().toExternalForm(), OAuthVersion.OAuth20); 268 } 269 if (token == null) { // check if wizard completed 270 throw new MissingOAuthAccessTokenException(); 271 } 272 try { 273 token.sign(connection); 274 } catch (org.openstreetmap.josm.data.oauth.OAuthException e) { 275 throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e); 176 276 } 177 277 } … … 179 279 protected void addAuth(HttpClient connection) throws OsmTransferException { 180 280 final String authMethod = OsmApi.getAuthMethod(); 181 if ("basic".equals(authMethod)) { 182 addBasicAuthorizationHeader(connection); 183 } else if ("oauth".equals(authMethod)) { 184 addOAuthAuthorizationHeader(connection); 185 } else { 186 String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod); 187 Logging.warn(msg); 188 throw new OsmTransferException(msg); 281 switch (authMethod) { 282 case "basic": 283 addBasicAuthorizationHeader(connection); 284 return; 285 case "oauth": 286 addOAuthAuthorizationHeader(connection); 287 return; 288 case "oauth20": 289 addOAuth20AuthorizationHeader(connection); 290 return; 291 default: 292 String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod); 293 Logging.warn(msg); 294 throw new OsmTransferException(msg); 189 295 } 190 296 } -
trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
r16553 r18650 11 11 import java.net.URL; 12 12 import java.util.List; 13 import java.util.Objects; 13 14 14 15 import javax.xml.parsers.ParserConfigurationException; … … 18 19 import org.openstreetmap.josm.data.osm.DataSet; 19 20 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 20 import org.openstreetmap.josm.io.auth.CredentialsAgentException;21 21 import org.openstreetmap.josm.io.auth.CredentialsManager; 22 22 import org.openstreetmap.josm.tools.HttpClient; … … 39 39 */ 40 40 public abstract class OsmServerReader extends OsmConnection { 41 private final OsmApi api = OsmApi.getOsmApi();41 private final OsmApi api; 42 42 private boolean doAuthenticate; 43 43 protected boolean gpxParsedProperly; … … 48 48 */ 49 49 protected OsmServerReader() { 50 try { 51 doAuthenticate = OsmApi.isUsingOAuth() 52 && CredentialsManager.getInstance().lookupOAuthAccessToken() != null 53 && OsmApi.USE_OAUTH_FOR_ALL_REQUESTS.get(); 54 } catch (CredentialsAgentException e) { 55 Logging.warn(e); 56 } 50 this(OsmApi.getOsmApi()); 51 } 52 53 /** 54 * Constructs a new {@code OsmServerReader}. 55 * @param osmApi The API to use for this call 56 * @since 18650 57 */ 58 protected OsmServerReader(OsmApi osmApi) { 59 this.api = osmApi; 60 this.doAuthenticate = OsmApi.isUsingOAuthAndOAuthSetUp(osmApi) && OsmApi.USE_OAUTH_FOR_ALL_REQUESTS.get(); 57 61 } 58 62 … … 185 189 activeConnection = client; 186 190 adaptRequest(client); 187 if (doAuthenticate ) {191 if (doAuthenticate && Objects.equals(this.api.getHost(), client.getURL().getHost())) { 188 192 addAuth(client); 189 193 } -
trunk/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
r12992 r18650 6 6 import java.net.PasswordAuthentication; 7 7 8 import javax.annotation.Nullable; 9 10 import org.openstreetmap.josm.data.oauth.IOAuthToken; 8 11 import org.openstreetmap.josm.data.oauth.OAuthToken; 9 12 … … 66 69 67 70 /** 71 * Lookup the current OAuth Access Token to access the specified server. Replies null, if no 72 * Access Token is currently managed by this CredentialAgent. 73 * 74 * @param host The host to get OAuth credentials for 75 * @return the current OAuth Access Token to access the specified server. 76 * @throws CredentialsAgentException if something goes wrong 77 * @since 18650 78 */ 79 @Nullable 80 IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException; 81 82 /** 68 83 * Stores the OAuth Access Token <code>accessToken</code>. 69 84 * … … 72 87 */ 73 88 void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException; 89 90 /** 91 * Stores the OAuth Access Token <code>accessToken</code>. 92 * 93 * @param host The host the access token is for 94 * @param accessToken the access Token. null, to remove the Access Token. This will remove all IOAuthTokens <i>not</i> managed by 95 * {@link #storeOAuthAccessToken(OAuthToken)}. 96 * @throws CredentialsAgentException if something goes wrong 97 * @since 18650 98 */ 99 void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException; 74 100 75 101 /** -
trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
r18211 r18650 8 8 9 9 import org.openstreetmap.josm.data.UserIdentityManager; 10 import org.openstreetmap.josm.data.oauth.IOAuthToken; 10 11 import org.openstreetmap.josm.data.oauth.OAuthToken; 11 12 import org.openstreetmap.josm.io.OsmApi; … … 162 163 163 164 @Override 165 public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException { 166 return delegate.lookupOAuthAccessToken(host); 167 } 168 169 @Override 164 170 public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException { 165 171 delegate.storeOAuthAccessToken(accessToken); 172 } 173 174 @Override 175 public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException { 176 delegate.storeOAuthAccessToken(host, accessToken); 166 177 } 167 178 -
trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
r14698 r18650 7 7 import java.net.Authenticator.RequestorType; 8 8 import java.net.PasswordAuthentication; 9 import java.util.HashSet; 9 10 import java.util.Objects; 10 11 import java.util.Set; 12 13 import javax.json.JsonException; 11 14 import javax.swing.text.html.HTMLEditorKit; 12 15 16 import org.openstreetmap.josm.data.oauth.IOAuthToken; 17 import org.openstreetmap.josm.data.oauth.OAuth20Exception; 18 import org.openstreetmap.josm.data.oauth.OAuth20Parameters; 19 import org.openstreetmap.josm.data.oauth.OAuth20Token; 13 20 import org.openstreetmap.josm.data.oauth.OAuthToken; 21 import org.openstreetmap.josm.data.oauth.OAuthVersion; 14 22 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 15 23 import org.openstreetmap.josm.io.DefaultProxySelector; 16 24 import org.openstreetmap.josm.io.OsmApi; 17 25 import org.openstreetmap.josm.spi.preferences.Config; 26 import org.openstreetmap.josm.tools.Utils; 18 27 19 28 /** … … 69 78 if (Objects.equals(OsmApi.getOsmApi().getHost(), host)) { 70 79 Config.getPref().put("osm-server.username", credentials.getUserName()); 71 if (credentials.getPassword() == null) {80 if (credentials.getPassword().length == 0) { // PasswordAuthentication#getPassword cannot be null 72 81 Config.getPref().put("osm-server.password", null); 73 82 } else { … … 76 85 } else if (host != null) { 77 86 Config.getPref().put("server.username."+host, credentials.getUserName()); 78 if (credentials.getPassword() == null) {87 if (credentials.getPassword().length == 0) { 79 88 Config.getPref().put("server.password."+host, null); 80 89 } else { … … 85 94 case PROXY: 86 95 Config.getPref().put(DefaultProxySelector.PROXY_USER, credentials.getUserName()); 87 if (credentials.getPassword() == null) {96 if (credentials.getPassword().length == 0) { 88 97 Config.getPref().put(DefaultProxySelector.PROXY_PASS, null); 89 98 } else { … … 108 117 return null; 109 118 return new OAuthToken(accessTokenKey, accessTokenSecret); 119 } 120 121 @Override 122 public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException { 123 Set<String> keySet = new HashSet<>(Config.getPref().getKeySet()); 124 keySet.addAll(Config.getPref().getSensitive()); // Just in case we decide to not return sensitive keys in getKeySet 125 for (OAuthVersion oauthType : OAuthVersion.values()) { 126 final String hostKey = "oauth.access-token.object." + oauthType + "." + host; 127 final String parametersKey = "oauth.access-token.parameters." + oauthType + "." + host; 128 if (!keySet.contains(hostKey) || !keySet.contains(parametersKey)) { 129 continue; // Avoid adding empty temporary entries to preferences 130 } 131 String token = Config.getPref().get(hostKey, null); 132 String parameters = Config.getPref().get(parametersKey, null); 133 if (!Utils.isBlank(token) && !Utils.isBlank(parameters) && OAuthVersion.OAuth20 == oauthType) { 134 try { 135 OAuth20Parameters oAuth20Parameters = new OAuth20Parameters(parameters); 136 return new OAuth20Token(oAuth20Parameters, token); 137 } catch (OAuth20Exception | JsonException e) { 138 throw new CredentialsAgentException(e); 139 } 140 } 141 } 142 return null; 110 143 } 111 144 … … 124 157 Config.getPref().put("oauth.access-token.key", accessToken.getKey()); 125 158 Config.getPref().put("oauth.access-token.secret", accessToken.getSecret()); 159 } 160 } 161 162 @Override 163 public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException { 164 Objects.requireNonNull(host, "host"); 165 if (accessToken == null) { 166 Set<String> keySet = new HashSet<>(Config.getPref().getKeySet()); 167 keySet.addAll(Config.getPref().getSensitive()); // Just in case we decide to not return sensitive keys in getKeySet 168 // Assume we want to remove all access tokens 169 for (OAuthVersion oauthType : OAuthVersion.values()) { 170 final String hostKey = "oauth.access-token.parameters." + oauthType + "." + host; 171 final String parametersKey = "oauth.access-token.parameters." + oauthType + "." + host; 172 if (keySet.contains(hostKey)) { 173 Config.getPref().removeSensitive(hostKey); 174 } 175 if (keySet.contains(parametersKey)) { 176 Config.getPref().removeSensitive(parametersKey); 177 } 178 } 179 } else { 180 final String hostKey = "oauth.access-token.object." + accessToken.getOAuthType() + "." + host; 181 final String parametersKey = "oauth.access-token.parameters." + accessToken.getOAuthType() + "." + host; 182 Config.getPref().put(hostKey, accessToken.toPreferencesString()); 183 Config.getPref().put(parametersKey, accessToken.getParameters().toPreferencesString()); 184 Config.getPref().addSensitive(this, hostKey); 185 Config.getPref().addSensitive(this, parametersKey); 126 186 } 127 187 } -
trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java
r18211 r18650 31 31 import org.openstreetmap.josm.io.remotecontrol.handler.AddNodeHandler; 32 32 import org.openstreetmap.josm.io.remotecontrol.handler.AddWayHandler; 33 import org.openstreetmap.josm.io.remotecontrol.handler.AuthorizationHandler; 33 34 import org.openstreetmap.josm.io.remotecontrol.handler.FeaturesHandler; 34 35 import org.openstreetmap.josm.io.remotecontrol.handler.ImageryHandler; … … 172 173 addRequestHandlerClass(FeaturesHandler.command, FeaturesHandler.class, true); 173 174 addRequestHandlerClass(OpenApiHandler.command, OpenApiHandler.class, true); 175 addRequestHandlerClass(AuthorizationHandler.command, AuthorizationHandler.class, true); 174 176 } 175 177 } -
trunk/src/org/openstreetmap/josm/spi/preferences/AbstractPreferences.java
r18209 r18650 2 2 package org.openstreetmap.josm.spi.preferences; 3 3 4 import java.util.Arrays; 5 import java.util.Collection; 6 import java.util.Collections; 7 import java.util.HashSet; 4 8 import java.util.LinkedList; 5 9 import java.util.List; 6 10 import java.util.Map; 7 11 import java.util.Map.Entry; 12 import java.util.Set; 8 13 import java.util.TreeMap; 9 14 import java.util.stream.Collectors; 10 15 16 import org.openstreetmap.josm.io.DefaultProxySelector; 17 import org.openstreetmap.josm.io.auth.CredentialsAgent; 18 import org.openstreetmap.josm.io.auth.CredentialsManager; 11 19 import org.openstreetmap.josm.tools.Logging; 12 20 import org.openstreetmap.josm.tools.Utils; … … 17 25 */ 18 26 public abstract class AbstractPreferences implements IPreferences { 27 /** The preference key for sensitive keys */ 28 private static final String KEY_SENSITIVE_KEYS = "sensitive.keys"; 29 30 /** A set of sensitive keys that should not be seen/distributed outside of specific callers (like a {@link CredentialsAgent}) */ 31 private static final Set<String> SENSITIVE_KEYS = new HashSet<>(); 19 32 20 33 @Override … … 176 189 .collect(Collectors.toCollection(LinkedList::new)); 177 190 } 191 192 @Override 193 public void addSensitive(CredentialsAgent caller, String key) { 194 if (SENSITIVE_KEYS.isEmpty()) { 195 populateSensitiveKeys(); 196 } 197 if (CredentialsManager.getInstance().getCredentialsAgentClass().equals(caller.getClass())) { 198 SENSITIVE_KEYS.add(key); 199 putList("sensitive.keys", SENSITIVE_KEYS.stream().sorted().collect(Collectors.toList())); 200 } 201 } 202 203 @Override 204 public Collection<String> getSensitive() { 205 if (SENSITIVE_KEYS.isEmpty()) { 206 populateSensitiveKeys(); 207 } 208 return Collections.unmodifiableSet(SENSITIVE_KEYS); 209 } 210 211 @Override 212 public void removeSensitive(String key) { 213 if (KEY_SENSITIVE_KEYS.equals(key)) { 214 throw new IllegalArgumentException(KEY_SENSITIVE_KEYS + " cannot be removed from the sensitive key list."); 215 } 216 // Reset the key first -- avoid race conditions where a sensitive value might be visible if we start restricting access in the future. 217 put(key, null); 218 SENSITIVE_KEYS.remove(key); 219 putList(KEY_SENSITIVE_KEYS, SENSITIVE_KEYS.stream().sorted().collect(Collectors.toList())); 220 } 221 222 /** 223 * Populate the sensitive key set from preferences 224 */ 225 private void populateSensitiveKeys() { 226 SENSITIVE_KEYS.addAll(getList(KEY_SENSITIVE_KEYS, Arrays.asList("sensitive.keys", "osm-server.username", "osm-server.password", 227 DefaultProxySelector.PROXY_USER, DefaultProxySelector.PROXY_PASS, 228 "oauth.access-token.key", "oauth.access-token.secret"))); 229 } 178 230 } -
trunk/src/org/openstreetmap/josm/spi/preferences/IPreferences.java
r12987 r18650 2 2 package org.openstreetmap.josm.spi.preferences; 3 3 4 import java.util.Collection; 4 5 import java.util.Collections; 5 6 import java.util.List; 6 7 import java.util.Map; 7 8 import java.util.Set; 9 10 import org.openstreetmap.josm.io.auth.CredentialsAgent; 8 11 9 12 /** … … 240 243 */ 241 244 Set<String> getKeySet(); 245 246 /** 247 * Add sensitive keys 248 * @param caller The calling agent 249 * @param key The key that may contain sensitive information 250 * @since 18650 251 */ 252 void addSensitive(CredentialsAgent caller, String key); 253 254 /** 255 * Get sensitive keys 256 * @return The sensitive keys 257 * @since 18650 258 */ 259 Collection<String> getSensitive(); 260 261 /** 262 * Remove sensitive keys. This removes the key from the sensitive list <i>and</i> 263 * removes the stored preference value. 264 * @param key The key to remove 265 * @since 18650 266 */ 267 void removeSensitive(String key); 242 268 }
Note:
See TracChangeset
for help on using the changeset viewer.