- Timestamp:
- 2024-02-21T21:26:18+01:00 (9 months ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 7 deleted
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java
r18723 r18991 148 148 return builder.build().toString(); 149 149 } 150 151 @Override 152 public int hashCode() { 153 return Objects.hash(this.apiUrl, this.authorizeUrl, this.tokenUrl, this.clientId, this.clientSecret, this.redirectUri); 154 } 155 156 @Override 157 public boolean equals(Object obj) { 158 if (obj != null && this.getClass() == obj.getClass()) { 159 OAuth20Parameters other = (OAuth20Parameters) obj; 160 return Objects.equals(this.clientSecret, other.clientSecret) && 161 Objects.equals(this.clientId, other.clientId) && 162 Objects.equals(this.redirectUri, other.redirectUri) && 163 Objects.equals(this.tokenUrl, other.tokenUrl) && 164 Objects.equals(this.authorizeUrl, other.authorizeUrl) && 165 Objects.equals(this.apiUrl, other.apiUrl); 166 } 167 return false; 168 } 150 169 } -
trunk/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
r18764 r18991 37 37 38 38 private boolean saveToPreferences; 39 private String accessTokenKey;40 private String accessTokenSecret;41 39 42 40 private final Map<String, Map<OAuthVersion, IOAuthToken>> tokenMap = new HashMap<>(); … … 53 51 /** 54 52 * Sets whether the current access token should be saved to the preferences file. 55 * 53 * <p> 56 54 * If true, the access token is saved in clear text to the preferences file. The same 57 55 * access token can therefore be used in multiple JOSM sessions. 58 * 56 * <p> 59 57 * If false, the access token isn't saved to the preferences file. If JOSM is closed, 60 58 * the access token is lost and new token has to be generated by the OSM server the … … 65 63 public void setSaveToPreferences(boolean saveToPreferences) { 66 64 this.saveToPreferences = saveToPreferences; 67 }68 69 /**70 * Replies the access token key. null, if no access token key is currently set.71 *72 * @return the access token key73 */74 public String getAccessTokenKey() {75 return accessTokenKey;76 }77 78 /**79 * Sets the access token key. Pass in null to remove the current access token key.80 *81 * @param accessTokenKey the access token key82 */83 public void setAccessTokenKey(String accessTokenKey) {84 this.accessTokenKey = accessTokenKey;85 }86 87 /**88 * Replies the access token secret. null, if no access token secret is currently set.89 *90 * @return the access token secret91 */92 public String getAccessTokenSecret() {93 return accessTokenSecret;94 }95 96 /**97 * Sets the access token secret. Pass in null to remove the current access token secret.98 *99 * @param accessTokenSecret access token secret, or null100 */101 public void setAccessTokenSecret(String accessTokenSecret) {102 this.accessTokenSecret = accessTokenSecret;103 }104 105 /**106 * Replies the access token.107 * @return the access token, can be {@code null}108 */109 public OAuthToken getAccessToken() {110 if (!containsAccessToken())111 return null;112 return new OAuthToken(accessTokenKey, accessTokenSecret);113 65 } 114 66 … … 143 95 * Sets the access token hold by this holder. 144 96 * 145 * @param accessTokenKey the access token key146 * @param accessTokenSecret the access token secret147 */148 public void setAccessToken(String accessTokenKey, String accessTokenSecret) {149 this.accessTokenKey = accessTokenKey;150 this.accessTokenSecret = accessTokenSecret;151 }152 153 /**154 * Sets the access token hold by this holder.155 *156 * @param token the access token. Can be null to clear the content in this holder.157 */158 public void setAccessToken(OAuthToken token) {159 if (token == null) {160 this.accessTokenKey = null;161 this.accessTokenSecret = null;162 } else {163 this.accessTokenKey = token.getKey();164 this.accessTokenSecret = token.getSecret();165 }166 }167 168 /**169 * Sets the access token hold by this holder.170 *171 97 * @param api The api the token is for 172 98 * @param token the access token. Can be null to clear the content in this holder. … … 187 113 188 114 /** 189 * Replies true if this holder contains an complete access token, consisting of an190 * Access Token Key and an Access Token Secret.191 *192 * @return true if this holder contains an complete access token193 */194 public boolean containsAccessToken() {195 return accessTokenKey != null && accessTokenSecret != null;196 }197 198 /**199 115 * Initializes the content of this holder from the Access Token managed by the 200 116 * credential manager. … … 205 121 public void init(CredentialsAgent cm) { 206 122 CheckParameterUtil.ensureParameterNotNull(cm, "cm"); 207 OAuthToken token = null;208 try {209 token = cm.lookupOAuthAccessToken();210 } catch (CredentialsAgentException e) {211 Logging.error(e);212 Logging.warn(tr("Failed to retrieve OAuth Access Token from credential manager"));213 Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));214 }215 123 saveToPreferences = Config.getPref().getBoolean("oauth.access-token.save-to-preferences", true); 216 if (token != null) {217 accessTokenKey = token.getKey();218 accessTokenSecret = token.getSecret();219 }220 124 } 221 125 … … 232 136 try { 233 137 if (!saveToPreferences) { 234 cm.storeOAuthAccessToken(null);235 138 for (String host : this.tokenMap.keySet()) { 236 139 cm.storeOAuthAccessToken(host, null); 237 140 } 238 141 } else { 239 if (this.accessTokenKey != null && this.accessTokenSecret != null) {240 cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret));241 } else {242 cm.storeOAuthAccessToken(null);243 }244 142 for (Map.Entry<String, Map<OAuthVersion, IOAuthToken>> entry : this.tokenMap.entrySet()) { 245 143 if (entry.getValue().isEmpty()) { … … 265 163 */ 266 164 public void clear() { 267 accessTokenKey = null; 268 accessTokenSecret = null; 165 this.tokenMap.clear(); 269 166 } 270 167 } -
trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
r18723 r18991 4 4 import java.io.BufferedReader; 5 5 import java.io.IOException; 6 import java.net.URI; 7 import java.net.URISyntaxException; 6 8 import java.net.URL; 7 import java.util.Objects; 9 import java.util.HashMap; 10 import java.util.Map; 11 12 import org.openstreetmap.josm.io.NetworkManager; 13 import org.openstreetmap.josm.io.OsmApi; 14 import org.openstreetmap.josm.io.auth.CredentialsAgentException; 15 import org.openstreetmap.josm.io.auth.CredentialsManager; 16 import org.openstreetmap.josm.spi.preferences.Config; 17 import org.openstreetmap.josm.spi.preferences.IUrls; 18 import org.openstreetmap.josm.tools.HttpClient; 19 import org.openstreetmap.josm.tools.JosmRuntimeException; 20 import org.openstreetmap.josm.tools.Logging; 21 import org.openstreetmap.josm.tools.Utils; 8 22 9 23 import jakarta.json.Json; … … 13 27 import jakarta.json.JsonValue; 14 28 15 import org.openstreetmap.josm.io.OsmApi;16 import org.openstreetmap.josm.io.auth.CredentialsAgentException;17 import org.openstreetmap.josm.io.auth.CredentialsManager;18 import org.openstreetmap.josm.spi.preferences.Config;19 import org.openstreetmap.josm.spi.preferences.IUrls;20 import org.openstreetmap.josm.tools.CheckParameterUtil;21 import org.openstreetmap.josm.tools.HttpClient;22 import org.openstreetmap.josm.tools.Logging;23 import org.openstreetmap.josm.tools.Utils;24 25 import oauth.signpost.OAuthConsumer;26 import oauth.signpost.OAuthProvider;27 28 29 /** 29 30 * This class manages an immutable set of OAuth parameters. 30 * @since 2747 31 * @since 2747 (static factory class since 18991) 31 32 */ 32 public class OAuthParameters implements IOAuthParameters { 33 34 /** 35 * The default JOSM OAuth consumer key (created by user josmeditor). 36 */ 37 public static final String DEFAULT_JOSM_CONSUMER_KEY = "F7zPYlVCqE2BUH9Hr4SsWZSOnrKjpug1EgqkbsSb"; 38 /** 39 * The default JOSM OAuth consumer secret (created by user josmeditor). 40 */ 41 public static final String DEFAULT_JOSM_CONSUMER_SECRET = "rIkjpPcBNkMQxrqzcOvOC4RRuYupYr7k8mfP13H5"; 33 public final class OAuthParameters { 34 private static final Map<String, JsonObject> RFC8414_RESPONSES = new HashMap<>(1); 35 private static final String OSM_API_DEFAULT = "https://api.openstreetmap.org/api"; 36 private static final String OSM_API_DEV = "https://api06.dev.openstreetmap.org/api"; 37 private static final String OSM_API_MASTER = "https://master.apis.dev.openstreetmap.org/api"; 38 39 private OAuthParameters() { 40 // Hide constructor 41 } 42 42 43 43 /** 44 44 * Replies a set of default parameters for a consumer accessing the standard OSM server 45 45 * at {@link IUrls#getDefaultOsmApiUrl}. 46 * 46 * <p> 47 * Note that this may make network requests for RFC 8414 compliant endpoints. 47 48 * @return a set of default parameters 48 49 */ 49 public static OAuthParameters createDefault() {50 return createDefault( null);50 public static IOAuthParameters createDefault() { 51 return createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20); 51 52 } 52 53 … … 55 56 * at the given API url. URL parameters are only set if the URL equals {@link IUrls#getDefaultOsmApiUrl} 56 57 * or references the domain "dev.openstreetmap.org", otherwise they may be <code>null</code>. 57 * 58 * @param apiUrl The API URL for which the OAuth default parameters are created. If null or empty, the default OSM API url is used. 59 * @return a set of default parameters for the given {@code apiUrl} 60 * @since 5422 61 */ 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>. 58 * <p> 59 * Note that this may make network requests for RFC 8414 compliant endpoints. 70 60 * 71 61 * @param apiUrl The API URL for which the OAuth default parameters are created. If null or empty, the default OSM API url is used. … … 80 70 81 71 switch (oAuthVersion) { 82 case OAuth10a:83 return getDefaultOAuth10Parameters(apiUrl);84 72 case OAuth20: 85 73 case OAuth21: // For now, OAuth 2.1 (draft) is just OAuth 2.0 with mandatory extensions, which we implement. … … 90 78 } 91 79 80 private static JsonObject getRFC8414Parameters(String apiUrl) { 81 HttpClient client = null; 82 try { 83 final URI apiURI = new URI(apiUrl); 84 final URL rfc8414URL = new URI(apiURI.getScheme(), apiURI.getHost(), 85 "/.well-known/oauth-authorization-server", null).toURL(); 86 client = HttpClient.create(rfc8414URL); 87 HttpClient.Response response = client.connect(); 88 if (response.getResponseCode() == 200) { 89 try (BufferedReader reader = response.getContentReader(); 90 JsonReader jsonReader = Json.createReader(reader)) { 91 JsonStructure structure = jsonReader.read(); 92 if (structure.getValueType() == JsonValue.ValueType.OBJECT) { 93 return structure.asJsonObject(); 94 } 95 } 96 } 97 } catch (URISyntaxException | IOException e) { 98 throw new JosmRuntimeException(e); 99 } finally { 100 if (client != null) { 101 client.disconnect(); 102 } 103 } 104 return Json.createObjectBuilder().build(); 105 } 106 92 107 /** 93 108 * Get the default OAuth 2.0 parameters … … 98 113 final String clientId; 99 114 final String clientSecret; 100 final String redirectUri ;115 final String redirectUri = "http://127.0.0.1:8111/oauth_authorization"; 101 116 final String baseUrl; 102 if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl) && !"http://invalid".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) { 117 apiUrl = apiUrl == null ? OsmApi.getOsmApi().getServerUrl() : apiUrl; 118 switch (apiUrl) { 119 case OSM_API_DEV: 120 case OSM_API_MASTER: 121 // This clientId/clientSecret are provided by taylor.smock. Feel free to change if needed, but 122 // do let one of the maintainers with server access know so that they can update the test OAuth 123 // token. 124 clientId = "-QZt6n1btDfqrfJNGUIMZjzcyqTgIV6sy79_W4kmQLM"; 125 // Keep secret for dev apis, just in case we want to test something that needs it. 126 clientSecret = "SWnmRD4AdLO-2-ttHE5TR3eLF2McNf7dh0_Z2WNzJdI"; 127 break; 128 case OSM_API_DEFAULT: 129 clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI"; 130 // We don't actually use the client secret in our authorization flow. 131 clientSecret = null; 132 break; 133 case "https://www.openhistoricalmap.org/api": 134 // clientId provided by 1ec5 (Minh Nguyễn) 135 clientId = "Hl5yIhFS-Egj6aY7A35ouLOuZl0EHjj8JJQQ46IO96E"; 136 clientSecret = null; 137 break; 138 default: 139 clientId = ""; 140 clientSecret = null; 141 } 142 baseUrl = apiUrl; 143 // Check if the server is RFC 8414 compliant 144 try { 145 synchronized (RFC8414_RESPONSES) { 146 final JsonObject data; 147 if (NetworkManager.isOffline(apiUrl)) { 148 data = null; 149 } else { 150 data = RFC8414_RESPONSES.computeIfAbsent(apiUrl, OAuthParameters::getRFC8414Parameters); 151 } 152 if (data == null || data.isEmpty()) { 153 RFC8414_RESPONSES.remove(apiUrl); 154 } else { 155 return parseAuthorizationServerMetadataResponse(clientId, clientSecret, apiUrl, 156 redirectUri, data); 157 } 158 } 159 } catch (JosmRuntimeException e) { 160 if (e.getCause() instanceof URISyntaxException || e.getCause() instanceof IOException) { 123 161 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 } 162 } else { 163 throw e; 164 } 165 } catch (OAuthException e) { 166 Logging.trace(e); 167 } 168 // Fall back to guessing the parameters. 135 169 return new OAuth20Parameters(clientId, clientSecret, baseUrl, apiUrl, redirectUri); 136 170 } … … 155 189 156 190 /** 157 * Get the default OAuth 1.0a parameters158 * @param apiUrl The api url159 * @return The default parameters160 */161 private static OAuthParameters getDefaultOAuth10Parameters(String apiUrl) {162 final String consumerKey;163 final String consumerSecret;164 final String serverUrl;165 166 if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) {167 consumerKey = ""; // a custom consumer key is required168 consumerSecret = ""; // a custom consumer secret is requireds169 serverUrl = apiUrl.replaceAll("/api$", "");170 } else {171 consumerKey = DEFAULT_JOSM_CONSUMER_KEY;172 consumerSecret = DEFAULT_JOSM_CONSUMER_SECRET;173 serverUrl = Config.getUrls().getOSMWebsite();174 }175 176 return new OAuthParameters(177 consumerKey,178 consumerSecret,179 serverUrl + "/oauth/request_token",180 serverUrl + "/oauth/access_token",181 serverUrl + "/oauth/authorize",182 serverUrl + "/login",183 serverUrl + "/logout");184 }185 186 /**187 * Replies a set of parameters as defined in the preferences.188 *189 * @param apiUrl the API URL. Must not be null.190 * @return the parameters191 */192 public static OAuthParameters createFromApiUrl(String apiUrl) {193 return (OAuthParameters) createFromApiUrl(apiUrl, OAuthVersion.OAuth10a);194 }195 196 /**197 191 * Replies a set of parameters as defined in the preferences. 198 192 * … … 205 199 IOAuthParameters parameters = createDefault(apiUrl, oAuthVersion); 206 200 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 201 case OAuth20: 218 202 case OAuth21: // Right now, OAuth 2.1 will work with our OAuth 2.0 implementation … … 229 213 } 230 214 } 231 232 /**233 * Remembers the current values in the preferences.234 */235 @Override236 public void rememberPreferences() {237 Config.getPref().put("oauth.settings.consumer-key", getConsumerKey());238 Config.getPref().put("oauth.settings.consumer-secret", getConsumerSecret());239 Config.getPref().put("oauth.settings.request-token-url", getRequestTokenUrl());240 Config.getPref().put("oauth.settings.access-token-url", getAccessTokenUrl());241 Config.getPref().put("oauth.settings.authorise-url", getAuthoriseUrl());242 Config.getPref().put("oauth.settings.osm-login-url", getOsmLoginUrl());243 Config.getPref().put("oauth.settings.osm-logout-url", getOsmLogoutUrl());244 }245 246 private final String consumerKey;247 private final String consumerSecret;248 private final String requestTokenUrl;249 private final String accessTokenUrl;250 private final String authoriseUrl;251 private final String osmLoginUrl;252 private final String osmLogoutUrl;253 254 /**255 * Constructs a new {@code OAuthParameters}.256 * @param consumerKey consumer key257 * @param consumerSecret consumer secret258 * @param requestTokenUrl request token URL259 * @param accessTokenUrl access token URL260 * @param authoriseUrl authorise URL261 * @param osmLoginUrl the OSM login URL (for automatic mode)262 * @param osmLogoutUrl the OSM logout URL (for automatic mode)263 * @see #createDefault264 * @see #createFromApiUrl265 * @since 9220266 */267 public OAuthParameters(String consumerKey, String consumerSecret,268 String requestTokenUrl, String accessTokenUrl, String authoriseUrl, String osmLoginUrl, String osmLogoutUrl) {269 this.consumerKey = consumerKey;270 this.consumerSecret = consumerSecret;271 this.requestTokenUrl = requestTokenUrl;272 this.accessTokenUrl = accessTokenUrl;273 this.authoriseUrl = authoriseUrl;274 this.osmLoginUrl = osmLoginUrl;275 this.osmLogoutUrl = osmLogoutUrl;276 }277 278 /**279 * Creates a clone of the parameters in <code>other</code>.280 *281 * @param other the other parameters. Must not be null.282 * @throws IllegalArgumentException if other is null283 */284 public OAuthParameters(OAuthParameters other) {285 CheckParameterUtil.ensureParameterNotNull(other, "other");286 this.consumerKey = other.consumerKey;287 this.consumerSecret = other.consumerSecret;288 this.accessTokenUrl = other.accessTokenUrl;289 this.requestTokenUrl = other.requestTokenUrl;290 this.authoriseUrl = other.authoriseUrl;291 this.osmLoginUrl = other.osmLoginUrl;292 this.osmLogoutUrl = other.osmLogoutUrl;293 }294 295 /**296 * Gets the consumer key.297 * @return The consumer key298 */299 public String getConsumerKey() {300 return consumerKey;301 }302 303 /**304 * Gets the consumer secret.305 * @return The consumer secret306 */307 public String getConsumerSecret() {308 return consumerSecret;309 }310 311 /**312 * Gets the request token URL.313 * @return The request token URL314 */315 public String getRequestTokenUrl() {316 return requestTokenUrl;317 }318 319 /**320 * Gets the access token URL.321 * @return The access token URL322 */323 @Override324 public String getAccessTokenUrl() {325 return accessTokenUrl;326 }327 328 @Override329 public String getAuthorizationUrl() {330 return this.authoriseUrl;331 }332 333 @Override334 public OAuthVersion getOAuthVersion() {335 return OAuthVersion.OAuth10a;336 }337 338 @Override339 public String getClientId() {340 return this.consumerKey;341 }342 343 @Override344 public String getClientSecret() {345 return this.consumerSecret;346 }347 348 /**349 * Gets the authorise URL.350 * @return The authorise URL351 */352 public String getAuthoriseUrl() {353 return this.getAuthorizationUrl();354 }355 356 /**357 * Gets the URL used to login users on the website (for automatic mode).358 * @return The URL used to login users359 */360 public String getOsmLoginUrl() {361 return osmLoginUrl;362 }363 364 /**365 * Gets the URL used to logout users on the website (for automatic mode).366 * @return The URL used to logout users367 */368 public String getOsmLogoutUrl() {369 return osmLogoutUrl;370 }371 372 /**373 * Builds an {@link OAuthConsumer} based on these parameters.374 *375 * @return the consumer376 */377 public OAuthConsumer buildConsumer() {378 return new SignpostAdapters.OAuthConsumer(consumerKey, consumerSecret);379 }380 381 /**382 * Builds an {@link OAuthProvider} based on these parameters and a OAuth consumer <code>consumer</code>.383 *384 * @param consumer the consumer. Must not be null.385 * @return the provider386 * @throws IllegalArgumentException if consumer is null387 */388 public OAuthProvider buildProvider(OAuthConsumer consumer) {389 CheckParameterUtil.ensureParameterNotNull(consumer, "consumer");390 return new SignpostAdapters.OAuthProvider(391 requestTokenUrl,392 accessTokenUrl,393 authoriseUrl394 );395 }396 397 @Override398 public boolean equals(Object o) {399 if (this == o) return true;400 if (o == null || getClass() != o.getClass()) return false;401 OAuthParameters that = (OAuthParameters) o;402 return Objects.equals(consumerKey, that.consumerKey) &&403 Objects.equals(consumerSecret, that.consumerSecret) &&404 Objects.equals(requestTokenUrl, that.requestTokenUrl) &&405 Objects.equals(accessTokenUrl, that.accessTokenUrl) &&406 Objects.equals(authoriseUrl, that.authoriseUrl) &&407 Objects.equals(osmLoginUrl, that.osmLoginUrl) &&408 Objects.equals(osmLogoutUrl, that.osmLogoutUrl);409 }410 411 @Override412 public int hashCode() {413 return Objects.hash(consumerKey, consumerSecret, requestTokenUrl, accessTokenUrl, authoriseUrl, osmLoginUrl, osmLogoutUrl);414 }415 215 } -
trunk/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java
r18650 r18991 8 8 */ 9 9 public enum OAuthVersion { 10 /** <a href="https://oauth.net/core/1.0a/">OAuth 1.0a</a> */ 10 /** 11 * <a href="https://oauth.net/core/1.0a/">OAuth 1.0a</a> 12 * @deprecated The OSM API server has deprecated and will remove OAuth 1.0a support in June 2024. 13 */ 14 @Deprecated 11 15 OAuth10a, 12 16 /** <a href="https://datatracker.ietf.org/doc/html/rfc6749">OAuth 2.0</a> */ -
trunk/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java
r18650 r18991 5 5 6 6 import org.openstreetmap.josm.data.oauth.IOAuthParameters; 7 import org.openstreetmap.josm.data.oauth.IOAuthToken; 7 8 import org.openstreetmap.josm.data.oauth.OAuthParameters; 8 import org.openstreetmap.josm.data.oauth.OAuthToken;9 9 import org.openstreetmap.josm.data.oauth.OAuthVersion; 10 10 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; … … 23 23 24 24 private String apiUrl; 25 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(OAuthVersion.OAuth10a); 26 private transient OAuthToken accessToken; 27 28 /** 29 * Constructs a new {@code AbstractAuthorizationUI} without API URL. 30 * @since 10189 31 */ 32 protected AbstractAuthorizationUI() { 33 } 25 private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties; 26 private transient IOAuthToken accessToken; 34 27 35 28 /** 36 29 * Constructs a new {@code AbstractAuthorizationUI} for the given API URL. 37 * @param apiUrl The OSM API URL 38 * @since 5422 30 * @param apiUrl The OSM API URL (may be null) 31 * @param oAuthVersion The oauth version to use 32 * @since 18991 39 33 */ 40 protected AbstractAuthorizationUI(String apiUrl) { 41 setApiUrl(apiUrl); 34 protected AbstractAuthorizationUI(String apiUrl, OAuthVersion oAuthVersion) { 35 this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(oAuthVersion); 36 if (apiUrl != null) { 37 setApiUrl(apiUrl); 38 } 42 39 } 43 40 44 protected void fireAccessTokenChanged( OAuthToken oldValue,OAuthToken newValue) {41 protected void fireAccessTokenChanged(IOAuthToken oldValue, IOAuthToken newValue) { 45 42 firePropertyChange(ACCESS_TOKEN_PROP, oldValue, newValue); 46 43 } … … 91 88 * @return the retrieved Access Token 92 89 */ 93 public OAuthToken getAccessToken() {90 public IOAuthToken getAccessToken() { 94 91 return accessToken; 95 92 } … … 101 98 * @param accessToken the new access token. null, to clear the current access token 102 99 */ 103 protected void setAccessToken( OAuthToken accessToken) {104 OAuthToken oldValue = this.accessToken;100 protected void setAccessToken(IOAuthToken accessToken) { 101 IOAuthToken oldValue = this.accessToken; 105 102 this.accessToken = accessToken; 106 103 if (oldValue == null ^ this.accessToken == null) { … … 111 108 fireAccessTokenChanged(oldValue, this.accessToken); 112 109 } 110 } 111 112 /** 113 * Get the OAuth version for this AuthorizationUI 114 * @return The OAuth version 115 * @since 18991 116 */ 117 public OAuthVersion getOAuthVersion() { 118 return this.pnlAdvancedProperties.getAdvancedParameters().getOAuthVersion(); 113 119 } 114 120 -
trunk/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java
r14977 r18991 12 12 import javax.swing.JPanel; 13 13 14 import org.openstreetmap.josm.data.oauth.IOAuthToken; 15 import org.openstreetmap.josm.data.oauth.OAuth20Token; 14 16 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 15 import org.openstreetmap.josm.data.oauth.OAuthToken;16 17 import org.openstreetmap.josm.gui.widgets.JosmTextField; 18 import org.openstreetmap.josm.tools.JosmRuntimeException; 17 19 18 20 /** 19 * Displays the key and the secretof an OAuth Access Token.20 * @since 2746 21 * Displays the key of an OAuth Access Token. 22 * @since 2746 (modified for OAuth 2 in 18991) 21 23 */ 22 24 public class AccessTokenInfoPanel extends JPanel { 23 25 24 26 private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false); 25 private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);26 27 private final JCheckBox cbSaveAccessTokenInPreferences = new JCheckBox(tr("Save Access Token in preferences")); 27 28 … … 56 57 add(new JLabel(tr("Access Token Secret:")), gc); 57 58 58 gc.gridx = 1;59 59 gc.weightx = 1.0; 60 add(tfAccessTokenSecret, gc);61 tfAccessTokenSecret.setEditable(false);62 63 60 // the checkbox 64 61 gc.gridx = 0; … … 87 84 * @param token the access token. If null, the content in the info panel is cleared 88 85 */ 89 public void setAccessToken( OAuthToken token) {86 public void setAccessToken(IOAuthToken token) { 90 87 if (token == null) { 91 88 tfAccessTokenKey.setText(""); 92 tfAccessTokenSecret.setText("");93 89 return; 94 90 } 95 tfAccessTokenKey.setText(token.getKey()); 96 tfAccessTokenSecret.setText(token.getSecret()); 91 if (token instanceof OAuth20Token) { 92 tfAccessTokenKey.setText(((OAuth20Token) token).getBearerToken()); 93 } else { 94 throw new JosmRuntimeException("Unknown token type: " + token.getClass()); 95 } 97 96 } 98 97 -
trunk/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java
r18650 r18991 22 22 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 23 23 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; 24 import org.openstreetmap.josm.gui.MainApplication; 24 25 import org.openstreetmap.josm.gui.help.HelpUtil; 26 import org.openstreetmap.josm.gui.util.GuiHelper; 25 27 import org.openstreetmap.josm.gui.widgets.JosmTextField; 26 28 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator; … … 53 55 private final JosmTextField tfAccessTokenURL = new JosmTextField(); 54 56 private final JosmTextField tfAuthoriseURL = new JosmTextField(); 55 private final JosmTextField tfOsmLoginURL = new JosmTextField();56 private final JosmTextField tfOsmLogoutURL = new JosmTextField();57 57 private final OAuthVersion oauthVersion; 58 58 private transient UseDefaultItemListener ilUseDefault; … … 84 84 gc.weightx = 0.0; 85 85 gc.gridwidth = 1; 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 } 86 add(new JLabel(tr("Client ID:")), gc); 91 87 92 88 gc.gridx = 1; … … 99 95 gc.gridx = 0; 100 96 gc.weightx = 0.0; 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 } 97 add(new JLabel(tr("Client Secret:")), gc); 106 98 107 99 gc.gridx = 1; … … 114 106 gc.gridx = 0; 115 107 gc.weightx = 0.0; 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 } 108 add(new JLabel(tr("Redirect URL:")), gc); 121 109 122 110 gc.gridx = 1; … … 147 135 SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL); 148 136 149 if (this.oauthVersion == OAuthVersion.OAuth10a) {150 // -- OSM login URL151 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 URL162 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 }172 173 137 ilUseDefault = new UseDefaultItemListener(); 174 138 cbUseDefaults.addItemListener(ilUseDefault); 139 cbUseDefaults.setSelected(Config.getPref().getBoolean("oauth.settings.use-default", true)); 175 140 } 176 141 177 142 protected boolean hasCustomSettings() { 178 OAuthParameters params = OAuthParameters.createDefault(apiUrl);143 IOAuthParameters params = OAuthParameters.createDefault(apiUrl, OAuthVersion.OAuth20); 179 144 return !params.equals(getAdvancedParameters()); 180 145 } … … 211 176 212 177 protected void resetToDefaultSettings() { 213 cbUseDefaults.setSelected(true);214 178 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 } 235 236 setChildComponentsEnabled(false); 179 GuiHelper.runInEDTAndWaitWithException(() -> { 180 cbUseDefaults.setSelected(true); 181 switch (this.oauthVersion) { 182 case OAuth20: 183 case OAuth21: 184 OAuth20Parameters params20 = (OAuth20Parameters) iParams; 185 tfConsumerKey.setText(params20.getClientId()); 186 tfConsumerSecret.setText(params20.getClientSecret()); 187 tfAccessTokenURL.setText(params20.getAccessTokenUrl()); 188 tfAuthoriseURL.setText(params20.getAuthorizationUrl()); 189 tfRequestTokenURL.setText(params20.getRedirectUri()); 190 break; 191 default: 192 throw new UnsupportedOperationException("Unsupported OAuth version: " + this.oauthVersion); 193 } 194 setChildComponentsEnabled(false); 195 }); 237 196 } 238 197 … … 253 212 if (cbUseDefaults.isSelected()) 254 213 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 214 return new OAuth20Parameters( 266 215 tfConsumerKey.getText(), … … 286 235 cbUseDefaults.setSelected(false); 287 236 setChildComponentsEnabled(true); 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) { 237 if (parameters instanceof OAuth20Parameters) { 298 238 OAuth20Parameters parameters20 = (OAuth20Parameters) parameters; 299 239 tfConsumerKey.setText(parameters20.getClientId()); … … 317 257 boolean useDefault = Config.getPref().getBoolean("oauth.settings.use-default", true); 318 258 ilUseDefault.setEnabled(false); 319 if (useDefault) { 320 resetToDefaultSettings(); 321 } else { 322 setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl)); 323 } 324 ilUseDefault.setEnabled(true); 259 MainApplication.worker.execute(() -> { 260 if (useDefault) { 261 this.resetToDefaultSettings(); 262 } else { 263 setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl, OAuthVersion.OAuth20)); 264 } 265 GuiHelper.runInEDT(() -> ilUseDefault.setEnabled(true)); 266 }); 325 267 } 326 268 … … 331 273 Config.getPref().putBoolean("oauth.settings.use-default", cbUseDefaults.isSelected()); 332 274 if (cbUseDefaults.isSelected()) { 333 new OAuthParameters(null, null, null, null, null, null, null).rememberPreferences();275 MainApplication.worker.execute(() -> OAuthParameters.createDefault().rememberPreferences()); 334 276 } else { 335 277 getAdvancedParameters().rememberPreferences(); … … 349 291 return; 350 292 } 351 resetToDefaultSettings();293 MainApplication.worker.execute(AdvancedOAuthPropertiesPanel.this::resetToDefaultSettings); 352 294 break; 353 295 case ItemEvent.DESELECTED: … … 372 314 this.apiUrl = apiUrl; 373 315 if (cbUseDefaults.isSelected()) { 374 resetToDefaultSettings();316 MainApplication.worker.execute(this::resetToDefaultSettings); 375 317 } 376 318 } -
trunk/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java
r18650 r18991 13 13 import java.awt.event.ActionEvent; 14 14 import java.io.IOException; 15 import java.net.Authenticator.RequestorType;16 import java.net.PasswordAuthentication;17 15 import java.util.concurrent.Executor; 18 16 … … 24 22 import javax.swing.JPanel; 25 23 import javax.swing.JTabbedPane; 26 import javax.swing.event.DocumentEvent;27 import javax.swing.event.DocumentListener;28 import javax.swing.text.JTextComponent;29 24 import javax.swing.text.html.HTMLEditorKit; 30 25 31 import org.openstreetmap.josm.data.oauth. OAuthParameters;32 import org.openstreetmap.josm.data.oauth.OAuth Token;26 import org.openstreetmap.josm.data.oauth.IOAuthToken; 27 import org.openstreetmap.josm.data.oauth.OAuthVersion; 33 28 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 34 29 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 35 30 import org.openstreetmap.josm.gui.help.HelpUtil; 36 import org.openstreetmap.josm.gui.preferences.server.UserNameValidator;37 31 import org.openstreetmap.josm.gui.util.GuiHelper; 38 import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator;39 32 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 40 33 import org.openstreetmap.josm.gui.widgets.JMultilineLabel; 41 import org.openstreetmap.josm.gui.widgets.JosmPasswordField;42 import org.openstreetmap.josm.gui.widgets.JosmTextField;43 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;44 34 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; 45 import org.openstreetmap.josm.io.OsmApi;46 35 import org.openstreetmap.josm.io.OsmTransferException; 47 import org.openstreetmap.josm.io.auth.CredentialsAgent;48 import org.openstreetmap.josm.io.auth.CredentialsAgentException;49 import org.openstreetmap.josm.io.auth.CredentialsManager;50 36 import org.openstreetmap.josm.tools.ImageProvider; 51 37 import org.openstreetmap.josm.tools.Logging; 52 import org.openstreetmap.josm.tools.Utils;53 38 import org.xml.sax.SAXException; 54 39 55 40 /** 56 * This is a nUI which supports a JOSM user to get an OAuth Access Token in a fully41 * This is a UI which supports a JOSM user to get an OAuth Access Token in a fully 57 42 * automatic process. 58 43 * … … 60 45 */ 61 46 public class FullyAutomaticAuthorizationUI extends AbstractAuthorizationUI { 62 63 private final JosmTextField tfUserName = new JosmTextField();64 private final JosmPasswordField tfPassword = new JosmPasswordField();65 private transient UserNameValidator valUserName;66 private transient PasswordValidator valPassword;67 47 private final AccessTokenInfoPanel pnlAccessTokenInfo = new AccessTokenInfoPanel(); 68 48 private OsmPrivilegesPanel pnlOsmPrivileges; … … 105 85 + tr("Please enter your OSM user name and password. The password will <strong>not</strong> be saved " 106 86 + "in clear text in the JOSM preferences and it will be submitted to the OSM server <strong>only once</strong>. " 107 + "Subsequent data upload requests don''t use your password any more.").replace All("\\. ", ".<br>")87 + "Subsequent data upload requests don''t use your password any more.").replace(". ", ".<br>") 108 88 + "</p>" 109 89 + "</body></html>"); … … 119 99 pnl.add(new JLabel(tr("Username: ")), gc); 120 100 121 gc.gridx = 1;122 gc.weightx = 1.0;123 pnl.add(tfUserName, gc);124 SelectAllOnFocusGainedDecorator.decorate(tfUserName);125 valUserName = new UserNameValidator(tfUserName);126 valUserName.validate();127 128 101 // the password input field 129 102 gc.anchor = GridBagConstraints.NORTHWEST; … … 134 107 pnl.add(new JLabel(tr("Password:")), gc); 135 108 109 // filler - grab remaining space 136 110 gc.gridx = 1; 137 gc.weightx = 1.0;138 pnl.add(tfPassword, gc);139 SelectAllOnFocusGainedDecorator.decorate(tfPassword);140 valPassword = new PasswordValidator(tfPassword);141 valPassword.validate();142 143 // filler - grab remaining space144 111 gc.gridy = 4; 145 112 gc.gridwidth = 2; … … 168 135 169 136 /** 170 * Initializes the panel with values from the preferences171 * @param paramApiUrl the API URL172 */173 @Override174 public void initialize(String paramApiUrl) {175 super.initialize(paramApiUrl);176 CredentialsAgent cm = CredentialsManager.getInstance();177 try {178 PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());179 if (pa == null) {180 tfUserName.setText("");181 tfPassword.setText("");182 } else {183 tfUserName.setText(pa.getUserName() == null ? "" : pa.getUserName());184 tfPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));185 }186 } catch (CredentialsAgentException e) {187 Logging.error(e);188 tfUserName.setText("");189 tfPassword.setText("");190 }191 }192 193 /**194 137 * Builds the panel with the action button for starting the authorisation 195 138 * … … 200 143 201 144 RunAuthorisationAction runAuthorisationAction = new RunAuthorisationAction(); 202 tfPassword.getDocument().addDocumentListener(runAuthorisationAction);203 tfUserName.getDocument().addDocumentListener(runAuthorisationAction);204 145 pnl.add(new JButton(runAuthorisationAction)); 205 146 return pnl; … … 289 230 } 290 231 291 protected String getOsmUserName() {292 return tfUserName.getText();293 }294 295 protected String getOsmPassword() {296 return String.valueOf(tfPassword.getPassword());297 }298 299 232 /** 300 233 * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL. … … 302 235 * @param executor the executor used for running the HTTP requests for the authorization 303 236 * @since 5422 304 */ 237 * @deprecated since 18991 238 */ 239 @Deprecated 305 240 public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor) { 306 super(apiUrl); 241 this(apiUrl, executor, OAuthVersion.OAuth10a); 242 } 243 244 /** 245 * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL. 246 * @param apiUrl The OSM API URL 247 * @param executor the executor used for running the HTTP requests for the authorization 248 * @param oAuthVersion The OAuth version to use for this UI 249 * @since 18991 250 */ 251 public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) { 252 super(apiUrl, oAuthVersion); 307 253 this.executor = executor; 308 254 build(); … … 315 261 316 262 @Override 317 protected void setAccessToken( OAuthToken accessToken) {263 protected void setAccessToken(IOAuthToken accessToken) { 318 264 super.setAccessToken(accessToken); 319 265 pnlAccessTokenInfo.setAccessToken(accessToken); … … 323 269 * Starts the authorisation process 324 270 */ 325 class RunAuthorisationAction extends AbstractAction implements DocumentListener{271 class RunAuthorisationAction extends AbstractAction { 326 272 RunAuthorisationAction() { 327 273 putValue(NAME, tr("Authorize now")); 328 274 new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this); 329 275 putValue(SHORT_DESCRIPTION, tr("Click to redirect you to the authorization form on the JOSM web site")); 330 updateEnabledState();331 276 } 332 277 … … 334 279 public void actionPerformed(ActionEvent evt) { 335 280 executor.execute(new FullyAutomaticAuthorisationTask(FullyAutomaticAuthorizationUI.this)); 336 }337 338 protected final void updateEnabledState() {339 setEnabled(valPassword.isValid() && valUserName.isValid());340 }341 342 @Override343 public void changedUpdate(DocumentEvent e) {344 updateEnabledState();345 }346 347 @Override348 public void insertUpdate(DocumentEvent e) {349 updateEnabledState();350 }351 352 @Override353 public void removeUpdate(DocumentEvent e) {354 updateEnabledState();355 281 } 356 282 } … … 386 312 FullyAutomaticAuthorizationUI.this, 387 313 getApiUrl(), 388 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),389 314 getAccessToken() 390 315 )); 391 }392 }393 394 static class PasswordValidator extends DefaultTextComponentValidator {395 PasswordValidator(JTextComponent tc) {396 super(tc, tr("Please enter your OSM password"), tr("The password cannot be empty. Please enter your OSM password"));397 316 } 398 317 } … … 439 358 + "Please check your advanced setting and try again." 440 359 + "</html>", 441 ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getAuthoriseUrl()),360 getAdvancedPropertiesPanel().getAdvancedParameters().getAuthorizationUrl()), 442 361 tr("OAuth authorization failed"), 443 362 JOptionPane.ERROR_MESSAGE, … … 446 365 } 447 366 448 protected void alertLoginFailed() {449 final String loginUrl = ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getOsmLoginUrl();450 HelpAwareOptionPane.showOptionDialog(451 FullyAutomaticAuthorizationUI.this,452 tr("<html>"453 + "The automatic process for retrieving an OAuth Access Token<br>"454 + "from the OSM server failed. JOSM failed to log into {0}<br>"455 + "for user {1}.<br><br>"456 + "Please check username and password and try again."457 +"</html>",458 loginUrl,459 Utils.escapeReservedCharactersHTML(getOsmUserName())),460 tr("OAuth authorization failed"),461 JOptionPane.ERROR_MESSAGE,462 HelpUtil.ht("/Dialog/OAuthAuthorisationWizard#FullyAutomaticProcessFailed")463 );464 }465 466 367 protected void handleException(final OsmOAuthAuthorizationException e) { 467 Runnable r = () -> { 468 if (e instanceof OsmLoginFailedException) { 469 alertLoginFailed(); 470 } else { 471 alertAuthorisationFailed(); 368 Logging.error(e); 369 GuiHelper.runInEDT(this::alertAuthorisationFailed); 370 } 371 372 @Override 373 protected void realRun() throws SAXException, IOException, OsmTransferException { 374 getProgressMonitor().setTicksCount(2); 375 OAuthAuthorizationWizard.authorize(true, token -> { 376 if (!canceled) { 377 getProgressMonitor().worked(1); 378 GuiHelper.runInEDT(() -> { 379 prepareUIForResultDisplay(); 380 setAccessToken(token.orElse(null)); 381 }); 472 382 } 473 }; 474 Logging.error(e); 475 GuiHelper.runInEDT(r); 476 } 477 478 @Override 479 protected void realRun() throws SAXException, IOException, OsmTransferException { 480 try { 481 getProgressMonitor().setTicksCount(3); 482 OsmOAuthAuthorizationClient authClient = new OsmOAuthAuthorizationClient( 483 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters() 484 ); 485 OAuthToken requestToken = authClient.getRequestToken( 486 getProgressMonitor().createSubTaskMonitor(1, false) 487 ); 488 getProgressMonitor().worked(1); 489 if (canceled) return; 490 authClient.authorise( 491 requestToken, 492 getOsmUserName(), 493 getOsmPassword(), 494 pnlOsmPrivileges.getPrivileges(), 495 getProgressMonitor().createSubTaskMonitor(1, false) 496 ); 497 getProgressMonitor().worked(1); 498 if (canceled) return; 499 final OAuthToken accessToken = authClient.getAccessToken( 500 getProgressMonitor().createSubTaskMonitor(1, false) 501 ); 502 getProgressMonitor().worked(1); 503 if (canceled) return; 504 GuiHelper.runInEDT(() -> { 505 prepareUIForResultDisplay(); 506 setAccessToken(accessToken); 507 }); 508 } catch (final OsmOAuthAuthorizationException e) { 509 handleException(e); 510 } 383 }, getApiUrl(), getOAuthVersion()); 384 getProgressMonitor().worked(1); 511 385 } 512 386 } -
trunk/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java
r18650 r18991 25 25 import javax.swing.text.JTextComponent; 26 26 27 import org.openstreetmap.josm.data.oauth.OAuth20Exception; 28 import org.openstreetmap.josm.data.oauth.OAuth20Token; 27 29 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 28 import org.openstreetmap.josm.data.oauth.OAuthParameters; 29 import org.openstreetmap.josm.data.oauth.OAuthToken; 30 import org.openstreetmap.josm.data.oauth.OAuthVersion; 30 31 import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator; 31 32 import org.openstreetmap.josm.gui.widgets.HtmlPanel; … … 33 34 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator; 34 35 import org.openstreetmap.josm.tools.ImageProvider; 36 import org.openstreetmap.josm.tools.JosmRuntimeException; 35 37 36 38 /** … … 43 45 private final JosmTextField tfAccessTokenKey = new JosmTextField(); 44 46 private transient AccessTokenKeyValidator valAccessTokenKey; 45 private final JosmTextField tfAccessTokenSecret = new JosmTextField();46 private transient AccessTokenSecretValidator valAccessTokenSecret;47 47 private final JCheckBox cbSaveToPreferences = new JCheckBox(tr("Save Access Token in preferences")); 48 48 private final HtmlPanel pnlMessage = new HtmlPanel(); … … 54 54 * @param executor the executor used for running the HTTP requests for the authorization 55 55 * @since 5422 56 * @deprecated since 18991, use {@link ManualAuthorizationUI#ManualAuthorizationUI(String, Executor, OAuthVersion)} 57 * instead. 56 58 */ 59 @Deprecated 57 60 public ManualAuthorizationUI(String apiUrl, Executor executor) { 58 super(/* dont pass apiURL because setApiUrl is overridden and references a local field */); 61 this(apiUrl, executor, OAuthVersion.OAuth10a); 62 } 63 64 /** 65 * Constructs a new {@code ManualAuthorizationUI} for the given API URL. 66 * @param apiUrl The OSM API URL 67 * @param executor the executor used for running the HTTP requests for the authorization 68 * @param oAuthVersion The OAuthVersion to use for this UI 69 * @since 18991 70 */ 71 public ManualAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) { 72 super(null /* don't pass apiURL because setApiUrl is overridden and references a local field */, 73 oAuthVersion); 59 74 setApiUrl(apiUrl); 60 75 this.executor = executor; … … 95 110 tfAccessTokenKey.getDocument().addDocumentListener(accessTokenBuilder); 96 111 97 // the access token key input field98 gc.gridy = 2;99 gc.gridx = 0;100 gc.weightx = 0.0;101 pnl.add(new JLabel(tr("Access Token Secret:")), gc);102 103 gc.gridx = 1;104 gc.weightx = 1.0;105 pnl.add(tfAccessTokenSecret, gc);106 SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenSecret);107 valAccessTokenSecret = new AccessTokenSecretValidator(tfAccessTokenSecret);108 valAccessTokenSecret.validate();109 tfAccessTokenSecret.getDocument().addDocumentListener(accessTokenBuilder);110 111 112 // the checkbox for saving to preferences 112 113 gc.gridy = 3; … … 185 186 } 186 187 187 private static class AccessTokenSecretValidator extends DefaultTextComponentValidator {188 AccessTokenSecretValidator(JTextComponent tc) {189 super(tc, tr("Please enter an Access Token Secret"),190 tr("The Access Token Secret must not be empty. Please enter an Access Token Secret"));191 }192 }193 194 188 class AccessTokenBuilder implements DocumentListener { 195 189 196 190 public void build() { 197 if (!valAccessTokenKey.isValid() || !valAccessTokenSecret.isValid()) {191 if (!valAccessTokenKey.isValid()) { 198 192 setAccessToken(null); 199 193 } else { 200 setAccessToken(new OAuthToken(tfAccessTokenKey.getText().trim(), tfAccessTokenSecret.getText().trim())); 194 try { 195 setAccessToken(new OAuth20Token(getOAuthParameters(), "{\"token_type\":\"bearer\", \"access_token\"" 196 + tfAccessTokenKey.getText().trim() + "\"}")); 197 } catch (OAuth20Exception e) { 198 throw new JosmRuntimeException(e); 199 } 201 200 } 202 201 } … … 234 233 ManualAuthorizationUI.this, 235 234 getApiUrl(), 236 (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),237 235 getAccessToken() 238 236 ); -
trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
r18650 r18991 20 20 import java.net.URL; 21 21 import java.util.Objects; 22 import java.util.Optional; 22 23 import java.util.concurrent.Executor; 23 24 import java.util.concurrent.FutureTask; 25 import java.util.function.Consumer; 24 26 25 27 import javax.swing.AbstractAction; … … 27 29 import javax.swing.JButton; 28 30 import javax.swing.JDialog; 31 import javax.swing.JOptionPane; 29 32 import javax.swing.JPanel; 30 33 import javax.swing.JScrollPane; … … 33 36 import javax.swing.text.html.HTMLEditorKit; 34 37 38 import org.openstreetmap.josm.data.oauth.IOAuthParameters; 39 import org.openstreetmap.josm.data.oauth.IOAuthToken; 40 import org.openstreetmap.josm.data.oauth.OAuth20Authorization; 35 41 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 36 42 import org.openstreetmap.josm.data.oauth.OAuthParameters; 37 import org.openstreetmap.josm.data.oauth.OAuthToken; 43 import org.openstreetmap.josm.data.oauth.OAuthVersion; 44 import org.openstreetmap.josm.data.oauth.osm.OsmScopes; 38 45 import org.openstreetmap.josm.gui.MainApplication; 39 46 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction; … … 43 50 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 44 51 import org.openstreetmap.josm.gui.widgets.JMultilineLabel; 52 import org.openstreetmap.josm.io.auth.CredentialsManager; 53 import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 45 54 import org.openstreetmap.josm.spi.preferences.Config; 46 55 import org.openstreetmap.josm.tools.GBC; … … 59 68 private final AuthorizationProcedure procedure; 60 69 private final String apiUrl; 70 private final OAuthVersion oAuthVersion; 61 71 62 72 private FullyAutomaticAuthorizationUI pnlFullyAutomaticAuthorisationUI; 63 private SemiAutomaticAuthorizationUI pnlSemiAutomaticAuthorisationUI;64 73 private ManualAuthorizationUI pnlManualAuthorisationUI; 65 74 private JScrollPane spAuthorisationProcedureUI; … … 67 76 68 77 /** 69 * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken( OAuthToken) sets the token}78 * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken(String, IOAuthToken)} sets the token 70 79 * and {@link OAuthAccessTokenHolder#setSaveToPreferences(boolean) saves to preferences}. 80 * @param callback Callback to run when authorization is finished 71 81 * @throws UserCancelException if user cancels the operation 72 82 */ 73 public void showDialog() throws UserCancelException { 74 setVisible(true); 75 if (isCanceled()) { 76 throw new UserCancelException(); 83 public void showDialog(Consumer<Optional<IOAuthToken>> callback) throws UserCancelException { 84 if ((this.oAuthVersion == OAuthVersion.OAuth20 || this.oAuthVersion == OAuthVersion.OAuth21) 85 && this.procedure == AuthorizationProcedure.FULLY_AUTOMATIC) { 86 authorize(true, callback, this.apiUrl, this.oAuthVersion); 87 } else { 88 setVisible(true); 89 if (isCanceled()) { 90 throw new UserCancelException(); 91 } 77 92 } 78 93 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance(); 79 holder.setAccessToken( getAccessToken());94 holder.setAccessToken(apiUrl, getAccessToken()); 80 95 holder.setSaveToPreferences(isSaveAccessTokenToPreferences()); 96 } 97 98 /** 99 * Perform the oauth dance 100 * @param startRemoteControl {@code true} to start remote control if it is not already running 101 * @param callback The callback to use to notify that the OAuth dance succeeded 102 * @param apiUrl The API URL to get the token for 103 * @param oAuthVersion The OAuth version that the authorization dance is force 104 */ 105 static void authorize(boolean startRemoteControl, Consumer<Optional<IOAuthToken>> callback, String apiUrl, OAuthVersion oAuthVersion) { 106 final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get()); 107 // TODO: Ask user if they want to start remote control? 108 if (!remoteControlIsRunning && startRemoteControl) { 109 RemoteControl.start(); 110 } 111 new OAuth20Authorization().authorize(OAuthParameters.createDefault(apiUrl, oAuthVersion), token -> { 112 if (!remoteControlIsRunning) { 113 RemoteControl.stop(); 114 } 115 OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, token.orElse(null)); 116 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 117 if (!token.isPresent()) { 118 GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(), 119 tr("Authentication failed, please check browser for details."), 120 tr("OAuth Authentication Failed"), 121 JOptionPane.ERROR_MESSAGE)); 122 } 123 if (callback != null) { 124 callback.accept(token); 125 } 126 }, OsmScopes.read_gpx, OsmScopes.write_gpx, 127 OsmScopes.read_prefs, OsmScopes.write_prefs, 128 OsmScopes.write_api, OsmScopes.write_notes); 81 129 } 82 130 … … 91 139 AcceptAccessTokenAction actAcceptAccessToken = new AcceptAccessTokenAction(); 92 140 pnlFullyAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken); 93 pnlSemiAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);94 141 pnlManualAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken); 95 142 … … 154 201 pnlFullyAutomaticAuthorisationUI.revalidate(); 155 202 break; 156 case SEMI_AUTOMATIC:157 spAuthorisationProcedureUI.getViewport().setView(pnlSemiAutomaticAuthorisationUI);158 pnlSemiAutomaticAuthorisationUI.revalidate();159 break;160 203 case MANUALLY: 161 204 spAuthorisationProcedureUI.getViewport().setView(pnlManualAuthorisationUI); 162 205 pnlManualAuthorisationUI.revalidate(); 163 206 break; 207 default: 208 throw new UnsupportedOperationException("Unsupported auth type: " + procedure); 164 209 } 165 210 validate(); … … 177 222 this.setMinimumSize(new Dimension(500, 300)); 178 223 179 pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor); 180 pnlSemiAutomaticAuthorisationUI = new SemiAutomaticAuthorizationUI(apiUrl, executor); 181 pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor); 224 pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor, oAuthVersion); 225 pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor, oAuthVersion); 182 226 183 227 spAuthorisationProcedureUI = GuiHelper.embedInVerticalScrollPane(new JPanel()); … … 213 257 * @param apiUrl the API URL. Must not be null. 214 258 * @param executor the executor used for running the HTTP requests for the authorization 259 * @param oAuthVersion The OAuth version this wizard is for 215 260 * @throws IllegalArgumentException if apiUrl is null 216 261 */ 217 public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl, Executor executor) { 262 public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl, 263 Executor executor, OAuthVersion oAuthVersion) { 218 264 super(GuiHelper.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL); 219 265 this.procedure = Objects.requireNonNull(procedure, "procedure"); 220 266 this.apiUrl = Objects.requireNonNull(apiUrl, "apiUrl"); 221 267 this.executor = executor; 268 this.oAuthVersion = oAuthVersion; 222 269 build(); 223 270 } … … 236 283 case FULLY_AUTOMATIC: return pnlFullyAutomaticAuthorisationUI; 237 284 case MANUALLY: return pnlManualAuthorisationUI; 238 case SEMI_AUTOMATIC: return pnlSemiAutomaticAuthorisationUI;239 285 default: return null; 240 286 } … … 246 292 * @return the access token. May be null if the wizard was canceled. 247 293 */ 248 public OAuthToken getAccessToken() {294 public IOAuthToken getAccessToken() { 249 295 return getCurrentAuthorisationUI().getAccessToken(); 250 296 } … … 255 301 * @return the current OAuth parameters. 256 302 */ 257 public OAuthParameters getOAuthParameters() {258 return (OAuthParameters)getCurrentAuthorisationUI().getOAuthParameters();303 public IOAuthParameters getOAuthParameters() { 304 return getCurrentAuthorisationUI().getOAuthParameters(); 259 305 } 260 306 … … 276 322 public void initFromPreferences() { 277 323 pnlFullyAutomaticAuthorisationUI.initialize(apiUrl); 278 pnlSemiAutomaticAuthorisationUI.initialize(apiUrl);279 324 pnlManualAuthorisationUI.initialize(apiUrl); 280 325 } … … 316 361 MainApplication.getMainFrame(), 317 362 AuthorizationProcedure.FULLY_AUTOMATIC, 318 serverUrl.toExternalForm(), Utils.newDirectExecutor()); 319 wizard.showDialog(); 363 serverUrl.toString(), Utils.newDirectExecutor(), 364 OAuthVersion.OAuth20); 365 wizard.showDialog(null); 320 366 return wizard; 321 367 }); … … 368 414 } 369 415 370 public final void updateEnabledState(OAuthToken token) { 416 /** 417 * Update the enabled state 418 * @param token The token to use 419 * @since 18991 420 */ 421 public final void updateEnabledState(IOAuthToken token) { 371 422 setEnabled(token != null); 372 423 } … … 376 427 if (!evt.getPropertyName().equals(AbstractAuthorizationUI.ACCESS_TOKEN_PROP)) 377 428 return; 378 updateEnabledState(( OAuthToken) evt.getNewValue());429 updateEnabledState((IOAuthToken) evt.getNewValue()); 379 430 } 380 431 } -
trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
r18918 r18991 12 12 import javax.xml.parsers.ParserConfigurationException; 13 13 14 import org.openstreetmap.josm.data.oauth.IOAuthParameters;15 14 import org.openstreetmap.josm.data.oauth.IOAuthToken; 16 15 import org.openstreetmap.josm.data.oauth.OAuth20Token; 17 import org.openstreetmap.josm.data.oauth.OAuthParameters; 18 import org.openstreetmap.josm.data.oauth.OAuthToken; 16 import org.openstreetmap.josm.data.oauth.OAuthException; 19 17 import org.openstreetmap.josm.data.osm.UserInfo; 20 18 import org.openstreetmap.josm.gui.HelpAwareOptionPane; … … 34 32 import org.xml.sax.SAXException; 35 33 36 import oauth.signpost.OAuthConsumer;37 import oauth.signpost.exception.OAuthException;38 39 34 /** 40 35 * Checks whether an OSM API server can be accessed with a specific Access Token. 41 * 36 * <p> 42 37 * It retrieves the user details for the user which is authorized to access the server with 43 38 * this token. … … 45 40 */ 46 41 public class TestAccessTokenTask extends PleaseWaitRunnable { 47 private final OAuthToken tokenOAuth1;48 42 private final IOAuthToken tokenOAuth2; 49 private final IOAuthParameters oauthParameters;50 43 private boolean canceled; 51 44 private final Component parent; … … 58 51 * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog is displayed 59 52 * @param apiUrl the API URL. Must not be null. 60 * @param parameters the OAuth parameters. Must not be null.61 53 * @param accessToken the Access Token. Must not be null. 54 * @since 18991 62 55 */ 63 public TestAccessTokenTask(Component parent, String apiUrl, OAuthParameters parameters,OAuthToken accessToken) {56 public TestAccessTokenTask(Component parent, String apiUrl, IOAuthToken accessToken) { 64 57 super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */); 65 58 CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl"); 66 CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");67 59 CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken"); 68 this.tokenOAuth1 = accessToken;69 this.tokenOAuth2 = null;70 this.oauthParameters = parameters;71 this.parent = parent;72 this.apiUrl = apiUrl;73 }74 75 /**76 * Create the task77 *78 * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog is displayed79 * @param apiUrl the API URL. Must not be null.80 * @param parameters the OAuth parameters. Must not be null.81 * @param accessToken the Access Token. Must not be null.82 * @since 1876483 */84 public TestAccessTokenTask(Component parent, String apiUrl, IOAuthParameters parameters, IOAuthToken accessToken) {85 super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */);86 CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");87 CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");88 CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken");89 this.tokenOAuth1 = null;90 60 this.tokenOAuth2 = accessToken; 91 this.oauthParameters = parameters;92 61 this.parent = parent; 93 62 this.apiUrl = apiUrl; … … 110 79 111 80 protected void sign(HttpClient con) throws OAuthException { 112 if (oauthParameters instanceof OAuthParameters) { 113 OAuthConsumer consumer = ((OAuthParameters) oauthParameters).buildConsumer(); 114 consumer.setTokenWithSecret(tokenOAuth1.getKey(), tokenOAuth1.getSecret()); 115 consumer.sign(con); 116 } else { 117 try { 118 this.tokenOAuth2.sign(con); 119 } catch (org.openstreetmap.josm.data.oauth.OAuthException e) { 120 // Adapt our OAuthException to the SignPost OAuth exception 121 throw new OAuthException(e) {}; 122 } 123 } 81 this.tokenOAuth2.sign(con); 124 82 } 125 83 … … 315 273 316 274 private String getAuthKey() { 317 if (this.tokenOAuth1 != null) {318 return this.tokenOAuth1.getKey();319 }320 275 if (this.tokenOAuth2 instanceof OAuth20Token) { 321 276 return ((OAuth20Token) this.tokenOAuth2).getBearerToken(); 322 277 } 323 throw new IllegalArgumentException("Only OAuth 1 and OAuth2 tokens are understood: " + this.tokenOAuth2);278 throw new IllegalArgumentException("Only OAuth2 tokens are understood: " + this.tokenOAuth2); 324 279 } 325 280 } -
trunk/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java
r18828 r18991 39 39 /** indicates whether we use basic authentication */ 40 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 41 /** indicates whether we use OAuth 2.0 as authentication scheme */ 44 42 private final JRadioButton rbOAuth20 = new JRadioButton(); … … 47 45 /** the panel for the basic authentication parameters */ 48 46 private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences; 49 /** the panel for the OAuth 1.0a authentication parameters */50 private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;51 47 /** the panel for the OAuth 2.0 authentication parameters */ 52 48 private OAuthAuthenticationPreferencesPanel pnlOAuth20Preferences; … … 59 55 final boolean defaultApi = JosmUrls.getInstance().getDefaultOsmApiUrl().equals(apiUrl); 60 56 rbBasicAuthentication.setEnabled(rbBasicAuthentication.isSelected() || "basic".equals(authMethod) || isExpert || !defaultApi); 61 rbOAuth.setEnabled(rbOAuth.isSelected() || "oauth".equals(authMethod) || isExpert || !defaultApi);62 57 }; 63 58 … … 85 80 rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password")); 86 81 rbBasicAuthentication.addItemListener(authChangeListener); 87 88 //-- radio button for OAuth 1.0a89 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 82 //-- radio button for OAuth 2.0 95 83 buttonPanel.add(rbOAuth20); 84 rbOAuth20.setSelected(true); // This must before adding the listener; otherwise, saveToPreferences is called prior to initFromPreferences 96 85 rbOAuth20.setText(tr("Use OAuth {0}", "2.0")); 97 86 rbOAuth20.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "2.0")); … … 102 91 ButtonGroup bg = new ButtonGroup(); 103 92 bg.add(rbBasicAuthentication); 104 bg.add(rbOAuth);105 93 bg.add(rbOAuth20); 106 94 … … 119 107 //-- the two panels for authentication parameters 120 108 pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel(); 121 pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth10a);122 109 pnlOAuth20Preferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth20); 123 110 124 111 ExpertToggleAction.addExpertModeChangeListener(expertModeChangeListener, true); 125 112 126 rbOAuth20.setSelected(true);127 113 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER); 128 114 } … … 133 119 public final void initFromPreferences() { 134 120 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); 121 if ("basic".equals(authMethod)) { 122 rbBasicAuthentication.setSelected(true); 123 } else if ("oauth20".equals(authMethod)) { 124 rbOAuth20.setSelected(true); 125 } else { 126 Logging.warn( 127 tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''OAuth 2.0 Authentication''.", 128 "osm-server.auth-method", authMethod)); 129 rbOAuth20.setSelected(true); 149 130 } 150 131 pnlBasicAuthPreferences.initFromPreferences(); 151 pnlOAuthPreferences.initFromPreferences();152 132 pnlOAuth20Preferences.initFromPreferences(); 153 133 } … … 161 141 if (rbBasicAuthentication.isSelected()) { 162 142 authMethod = "basic"; 163 } else if (rbOAuth.isSelected()) {164 authMethod = "oauth";165 143 } else if (rbOAuth20.isSelected()) { 166 144 authMethod = "oauth20"; … … 174 152 OAuthAccessTokenHolder.getInstance().clear(); 175 153 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 176 } else if ("oauth".equals(authMethod)) { 154 } else if ("oauth20".equals(authMethod)) { 155 // oauth20 177 156 // clear the password in the preferences 178 157 pnlBasicAuthPreferences.clearPassword(); 179 pnlBasicAuthPreferences.saveToPreferences();180 pnlOAuthPreferences.saveToPreferences();181 } else { // oauth20182 // clear the password in the preferences183 pnlBasicAuthPreferences.clearPassword();184 pnlBasicAuthPreferences.saveToPreferences();185 158 pnlOAuth20Preferences.saveToPreferences(); 186 159 } … … 188 161 if ("basic".equals(authMethod)) { 189 162 UserIdentityManager.getInstance().initFromPreferences(); 163 } else if (OsmApi.isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())) { 164 UserIdentityManager.getInstance().initFromOAuth(); 190 165 } else { 191 UserIdentityManager.getInstance(). initFromOAuth();166 UserIdentityManager.getInstance().setAnonymous(); 192 167 } 193 168 } … … 205 180 pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER); 206 181 pnlBasicAuthPreferences.revalidate(); 207 } else if (rbOAuth.isSelected()) {208 pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER);209 pnlOAuthPreferences.saveToPreferences();210 pnlOAuthPreferences.initFromPreferences();211 pnlOAuthPreferences.revalidate();212 182 } else if (rbOAuth20.isSelected()) { 213 183 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER); … … 222 192 @Override 223 193 public void propertyChange(PropertyChangeEvent evt) { 224 if (pnlOAuthPreferences != null) {225 pnlOAuthPreferences.propertyChange(evt);226 }227 194 if (pnlOAuth20Preferences != null) { 228 195 pnlOAuth20Preferences.propertyChange(evt); -
trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java
r18786 r18991 6 6 import java.awt.BorderLayout; 7 7 import java.awt.Color; 8 import java.awt.Component; 8 9 import java.awt.FlowLayout; 9 10 import java.awt.Font; … … 15 16 import java.beans.PropertyChangeEvent; 16 17 import java.beans.PropertyChangeListener; 18 import java.net.URI; 19 import java.util.Arrays; 20 import java.util.Objects; 17 21 18 22 import javax.swing.AbstractAction; … … 21 25 import javax.swing.JCheckBox; 22 26 import javax.swing.JLabel; 23 import javax.swing.JOptionPane;24 27 import javax.swing.JPanel; 25 28 26 29 import org.openstreetmap.josm.actions.ExpertToggleAction; 27 30 import org.openstreetmap.josm.data.oauth.IOAuthToken; 28 import org.openstreetmap.josm.data.oauth.OAuth20Authorization;29 31 import org.openstreetmap.josm.data.oauth.OAuth20Token; 30 32 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder; 31 33 import org.openstreetmap.josm.data.oauth.OAuthParameters; 32 import org.openstreetmap.josm.data.oauth.OAuthToken;33 34 import org.openstreetmap.josm.data.oauth.OAuthVersion; 34 import org.openstreetmap.josm.data. oauth.osm.OsmScopes;35 import org.openstreetmap.josm.data.validation.routines.DomainValidator; 35 36 import org.openstreetmap.josm.gui.MainApplication; 36 37 import org.openstreetmap.josm.gui.oauth.AdvancedOAuthPropertiesPanel; … … 43 44 import org.openstreetmap.josm.io.OsmApi; 44 45 import org.openstreetmap.josm.io.auth.CredentialsManager; 45 import org.openstreetmap.josm.io.remotecontrol.RemoteControl;46 46 import org.openstreetmap.josm.tools.GBC; 47 47 import org.openstreetmap.josm.tools.ImageProvider; 48 48 import org.openstreetmap.josm.tools.Logging; 49 49 import org.openstreetmap.josm.tools.UserCancelException; 50 import org.openstreetmap.josm.tools.Utils; 50 51 51 52 /** … … 69 70 70 71 /** 71 * Create the panel. Uses {@link OAuthVersion#OAuth10a}.72 */73 public OAuthAuthenticationPreferencesPanel() {74 this(OAuthVersion.OAuth10a);75 }76 77 /**78 72 * Create the panel. 79 73 * @param oAuthVersion The OAuth version to use … … 82 76 this.oAuthVersion = oAuthVersion; 83 77 // These must come after we set the oauth version 78 this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(this.oAuthVersion); 84 79 this.pnlNotYetAuthorised = new NotYetAuthorisedPanel(); 85 this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(this.oAuthVersion);86 80 this.pnlAlreadyAuthorised = new AlreadyAuthorisedPanel(); 87 81 build(); … … 124 118 setLayout(new GridBagLayout()); 125 119 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 126 GridBagConstraints gc = new GridBagConstraints();127 128 120 // the panel for the OAuth parameters. pnlAuthorisationMessage is an 129 121 // empty panel. It is going to be filled later, depending on the 130 122 // current OAuth state in JOSM. 131 gc.fill = GridBagConstraints.BOTH; 132 gc.anchor = GridBagConstraints.NORTHWEST; 133 gc.weighty = 1.0; 134 gc.weightx = 1.0; 135 gc.insets = new Insets(10, 0, 0, 0); 136 add(pnlAuthorisationMessage, gc); 123 add(pnlAuthorisationMessage, GBC.eol().fill(GridBagConstraints.BOTH).anchor(GridBagConstraints.NORTHWEST) 124 .weight(1, 1).insets(0, 10, 0, 0)); 125 // the panel with the advanced options 126 add(buildAdvancedPropertiesPanel(), GBC.eol().fill(GridBagConstraints.HORIZONTAL)); 137 127 } 138 128 139 129 protected void refreshView() { 140 130 pnlAuthorisationMessage.removeAll(); 141 if ((this.oAuthVersion == OAuthVersion.OAuth10a && 142 OAuthAccessTokenHolder.getInstance().containsAccessToken()) 143 || OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) { 131 if (OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) { 144 132 pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER); 145 133 pnlAlreadyAuthorised.refreshView(); … … 160 148 this.apiUrl = apiUrl; 161 149 pnlAdvancedProperties.setApiUrl(apiUrl); 150 for (JPanel panel : Arrays.asList(this.pnlNotYetAuthorised, (JPanel) this.pnlAlreadyAuthorised.getComponent(6))) { 151 for (Component component : panel.getComponents()) { 152 if (component instanceof JButton && ((JButton) component).getAction() instanceof AuthoriseNowAction) { 153 ((AuthoriseNowAction) ((JButton) component).getAction()).updateEnabledState(); 154 } 155 } 156 } 162 157 } 163 158 … … 204 199 205 200 // Action for authorising now 206 if (oAuthVersion == OAuthVersion.OAuth10a) { 207 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol()); 208 } 209 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.SEMI_AUTOMATIC)), GBC.eol()); 210 if (oAuthVersion == OAuthVersion.OAuth10a) { 211 JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY)); 212 add(authManually, GBC.eol()); 213 ExpertToggleAction.addVisibilitySwitcher(authManually); 214 } 201 add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol()); 202 JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY)); 203 add(authManually, GBC.eol()); 204 ExpertToggleAction.addVisibilitySwitcher(authManually); 215 205 216 206 // filler - grab remaining space … … 225 215 private class AlreadyAuthorisedPanel extends JPanel { 226 216 private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false); 227 private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);228 217 229 218 /** … … 266 255 add(new JLabel(tr("Access Token Secret:")), gc); 267 256 268 gc.gridx = 1;269 gc.weightx = 1.0;270 add(tfAccessTokenSecret, gc);271 tfAccessTokenSecret.setEditable(false);272 273 257 // -- access token secret 274 258 gc.gridy = 3; … … 281 265 // -- action buttons 282 266 JPanel btns = new JPanel(new FlowLayout(FlowLayout.LEFT)); 283 if (oAuthVersion == OAuthVersion.OAuth10a) { 284 // these want the OAuth 1.0 token information 285 btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC))); 286 } 287 btns.add(new JButton(new TestAuthorisationAction(oAuthVersion))); 267 btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC))); 268 btns.add(new JButton(new TestAuthorisationAction())); 288 269 btns.add(new JButton(new RemoveAuthorisationAction())); 289 270 gc.gridy = 4; … … 293 274 add(btns, gc); 294 275 295 // the panel with the advanced options296 gc.gridy = 5;297 gc.gridx = 0;298 gc.gridwidth = 2;299 gc.weightx = 1.0;300 add(buildAdvancedPropertiesPanel(), gc);301 302 276 // filler - grab the remaining space 303 277 gc.gridy = 6; … … 310 284 protected final void refreshView() { 311 285 switch (oAuthVersion) { 312 case OAuth10a:313 String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey();314 tfAccessTokenKey.setText(v == null ? "" : v);315 v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret();316 tfAccessTokenSecret.setText(v == null ? "" : v);317 tfAccessTokenSecret.setVisible(true);318 break;319 286 case OAuth20: 320 287 case OAuth21: … … 325 292 } 326 293 tfAccessTokenKey.setText(token == null ? "" : token); 327 tfAccessTokenSecret.setVisible(false); 294 break; 295 default: 328 296 } 329 297 cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences()); … … 341 309 putValue(NAME, tr("{0} ({1})", tr("Authorize now"), procedure.getText())); 342 310 putValue(SHORT_DESCRIPTION, procedure.getDescription()); 343 if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC 344 || OAuthAuthenticationPreferencesPanel.this.oAuthVersion != OAuthVersion.OAuth10a) { 311 if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC) { 345 312 new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this); 346 313 } 314 updateEnabledState(); 315 } 316 317 void updateEnabledState() { 318 if (procedure == AuthorizationProcedure.MANUALLY) { 319 this.setEnabled(true); 320 } else if (Utils.isValidUrl(apiUrl) && DomainValidator.getInstance().isValid(URI.create(apiUrl).getHost())) { 321 // We want to avoid trying to make connection with an invalid URL 322 final String currentApiUrl = apiUrl; 323 MainApplication.worker.execute(() -> { 324 final String clientId = OAuthParameters.createDefault(apiUrl, oAuthVersion).getClientId(); 325 if (Objects.equals(apiUrl, currentApiUrl)) { 326 GuiHelper.runInEDT(() -> this.setEnabled(!Utils.isEmpty(clientId))); 327 } 328 }); 329 } 347 330 } 348 331 349 332 @Override 350 333 public void actionPerformed(ActionEvent arg0) { 351 if (OAuthAuthenticationPreferencesPanel.this.oAuthVersion == OAuthVersion.OAuth10a) { 352 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard( 353 OAuthAuthenticationPreferencesPanel.this, 354 procedure, 355 apiUrl, 356 MainApplication.worker); 357 try { 358 wizard.showDialog(); 359 } catch (UserCancelException ignore) { 360 Logging.trace(ignore); 361 return; 362 } 363 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters()); 364 refreshView(); 365 } else { 366 final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get()); 367 // TODO: Ask user if they want to start remote control? 368 if (!remoteControlIsRunning) { 369 RemoteControl.start(); 370 } 371 new OAuth20Authorization().authorize(OAuthParameters.createDefault(OsmApi.getOsmApi().getServerUrl(), oAuthVersion), token -> { 372 if (!remoteControlIsRunning) { 373 RemoteControl.stop(); 374 } 375 OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), token.orElse(null)); 376 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 377 GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView); 378 if (!token.isPresent()) { 379 GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(), 380 tr("Authentication failed, please check browser for details."), 381 tr("OAuth Authentication Failed"), 382 JOptionPane.ERROR_MESSAGE)); 383 } 384 }, OsmScopes.read_gpx, OsmScopes.write_gpx, 385 OsmScopes.read_prefs, OsmScopes.write_prefs, 386 OsmScopes.write_api, OsmScopes.write_notes); 334 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard( 335 OAuthAuthenticationPreferencesPanel.this, 336 procedure, 337 apiUrl, 338 MainApplication.worker, 339 oAuthVersion); 340 try { 341 wizard.showDialog(token -> GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView)); 342 } catch (UserCancelException userCancelException) { 343 Logging.trace(userCancelException); 344 return; 387 345 } 346 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters()); 347 refreshView(); 388 348 } 389 349 } … … 401 361 @Override 402 362 public void actionPerformed(ActionEvent e) { 403 if (oAuthVersion == OAuthVersion.OAuth10a) { 404 OAuthAccessTokenHolder.getInstance().setAccessToken(null); 405 } else { 406 OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, (IOAuthToken) null); 407 } 363 OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, null); 408 364 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); 409 365 refreshView(); … … 430 386 */ 431 387 private class TestAuthorisationAction extends AbstractAction { 432 private final OAuthVersion oAuthVersion;433 434 388 /** 435 389 * Constructs a new {@code TestAuthorisationAction}. 436 390 */ 437 TestAuthorisationAction(OAuthVersion oAuthVersion) { 438 this.oAuthVersion = oAuthVersion; 391 TestAuthorisationAction() { 439 392 putValue(NAME, tr("Test Access Token")); 440 393 putValue(SHORT_DESCRIPTION, tr("Click test access to the OSM server with the current access token")); … … 444 397 @Override 445 398 public void actionPerformed(ActionEvent evt) { 446 if (this.oAuthVersion == OAuthVersion.OAuth10a) { 447 OAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(); 448 OAuthParameters parameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl()); 449 TestAccessTokenTask task = new TestAccessTokenTask( 450 OAuthAuthenticationPreferencesPanel.this, 451 apiUrl, 452 parameters, 453 token 454 ); 455 MainApplication.worker.submit(task); 456 } else { 457 IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20); 458 TestAccessTokenTask task = new TestAccessTokenTask( 459 OAuthAuthenticationPreferencesPanel.this, 460 apiUrl, 461 token.getParameters(), 462 token 463 ); 464 MainApplication.worker.submit(task); 465 } 399 IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20); 400 TestAccessTokenTask task = new TestAccessTokenTask( 401 OAuthAuthenticationPreferencesPanel.this, 402 apiUrl, 403 token 404 ); 405 MainApplication.worker.submit(task); 466 406 } 467 407 } -
trunk/src/org/openstreetmap/josm/io/MessageNotifier.java
r18650 r18991 145 145 try { 146 146 if (JosmPreferencesCredentialAgent.class.equals(credManager.getCredentialsAgentClass())) { 147 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) { 148 return credManager.lookupOAuthAccessToken() != null; 149 } else if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) { 147 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) { 150 148 return credManager.lookupOAuthAccessToken(OsmApi.getOsmApi().getHost()) != null; 151 149 } else if (OsmApi.isUsingOAuth()) { -
trunk/src/org/openstreetmap/josm/io/OsmApi.java
r18871 r18991 52 52 import org.xml.sax.SAXParseException; 53 53 54 import jakarta.annotation.Nullable; 55 54 56 /** 55 57 * Class that encapsulates the communications with the <a href="http://wiki.openstreetmap.org/wiki/API_v0.6">OSM API</a>.<br><br> … … 85 87 86 88 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;89 89 90 90 private URL url; … … 653 653 */ 654 654 public static boolean isUsingOAuth() { 655 return isUsingOAuth(OAuthVersion.OAuth10a) 656 || isUsingOAuth(OAuthVersion.OAuth20) 655 return isUsingOAuth(OAuthVersion.OAuth20) 657 656 || isUsingOAuth(OAuthVersion.OAuth21); 658 657 } … … 665 664 */ 666 665 public static boolean isUsingOAuth(OAuthVersion version) { 667 if (version == OAuthVersion.OAuth10a) { 668 return "oauth".equalsIgnoreCase(getAuthMethod()); 669 } else if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) { 670 return "oauth20".equalsIgnoreCase(getAuthMethod()); 666 if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) { 667 return getAuthMethodVersion() == OAuthVersion.OAuth20 || getAuthMethodVersion() == OAuthVersion.OAuth21; 671 668 } 672 669 return false; … … 680 677 public static boolean isUsingOAuthAndOAuthSetUp(OsmApi api) { 681 678 if (OsmApi.isUsingOAuth()) { 682 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) {683 return OAuthAccessTokenHolder.getInstance().containsAccessToken();684 }685 679 if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20)) { 686 680 return OAuthAccessTokenHolder.getInstance().getAccessToken(api.getBaseUrl(), OAuthVersion.OAuth20) != null; … … 698 692 */ 699 693 public static String getAuthMethod() { 700 setCurrentAuthMethod();701 694 return Config.getPref().get("osm-server.auth-method", "oauth20"); 702 695 } 703 696 704 697 /** 705 * This is a compatibility method for users who currently use OAuth 1.0 -- we are changing the default from oauth to oauth20,706 * but since oauth was the default, pre-existing users will suddenly be switched to oauth20.707 * This should be removed whenever {@link OAuthVersion#OAuth10a} support is removed.708 */ 709 private static void setCurrentAuthMethod() {710 if (!oauthCompatibilitySwitch) {711 oauthCompatibilitySwitch = true;712 final String prefKey = "osm-server.auth-method";713 if ("oauth20".equals(Config.getPref().get(prefKey, "oauth20"))714 && !isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())715 && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {716 Config.getPref().put( prefKey, "oauth");717 }698 * Returns the authentication method set in the preferences 699 * @return the authentication method 700 * @since 18991 701 */ 702 @Nullable 703 public static OAuthVersion getAuthMethodVersion() { 704 switch (getAuthMethod()) { 705 case "oauth20": return OAuthVersion.OAuth20; 706 case "oauth21": return OAuthVersion.OAuth21; 707 case "basic": return null; 708 default: 709 Config.getPref().put("osm-server.auth-method", null); 710 return getAuthMethodVersion(); 718 711 } 719 712 } -
trunk/src/org/openstreetmap/josm/io/OsmConnection.java
r18665 r18991 6 6 import java.lang.reflect.InvocationTargetException; 7 7 import java.net.Authenticator.RequestorType; 8 import java.net.MalformedURLException;9 8 import java.net.URL; 10 9 import java.nio.charset.StandardCharsets; … … 36 35 import org.openstreetmap.josm.tools.Logging; 37 36 38 import oauth.signpost.OAuthConsumer;39 import oauth.signpost.exception.OAuthException;40 41 37 /** 42 38 * Base class that handles common things like authentication for the reader and writer … … 51 47 protected boolean cancel; 52 48 protected HttpClient activeConnection; 53 protected OAuthParameters oauthParameters;54 49 protected IOAuthParameters oAuth20Parameters; 55 50 … … 146 141 147 142 /** 148 * Signs the connection with an OAuth authentication header149 *150 * @param connection the connection151 *152 * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured153 * @throws OsmTransferException if signing fails154 */155 protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {156 if (oauthParameters == null) {157 oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());158 }159 OAuthConsumer consumer = oauthParameters.buildConsumer();160 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();161 if (!holder.containsAccessToken()) {162 obtainAccessToken(connection);163 }164 if (!holder.containsAccessToken()) { // check if wizard completed165 throw new MissingOAuthAccessTokenException();166 }167 consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());168 try {169 consumer.sign(connection);170 } catch (OAuthException e) {171 throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);172 }173 }174 175 /**176 * Obtains an OAuth access token for the connection.177 * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.178 * @param connection connection for which the access token should be obtained179 * @throws MissingOAuthAccessTokenException if the process cannot be completed successfully180 */181 protected void obtainAccessToken(final HttpClient connection) throws MissingOAuthAccessTokenException {182 try {183 final URL apiUrl = new URL(OsmApi.getOsmApi().getServerUrl());184 if (!Objects.equals(apiUrl.getHost(), connection.getURL().getHost())) {185 throw new MissingOAuthAccessTokenException();186 }187 fetcher.obtainAccessToken(apiUrl);188 OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true);189 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());190 } catch (MalformedURLException | InvocationTargetException e) {191 throw new MissingOAuthAccessTokenException(e);192 } catch (InterruptedException e) {193 Thread.currentThread().interrupt();194 throw new MissingOAuthAccessTokenException(e);195 }196 }197 198 /**199 143 * Obtains an OAuth access token for the connection. 200 144 * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}. … … 221 165 } 222 166 // Clean up old token/password 223 OAuthAccessTokenHolder.getInstance().setAccessToken(null);224 167 OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), authToken.orElse(null)); 225 168 OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance()); … … 281 224 addBasicAuthorizationHeader(connection); 282 225 return; 283 case "oauth":284 addOAuthAuthorizationHeader(connection);285 return;286 226 case "oauth20": 287 227 addOAuth20AuthorizationHeader(connection); -
trunk/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
r18877 r18991 7 7 8 8 import org.openstreetmap.josm.data.oauth.IOAuthToken; 9 import org.openstreetmap.josm.data.oauth.OAuthToken;10 9 11 10 import jakarta.annotation.Nullable; … … 65 64 * @return the current OAuth Access Token to access the OSM server. 66 65 * @throws CredentialsAgentException if something goes wrong 66 * @deprecated since 18991 -- OAuth 1.0 is being removed from the OSM API 67 67 */ 68 OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException; 68 @Deprecated 69 default IOAuthToken lookupOAuthAccessToken() throws CredentialsAgentException { 70 throw new CredentialsAgentException("Call to deprecated method"); 71 } 69 72 70 73 /** … … 85 88 * @param accessToken the access Token. null, to remove the Access Token. 86 89 * @throws CredentialsAgentException if something goes wrong 90 * @deprecated since 18991 -- OAuth 1.0 is being removed from the OSM API 87 91 */ 88 void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException; 92 @Deprecated 93 default void storeOAuthAccessToken(IOAuthToken accessToken) throws CredentialsAgentException { 94 throw new CredentialsAgentException("Call to deprecated method"); 95 } 89 96 90 97 /** … … 93 100 * @param host The host the access token is for 94 101 * @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)}.102 * {@link #storeOAuthAccessToken(IOAuthToken)}. 96 103 * @throws CredentialsAgentException if something goes wrong 97 104 * @since 18650 -
trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
r18650 r18991 9 9 import org.openstreetmap.josm.data.UserIdentityManager; 10 10 import org.openstreetmap.josm.data.oauth.IOAuthToken; 11 import org.openstreetmap.josm.data.oauth.OAuthToken;12 11 import org.openstreetmap.josm.io.OsmApi; 13 12 import org.openstreetmap.josm.tools.CheckParameterUtil; … … 17 16 /** 18 17 * CredentialManager is a factory for the single credential agent used. 19 * 18 * <p> 20 19 * Currently, it defaults to replying an instance of {@link JosmPreferencesCredentialAgent}. 21 20 * @since 2641 … … 158 157 159 158 @Override 160 public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {161 return delegate.lookupOAuthAccessToken();162 }163 164 @Override165 159 public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException { 166 160 return delegate.lookupOAuthAccessToken(host); 167 }168 169 @Override170 public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {171 delegate.storeOAuthAccessToken(accessToken);172 161 } 173 162 -
trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
r18723 r18991 18 18 import org.openstreetmap.josm.data.oauth.OAuth20Parameters; 19 19 import org.openstreetmap.josm.data.oauth.OAuth20Token; 20 import org.openstreetmap.josm.data.oauth.OAuthToken;21 20 import org.openstreetmap.josm.data.oauth.OAuthVersion; 22 21 import org.openstreetmap.josm.gui.widgets.HtmlPanel; … … 103 102 } 104 103 105 /**106 * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no107 * Access Token is currently managed by this CredentialManager.108 *109 * @return the current OAuth Access Token to access the OSM server.110 * @throws CredentialsAgentException if something goes wrong111 */112 @Override113 public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {114 String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);115 String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);116 if (accessTokenKey == null && accessTokenSecret == null)117 return null;118 return new OAuthToken(accessTokenKey, accessTokenSecret);119 }120 121 104 @Override 122 105 public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException { … … 141 124 } 142 125 return null; 143 }144 145 /**146 * Stores the OAuth Access Token <code>accessToken</code>.147 *148 * @param accessToken the access Token. null, to remove the Access Token.149 * @throws CredentialsAgentException if something goes wrong150 */151 @Override152 public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {153 if (accessToken == null) {154 Config.getPref().put("oauth.access-token.key", null);155 Config.getPref().put("oauth.access-token.secret", null);156 } else {157 Config.getPref().put("oauth.access-token.key", accessToken.getKey());158 Config.getPref().put("oauth.access-token.secret", accessToken.getSecret());159 }160 126 } 161 127 -
trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java
r18211 r18991 298 298 + "Please launch the preferences dialog and retrieve another OAuth token." 299 299 + "</html>", 300 OAuthAccessTokenHolder.getInstance().getAccessToken Key()300 OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion()) 301 301 ); 302 302 } … … 344 344 + "Please launch the preferences dialog and retrieve another OAuth token." 345 345 + "</html>", 346 OAuthAccessTokenHolder.getInstance().getAccessToken Key(),346 OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion()), 347 347 e.getAccessedUrl() == null ? tr("unknown") : e.getAccessedUrl() 348 348 );
Note:
See TracChangeset
for help on using the changeset viewer.