Subject: [PATCH] Fix #22810: OSM OAuth 1.0a/Basic auth deprecation and removal
---
Index: core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java b/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java
--- a/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/data/oauth/OAuth20Parameters.java	(date 1707931029514)
@@ -147,4 +147,23 @@
         if (this.tokenUrl != null) builder.add(TOKEN_URL, this.tokenUrl);
         return builder.build().toString();
     }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.apiUrl, this.authorizeUrl, this.tokenUrl, this.clientId, this.clientSecret, this.redirectUri);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj != null && this.getClass() == obj.getClass()) {
+            OAuth20Parameters other = (OAuth20Parameters) obj;
+            return Objects.equals(this.clientSecret, other.clientSecret) &&
+                    Objects.equals(this.clientId, other.clientId) &&
+                    Objects.equals(this.redirectUri, other.redirectUri) &&
+                    Objects.equals(this.tokenUrl, other.tokenUrl) &&
+                    Objects.equals(this.authorizeUrl, other.authorizeUrl) &&
+                    Objects.equals(this.apiUrl, other.apiUrl);
+        }
+        return false;
+    }
 }
Index: core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
--- a/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java	(date 1707931029552)
@@ -36,8 +36,6 @@
     }
 
     private boolean saveToPreferences;
-    private String accessTokenKey;
-    private String accessTokenSecret;
 
     private final Map<String, Map<OAuthVersion, IOAuthToken>> tokenMap = new HashMap<>();
 
@@ -52,10 +50,10 @@
 
     /**
      * Sets whether the current access token should be saved to the preferences file.
-     *
+     * <p>
      * If true, the access token is saved in clear text to the preferences file. The same
      * access token can therefore be used in multiple JOSM sessions.
-     *
+     * <p>
      * If false, the access token isn't saved to the preferences file. If JOSM is closed,
      * the access token is lost and new token has to be generated by the OSM server the
      * next time JOSM is used.
@@ -66,52 +64,6 @@
         this.saveToPreferences = saveToPreferences;
     }
 
-    /**
-     * Replies the access token key. null, if no access token key is currently set.
-     *
-     * @return the access token key
-     */
-    public String getAccessTokenKey() {
-        return accessTokenKey;
-    }
-
-    /**
-     * Sets the access token key. Pass in null to remove the current access token key.
-     *
-     * @param accessTokenKey the access token key
-     */
-    public void setAccessTokenKey(String accessTokenKey) {
-        this.accessTokenKey = accessTokenKey;
-    }
-
-    /**
-     * Replies the access token secret. null, if no access token secret is currently set.
-     *
-     * @return the access token secret
-     */
-    public String getAccessTokenSecret() {
-        return accessTokenSecret;
-    }
-
-    /**
-     * Sets the access token secret. Pass in null to remove the current access token secret.
-     *
-     * @param accessTokenSecret access token secret, or null
-     */
-    public void setAccessTokenSecret(String accessTokenSecret) {
-        this.accessTokenSecret = accessTokenSecret;
-    }
-
-    /**
-     * Replies the access token.
-     * @return the access token, can be {@code null}
-     */
-    public OAuthToken getAccessToken() {
-        if (!containsAccessToken())
-            return null;
-        return new OAuthToken(accessTokenKey, accessTokenSecret);
-    }
-
     /**
      * Replies the access token.
      * @param api The api the token is for
@@ -139,32 +91,6 @@
         return null;
     }
 
-    /**
-     * Sets the access token hold by this holder.
-     *
-     * @param accessTokenKey the access token key
-     * @param accessTokenSecret the access token secret
-     */
-    public void setAccessToken(String accessTokenKey, String accessTokenSecret) {
-        this.accessTokenKey = accessTokenKey;
-        this.accessTokenSecret = accessTokenSecret;
-    }
-
-    /**
-     * Sets the access token hold by this holder.
-     *
-     * @param token the access token. Can be null to clear the content in this holder.
-     */
-    public void setAccessToken(OAuthToken token) {
-        if (token == null) {
-            this.accessTokenKey = null;
-            this.accessTokenSecret = null;
-        } else {
-            this.accessTokenKey = token.getKey();
-            this.accessTokenSecret = token.getSecret();
-        }
-    }
-
     /**
      * Sets the access token hold by this holder.
      *
@@ -185,16 +111,6 @@
         }
     }
 
-    /**
-     * Replies true if this holder contains an complete access token, consisting of an
-     * Access Token Key and an Access Token Secret.
-     *
-     * @return true if this holder contains an complete access token
-     */
-    public boolean containsAccessToken() {
-        return accessTokenKey != null && accessTokenSecret != null;
-    }
-
     /**
      * Initializes the content of this holder from the Access Token managed by the
      * credential manager.
@@ -204,19 +120,7 @@
      */
     public void init(CredentialsAgent cm) {
         CheckParameterUtil.ensureParameterNotNull(cm, "cm");
-        OAuthToken token = null;
-        try {
-            token = cm.lookupOAuthAccessToken();
-        } catch (CredentialsAgentException e) {
-            Logging.error(e);
-            Logging.warn(tr("Failed to retrieve OAuth Access Token from credential manager"));
-            Logging.warn(tr("Current credential manager is of type ''{0}''", cm.getClass().getName()));
-        }
         saveToPreferences = Config.getPref().getBoolean("oauth.access-token.save-to-preferences", true);
-        if (token != null) {
-            accessTokenKey = token.getKey();
-            accessTokenSecret = token.getSecret();
-        }
     }
 
     /**
@@ -231,16 +135,10 @@
         Config.getPref().putBoolean("oauth.access-token.save-to-preferences", saveToPreferences);
         try {
             if (!saveToPreferences) {
-                cm.storeOAuthAccessToken(null);
                 for (String host : this.tokenMap.keySet()) {
                     cm.storeOAuthAccessToken(host, null);
                 }
             } else {
-                if (this.accessTokenKey != null && this.accessTokenSecret != null) {
-                    cm.storeOAuthAccessToken(new OAuthToken(accessTokenKey, accessTokenSecret));
-                } else {
-                    cm.storeOAuthAccessToken(null);
-                }
                 for (Map.Entry<String, Map<OAuthVersion, IOAuthToken>> entry : this.tokenMap.entrySet()) {
                     if (entry.getValue().isEmpty()) {
                         cm.storeOAuthAccessToken(entry.getKey(), null);
@@ -264,7 +162,6 @@
      * Clears the content of this holder
      */
     public void clear() {
-        accessTokenKey = null;
-        accessTokenSecret = null;
+        this.tokenMap.clear();
     }
 }
Index: core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
--- a/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java	(date 1707941739037)
@@ -3,42 +3,42 @@
 
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
-import java.util.Objects;
+import java.util.HashMap;
+import java.util.Map;
 
-import jakarta.json.Json;
-import jakarta.json.JsonObject;
-import jakarta.json.JsonReader;
-import jakarta.json.JsonStructure;
-import jakarta.json.JsonValue;
-
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
 import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.spi.preferences.IUrls;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.HttpClient;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
 
-import oauth.signpost.OAuthConsumer;
-import oauth.signpost.OAuthProvider;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import jakarta.json.JsonStructure;
+import jakarta.json.JsonValue;
 
 /**
  * This class manages an immutable set of OAuth parameters.
- * @since 2747
+ * @since 2747 (static factory class since xxx)
  */
-public class OAuthParameters implements IOAuthParameters {
+public final class OAuthParameters {
+    private static final Map<String, JsonObject> RFC8414_RESPONSES = new HashMap<>(1);
+    private static final String OSM_API_DEFAULT = "https://api.openstreetmap.org/api";
+    private static final String OSM_API_DEV = "https://api06.dev.openstreetmap.org/api";
+    private static final String OSM_API_MASTER = "https://master.apis.dev.openstreetmap.org/api";
 
-    /**
-     * The default JOSM OAuth consumer key (created by user josmeditor).
-     */
-    public static final String DEFAULT_JOSM_CONSUMER_KEY = "F7zPYlVCqE2BUH9Hr4SsWZSOnrKjpug1EgqkbsSb";
-    /**
-     * The default JOSM OAuth consumer secret (created by user josmeditor).
-     */
-    public static final String DEFAULT_JOSM_CONSUMER_SECRET = "rIkjpPcBNkMQxrqzcOvOC4RRuYupYr7k8mfP13H5";
+    private OAuthParameters() {
+        // Hide constructor
+    }
 
     /**
      * Replies a set of default parameters for a consumer accessing the standard OSM server
@@ -46,21 +46,8 @@
      *
      * @return a set of default parameters
      */
-    public static OAuthParameters createDefault() {
-        return createDefault(null);
-    }
-
-    /**
-     * Replies a set of default parameters for a consumer accessing an OSM server
-     * at the given API url. URL parameters are only set if the URL equals {@link IUrls#getDefaultOsmApiUrl}
-     * or references the domain "dev.openstreetmap.org", otherwise they may be <code>null</code>.
-     *
-     * @param apiUrl The API URL for which the OAuth default parameters are created. If null or empty, the default OSM API url is used.
-     * @return a set of default parameters for the given {@code apiUrl}
-     * @since 5422
-     */
-    public static OAuthParameters createDefault(String apiUrl) {
-        return (OAuthParameters) createDefault(apiUrl, OAuthVersion.OAuth10a);
+    public static IOAuthParameters createDefault() {
+        return createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20);
     }
 
     /**
@@ -79,8 +66,6 @@
         }
 
         switch (oAuthVersion) {
-            case OAuth10a:
-                return getDefaultOAuth10Parameters(apiUrl);
             case OAuth20:
             case OAuth21: // For now, OAuth 2.1 (draft) is just OAuth 2.0 with mandatory extensions, which we implement.
                 return getDefaultOAuth20Parameters(apiUrl);
@@ -89,6 +74,33 @@
         }
     }
 
+    private static JsonObject getRFC8414Parameters(String apiUrl) {
+        HttpClient client = null;
+        try {
+            final URI apiURI = new URI(apiUrl);
+            final URL rfc8414URL = new URI(apiURI.getScheme(), apiURI.getHost(),
+                    "/.well-known/oauth-authorization-server", null).toURL();
+            client = HttpClient.create(rfc8414URL);
+            HttpClient.Response response = client.connect();
+            if (response.getResponseCode() == 200) {
+                try (BufferedReader reader = response.getContentReader();
+                     JsonReader jsonReader = Json.createReader(reader)) {
+                    JsonStructure structure = jsonReader.read();
+                    if (structure.getValueType() == JsonValue.ValueType.OBJECT) {
+                        return structure.asJsonObject();
+                    }
+                }
+            }
+        } catch (URISyntaxException | IOException e) {
+            throw new JosmRuntimeException(e);
+        } finally {
+            if (client != null) {
+                client.disconnect();
+            }
+        }
+        return Json.createObjectBuilder().build();
+    }
+
     /**
      * Get the default OAuth 2.0 parameters
      * @param apiUrl The API url
@@ -97,41 +109,60 @@
     private static OAuth20Parameters getDefaultOAuth20Parameters(String apiUrl) {
         final String clientId;
         final String clientSecret;
-        final String redirectUri;
+        final String redirectUri = "http://127.0.0.1:8111/oauth_authorization";
         final String baseUrl;
-        if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl) && !"http://invalid".equals(apiUrl)) {
-            clientId = "";
-            clientSecret = "";
-            baseUrl = apiUrl;
-            HttpClient client = null;
-            redirectUri = "";
-            // Check if the server is RFC 8414 compliant
-            try {
-                client = HttpClient.create(new URL(apiUrl + (apiUrl.endsWith("/") ? "" : "/") + ".well-known/oauth-authorization-server"));
-                HttpClient.Response response = client.connect();
-                if (response.getResponseCode() == 200) {
-                    try (BufferedReader reader = response.getContentReader();
-                         JsonReader jsonReader = Json.createReader(reader)) {
-                        JsonStructure structure = jsonReader.read();
-                        if (structure.getValueType() == JsonValue.ValueType.OBJECT) {
-                            return parseAuthorizationServerMetadataResponse(clientId, clientSecret, apiUrl,
-                                    redirectUri, structure.asJsonObject());
-                        }
-                    }
-                }
-            } catch (IOException | OAuthException e) {
+        apiUrl = apiUrl == null ? OsmApi.getOsmApi().getServerUrl() : apiUrl;
+        switch (apiUrl) {
+            case OSM_API_DEV:
+            case OSM_API_MASTER:
+                // This clientId/clientSecret are provided by taylor.smock. Feel free to change if needed, but
+                // do let one of the maintainers with server access know so that they can update the test OAuth
+                // token.
+                clientId = "-QZt6n1btDfqrfJNGUIMZjzcyqTgIV6sy79_W4kmQLM";
+                // Keep secret for dev apis, just in case we want to test something that needs it.
+                clientSecret = "SWnmRD4AdLO-2-ttHE5TR3eLF2McNf7dh0_Z2WNzJdI";
+                break;
+            case OSM_API_DEFAULT:
+                clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI";
+                // We don't actually use the client secret in our authorization flow.
+                clientSecret = null;
+                break;
+            case "https://www.openhistoricalmap.org/api/":
+                // clientId provided by 1ec5 (Minh Nguyễn)
+                clientId = "Hl5yIhFS-Egj6aY7A35ouLOuZl0EHjj8JJQQ46IO96E";
+                clientSecret = null;
+                break;
+            default:
+                clientId = "";
+                clientSecret = null;
+        }
+        baseUrl = apiUrl;
+        // Check if the server is RFC 8414 compliant
+        try {
+            synchronized (RFC8414_RESPONSES) {
+                final JsonObject data;
+                if (NetworkManager.isOffline(apiUrl)) {
+                    data = null;
+                } else {
+                    data = RFC8414_RESPONSES.computeIfAbsent(apiUrl, OAuthParameters::getRFC8414Parameters);
+                }
+                if (data == null || data.isEmpty()) {
+                    RFC8414_RESPONSES.remove(apiUrl);
+                } else {
+                    return parseAuthorizationServerMetadataResponse(clientId, clientSecret, apiUrl,
+                            redirectUri, data);
+                }
+            }
+        } catch (JosmRuntimeException e) {
+            if (e.getCause() instanceof URISyntaxException || e.getCause() instanceof IOException) {
                 Logging.trace(e);
-            } finally {
-                if (client != null) client.disconnect();
-            }
-        } else {
-            clientId = "edPII614Lm0_0zEpc_QzEltA9BUll93-Y-ugRQUoHMI";
-            // We don't actually use the client secret in our authorization flow.
-            clientSecret = null;
-            baseUrl = "https://www.openstreetmap.org/oauth2";
-            redirectUri = "http://127.0.0.1:8111/oauth_authorization";
-            apiUrl = OsmApi.getOsmApi().getBaseUrl();
+            } else {
+                throw e;
+            }
+        } catch (OAuthException e) {
+            Logging.trace(e);
         }
+        // Fall back to guessing the parameters.
         return new OAuth20Parameters(clientId, clientSecret, baseUrl, apiUrl, redirectUri);
     }
 
@@ -153,46 +184,6 @@
         return new OAuth20Parameters(clientId, clientSecret, tokenEndpoint, authorizationEndpoint, apiUrl, redirectUri);
     }
 
-    /**
-     * Get the default OAuth 1.0a parameters
-     * @param apiUrl The api url
-     * @return The default parameters
-     */
-    private static OAuthParameters getDefaultOAuth10Parameters(String apiUrl) {
-        final String consumerKey;
-        final String consumerSecret;
-        final String serverUrl;
-
-        if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) {
-            consumerKey = ""; // a custom consumer key is required
-            consumerSecret = ""; // a custom consumer secret is requireds
-            serverUrl = apiUrl.replaceAll("/api$", "");
-        } else {
-            consumerKey = DEFAULT_JOSM_CONSUMER_KEY;
-            consumerSecret = DEFAULT_JOSM_CONSUMER_SECRET;
-            serverUrl = Config.getUrls().getOSMWebsite();
-        }
-
-        return new OAuthParameters(
-                consumerKey,
-                consumerSecret,
-                serverUrl + "/oauth/request_token",
-                serverUrl + "/oauth/access_token",
-                serverUrl + "/oauth/authorize",
-                serverUrl + "/login",
-                serverUrl + "/logout");
-    }
-
-    /**
-     * Replies a set of parameters as defined in the preferences.
-     *
-     * @param apiUrl the API URL. Must not be null.
-     * @return the parameters
-     */
-    public static OAuthParameters createFromApiUrl(String apiUrl) {
-        return (OAuthParameters) createFromApiUrl(apiUrl, OAuthVersion.OAuth10a);
-    }
-
     /**
      * Replies a set of parameters as defined in the preferences.
      *
@@ -204,16 +195,6 @@
     public static IOAuthParameters createFromApiUrl(String apiUrl, OAuthVersion oAuthVersion) {
         IOAuthParameters parameters = createDefault(apiUrl, oAuthVersion);
         switch (oAuthVersion) {
-            case OAuth10a:
-                OAuthParameters oauth10aParameters = (OAuthParameters) parameters;
-                return new OAuthParameters(
-                    Config.getPref().get("oauth.settings.consumer-key", oauth10aParameters.getConsumerKey()),
-                    Config.getPref().get("oauth.settings.consumer-secret", oauth10aParameters.getConsumerSecret()),
-                    Config.getPref().get("oauth.settings.request-token-url", oauth10aParameters.getRequestTokenUrl()),
-                    Config.getPref().get("oauth.settings.access-token-url", oauth10aParameters.getAccessTokenUrl()),
-                    Config.getPref().get("oauth.settings.authorise-url", oauth10aParameters.getAuthoriseUrl()),
-                    Config.getPref().get("oauth.settings.osm-login-url", oauth10aParameters.getOsmLoginUrl()),
-                    Config.getPref().get("oauth.settings.osm-logout-url", oauth10aParameters.getOsmLogoutUrl()));
             case OAuth20:
             case OAuth21: // Right now, OAuth 2.1 will work with our OAuth 2.0 implementation
                 OAuth20Parameters oAuth20Parameters = (OAuth20Parameters) parameters;
@@ -228,188 +209,4 @@
                 throw new IllegalArgumentException("Unknown OAuth version: " + oAuthVersion);
         }
     }
-
-    /**
-     * Remembers the current values in the preferences.
-     */
-    @Override
-    public void rememberPreferences() {
-        Config.getPref().put("oauth.settings.consumer-key", getConsumerKey());
-        Config.getPref().put("oauth.settings.consumer-secret", getConsumerSecret());
-        Config.getPref().put("oauth.settings.request-token-url", getRequestTokenUrl());
-        Config.getPref().put("oauth.settings.access-token-url", getAccessTokenUrl());
-        Config.getPref().put("oauth.settings.authorise-url", getAuthoriseUrl());
-        Config.getPref().put("oauth.settings.osm-login-url", getOsmLoginUrl());
-        Config.getPref().put("oauth.settings.osm-logout-url", getOsmLogoutUrl());
-    }
-
-    private final String consumerKey;
-    private final String consumerSecret;
-    private final String requestTokenUrl;
-    private final String accessTokenUrl;
-    private final String authoriseUrl;
-    private final String osmLoginUrl;
-    private final String osmLogoutUrl;
-
-    /**
-     * Constructs a new {@code OAuthParameters}.
-     * @param consumerKey consumer key
-     * @param consumerSecret consumer secret
-     * @param requestTokenUrl request token URL
-     * @param accessTokenUrl access token URL
-     * @param authoriseUrl authorise URL
-     * @param osmLoginUrl the OSM login URL (for automatic mode)
-     * @param osmLogoutUrl the OSM logout URL (for automatic mode)
-     * @see #createDefault
-     * @see #createFromApiUrl
-     * @since 9220
-     */
-    public OAuthParameters(String consumerKey, String consumerSecret,
-                           String requestTokenUrl, String accessTokenUrl, String authoriseUrl, String osmLoginUrl, String osmLogoutUrl) {
-        this.consumerKey = consumerKey;
-        this.consumerSecret = consumerSecret;
-        this.requestTokenUrl = requestTokenUrl;
-        this.accessTokenUrl = accessTokenUrl;
-        this.authoriseUrl = authoriseUrl;
-        this.osmLoginUrl = osmLoginUrl;
-        this.osmLogoutUrl = osmLogoutUrl;
-    }
-
-    /**
-     * Creates a clone of the parameters in <code>other</code>.
-     *
-     * @param other the other parameters. Must not be null.
-     * @throws IllegalArgumentException if other is null
-     */
-    public OAuthParameters(OAuthParameters other) {
-        CheckParameterUtil.ensureParameterNotNull(other, "other");
-        this.consumerKey = other.consumerKey;
-        this.consumerSecret = other.consumerSecret;
-        this.accessTokenUrl = other.accessTokenUrl;
-        this.requestTokenUrl = other.requestTokenUrl;
-        this.authoriseUrl = other.authoriseUrl;
-        this.osmLoginUrl = other.osmLoginUrl;
-        this.osmLogoutUrl = other.osmLogoutUrl;
-    }
-
-    /**
-     * Gets the consumer key.
-     * @return The consumer key
-     */
-    public String getConsumerKey() {
-        return consumerKey;
-    }
-
-    /**
-     * Gets the consumer secret.
-     * @return The consumer secret
-     */
-    public String getConsumerSecret() {
-        return consumerSecret;
-    }
-
-    /**
-     * Gets the request token URL.
-     * @return The request token URL
-     */
-    public String getRequestTokenUrl() {
-        return requestTokenUrl;
-    }
-
-    /**
-     * Gets the access token URL.
-     * @return The access token URL
-     */
-    @Override
-    public String getAccessTokenUrl() {
-        return accessTokenUrl;
-    }
-
-    @Override
-    public String getAuthorizationUrl() {
-        return this.authoriseUrl;
-    }
-
-    @Override
-    public OAuthVersion getOAuthVersion() {
-        return OAuthVersion.OAuth10a;
-    }
-
-    @Override
-    public String getClientId() {
-        return this.consumerKey;
-    }
-
-    @Override
-    public String getClientSecret() {
-        return this.consumerSecret;
-    }
-
-    /**
-     * Gets the authorise URL.
-     * @return The authorise URL
-     */
-    public String getAuthoriseUrl() {
-        return this.getAuthorizationUrl();
-    }
-
-    /**
-     * Gets the URL used to login users on the website (for automatic mode).
-     * @return The URL used to login users
-     */
-    public String getOsmLoginUrl() {
-        return osmLoginUrl;
-    }
-
-    /**
-     * Gets the URL used to logout users on the website (for automatic mode).
-     * @return The URL used to logout users
-     */
-    public String getOsmLogoutUrl() {
-        return osmLogoutUrl;
-    }
-
-    /**
-     * Builds an {@link OAuthConsumer} based on these parameters.
-     *
-     * @return the consumer
-     */
-    public OAuthConsumer buildConsumer() {
-        return new SignpostAdapters.OAuthConsumer(consumerKey, consumerSecret);
-    }
-
-    /**
-     * Builds an {@link OAuthProvider} based on these parameters and a OAuth consumer <code>consumer</code>.
-     *
-     * @param consumer the consumer. Must not be null.
-     * @return the provider
-     * @throws IllegalArgumentException if consumer is null
-     */
-    public OAuthProvider buildProvider(OAuthConsumer consumer) {
-        CheckParameterUtil.ensureParameterNotNull(consumer, "consumer");
-        return new SignpostAdapters.OAuthProvider(
-                requestTokenUrl,
-                accessTokenUrl,
-                authoriseUrl
-        );
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        OAuthParameters that = (OAuthParameters) o;
-        return Objects.equals(consumerKey, that.consumerKey) &&
-                Objects.equals(consumerSecret, that.consumerSecret) &&
-                Objects.equals(requestTokenUrl, that.requestTokenUrl) &&
-                Objects.equals(accessTokenUrl, that.accessTokenUrl) &&
-                Objects.equals(authoriseUrl, that.authoriseUrl) &&
-                Objects.equals(osmLoginUrl, that.osmLoginUrl) &&
-                Objects.equals(osmLogoutUrl, that.osmLogoutUrl);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(consumerKey, consumerSecret, requestTokenUrl, accessTokenUrl, authoriseUrl, osmLoginUrl, osmLogoutUrl);
-    }
 }
Index: core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/data/oauth/OAuthToken.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,82 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.oauth;
-
-import java.util.Objects;
-
-import org.openstreetmap.josm.tools.CheckParameterUtil;
-
-import oauth.signpost.OAuthConsumer;
-
-/**
- * An oauth token that has been obtained by JOSM and can be used to authenticate the user on the server.
- */
-public class OAuthToken {
-
-    /**
-     * Creates an OAuthToken from the token currently managed by the {@link OAuthConsumer}.
-     *
-     * @param consumer the consumer
-     * @return the token
-     */
-    public static OAuthToken createToken(OAuthConsumer consumer) {
-        return new OAuthToken(consumer.getToken(), consumer.getTokenSecret());
-    }
-
-    private final String key;
-    private final String secret;
-
-    /**
-     * Creates a new token
-     *
-     * @param key the token key
-     * @param secret the token secret
-     */
-    public OAuthToken(String key, String secret) {
-        this.key = key;
-        this.secret = secret;
-    }
-
-    /**
-     * Creates a clone of another token
-     *
-     * @param other the other token. Must not be null.
-     * @throws IllegalArgumentException if other is null
-     */
-    public OAuthToken(OAuthToken other) {
-        CheckParameterUtil.ensureParameterNotNull(other, "other");
-        this.key = other.key;
-        this.secret = other.secret;
-    }
-
-    /**
-     * Replies the token key
-     *
-     * @return the token key
-     */
-    public String getKey() {
-        return key;
-    }
-
-    /**
-     * Replies the token secret
-     *
-     * @return the token secret
-     */
-    public String getSecret() {
-        return secret;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(key, secret);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null || getClass() != obj.getClass()) return false;
-        OAuthToken that = (OAuthToken) obj;
-        return Objects.equals(key, that.key) &&
-                Objects.equals(secret, that.secret);
-    }
-}
Index: core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java b/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java
--- a/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/data/oauth/OAuthVersion.java	(date 1707938469081)
@@ -7,7 +7,11 @@
  * @since 18650
  */
 public enum OAuthVersion {
-    /** <a href="https://oauth.net/core/1.0a/">OAuth 1.0a</a> */
+    /**
+     * <a href="https://oauth.net/core/1.0a/">OAuth 1.0a</a>
+     * @deprecated The OSM API server has deprecated and will remove OAuth 1.0a support in June 2024.
+     */
+    @Deprecated
     OAuth10a,
     /** <a href="https://datatracker.ietf.org/doc/html/rfc6749">OAuth 2.0</a> */
     OAuth20,
Index: core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java b/core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,162 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.oauth;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Map;
-
-import org.openstreetmap.josm.tools.HttpClient;
-
-import oauth.signpost.AbstractOAuthConsumer;
-import oauth.signpost.AbstractOAuthProvider;
-
-/**
- * Adapters to make {@code oauth.signpost} work with {@link HttpClient}.
- */
-public final class SignpostAdapters {
-
-    private SignpostAdapters() {
-        // Hide constructor for utility classes
-    }
-
-    /**
-     * OAuth provider.
-     */
-    public static class OAuthProvider extends AbstractOAuthProvider {
-
-        private static final long serialVersionUID = 1L;
-
-        /**
-         * Constructs a new {@code OAuthProvider}.
-         * @param requestTokenEndpointUrl request token endpoint URL
-         * @param accessTokenEndpointUrl access token endpoint URL
-         * @param authorizationWebsiteUrl authorization website URL
-         */
-        public OAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl, String authorizationWebsiteUrl) {
-            super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);
-        }
-
-        @Override
-        protected HttpRequest createRequest(String endpointUrl) throws Exception {
-            return new HttpRequest(HttpClient.create(new URL(endpointUrl)));
-        }
-
-        @Override
-        protected HttpResponse sendRequest(oauth.signpost.http.HttpRequest request) throws Exception {
-            return new HttpResponse(((HttpRequest) request).request.connect());
-        }
-
-        @Override
-        protected void closeConnection(oauth.signpost.http.HttpRequest request, oauth.signpost.http.HttpResponse response) throws Exception {
-            if (response != null) {
-                ((HttpResponse) response).response.disconnect();
-            } else if (request != null) {
-                ((HttpRequest) request).request.disconnect();
-            }
-        }
-    }
-
-    /**
-     * OAuth consumer.
-     */
-    public static class OAuthConsumer extends AbstractOAuthConsumer {
-
-        private static final long serialVersionUID = 1L;
-
-        /**
-         * Constructs a new {@code OAuthConsumer}.
-         * @param consumerKey consumer key
-         * @param consumerSecret consumer secret
-         */
-        public OAuthConsumer(String consumerKey, String consumerSecret) {
-            super(consumerKey, consumerSecret);
-        }
-
-        @Override
-        protected HttpRequest wrap(Object request) {
-            return new HttpRequest((HttpClient) request);
-        }
-    }
-
-    static final class HttpRequest implements oauth.signpost.http.HttpRequest {
-        final HttpClient request;
-
-        HttpRequest(HttpClient request) {
-            this.request = request;
-        }
-
-        @Override
-        public void setHeader(String name, String value) {
-            request.setHeader(name, value);
-        }
-
-        @Override
-        public String getMethod() {
-            return request.getRequestMethod();
-        }
-
-        @Override
-        public String getRequestUrl() {
-            return request.getURL().toExternalForm();
-        }
-
-        @Override
-        public String getContentType() {
-            return request.getRequestHeader("Content-Type");
-        }
-
-        @Override
-        public String getHeader(String name) {
-            return request.getRequestHeader(name);
-        }
-
-        @Override
-        public InputStream getMessagePayload() {
-            return null;
-        }
-
-        @Override
-        public void setRequestUrl(String url) {
-            throw new IllegalStateException();
-        }
-
-        @Override
-        public Map<String, String> getAllHeaders() {
-            throw new IllegalStateException();
-        }
-
-        @Override
-        public Object unwrap() {
-            throw new IllegalStateException();
-        }
-    }
-
-    static final class HttpResponse implements oauth.signpost.http.HttpResponse {
-        final HttpClient.Response response;
-
-        HttpResponse(HttpClient.Response response) {
-            this.response = response;
-        }
-
-        @Override
-        public int getStatusCode() {
-            return response.getResponseCode();
-        }
-
-        @Override
-        public String getReasonPhrase() {
-            return response.getResponseMessage();
-        }
-
-        @Override
-        public InputStream getContent() throws IOException {
-            return response.getContent();
-        }
-
-        @Override
-        public Object unwrap() {
-            throw new IllegalStateException();
-        }
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/AbstractAuthorizationUI.java	(date 1707931029871)
@@ -4,8 +4,8 @@
 import java.util.Objects;
 
 import org.openstreetmap.josm.data.oauth.IOAuthParameters;
+import org.openstreetmap.josm.data.oauth.IOAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -22,26 +22,23 @@
     public static final String ACCESS_TOKEN_PROP = AbstractAuthorizationUI.class.getName() + ".accessToken";
 
     private String apiUrl;
-    private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(OAuthVersion.OAuth10a);
-    private transient OAuthToken accessToken;
-
-    /**
-     * Constructs a new {@code AbstractAuthorizationUI} without API URL.
-     * @since 10189
-     */
-    protected AbstractAuthorizationUI() {
-    }
+    private final AdvancedOAuthPropertiesPanel pnlAdvancedProperties;
+    private transient IOAuthToken accessToken;
 
     /**
      * Constructs a new {@code AbstractAuthorizationUI} for the given API URL.
-     * @param apiUrl The OSM API URL
-     * @since 5422
+     * @param apiUrl The OSM API URL (may be null)
+     * @param oAuthVersion The oauth version to use
+     * @since xxx
      */
-    protected AbstractAuthorizationUI(String apiUrl) {
-        setApiUrl(apiUrl);
+    protected AbstractAuthorizationUI(String apiUrl, OAuthVersion oAuthVersion) {
+        this.pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(oAuthVersion);
+        if (apiUrl != null) {
+            setApiUrl(apiUrl);
+        }
     }
 
-    protected void fireAccessTokenChanged(OAuthToken oldValue, OAuthToken newValue) {
+    protected void fireAccessTokenChanged(IOAuthToken oldValue, IOAuthToken newValue) {
         firePropertyChange(ACCESS_TOKEN_PROP, oldValue, newValue);
     }
 
@@ -90,7 +87,7 @@
      *
      * @return the retrieved Access Token
      */
-    public OAuthToken getAccessToken() {
+    public IOAuthToken getAccessToken() {
         return accessToken;
     }
 
@@ -100,8 +97,8 @@
      *
      * @param accessToken the new access token. null, to clear the current access token
      */
-    protected void setAccessToken(OAuthToken accessToken) {
-        OAuthToken oldValue = this.accessToken;
+    protected void setAccessToken(IOAuthToken accessToken) {
+        IOAuthToken oldValue = this.accessToken;
         this.accessToken = accessToken;
         if (oldValue == null ^ this.accessToken == null) {
             fireAccessTokenChanged(oldValue, this.accessToken);
@@ -112,6 +109,15 @@
         }
     }
 
+    /**
+     * Get the OAuth version for this AuthorizationUI
+     * @return The OAuth version
+     * @since xxx
+     */
+    public OAuthVersion getOAuthVersion() {
+        return this.pnlAdvancedProperties.getAdvancedParameters().getOAuthVersion();
+    }
+
     /**
      * Replies true if this UI currently has an Access Token
      *
Index: core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java b/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java	(date 1707931029954)
@@ -11,18 +11,19 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 
+import org.openstreetmap.josm.data.oauth.IOAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuth20Token;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
 
 /**
- * Displays the key and the secret of an OAuth Access Token.
- * @since 2746
+ * Displays the key of an OAuth Access Token.
+ * @since 2746 (modified for OAuth 2 in xxx)
  */
 public class AccessTokenInfoPanel extends JPanel {
 
     private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
-    private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
     private final JCheckBox cbSaveAccessTokenInPreferences = new JCheckBox(tr("Save Access Token in preferences"));
 
     /**
@@ -55,11 +56,7 @@
         gc.insets = new Insets(0, 0, 3, 3);
         add(new JLabel(tr("Access Token Secret:")), gc);
 
-        gc.gridx = 1;
         gc.weightx = 1.0;
-        add(tfAccessTokenSecret, gc);
-        tfAccessTokenSecret.setEditable(false);
-
         // the checkbox
         gc.gridx = 0;
         gc.gridy = 2;
@@ -86,14 +83,16 @@
      *
      * @param token the access  token. If null, the content in the info panel is cleared
      */
-    public void setAccessToken(OAuthToken token) {
+    public void setAccessToken(IOAuthToken token) {
         if (token == null) {
             tfAccessTokenKey.setText("");
-            tfAccessTokenSecret.setText("");
             return;
         }
-        tfAccessTokenKey.setText(token.getKey());
-        tfAccessTokenSecret.setText(token.getSecret());
+        if (token instanceof OAuth20Token) {
+            tfAccessTokenKey.setText(((OAuth20Token) token).getBearerToken());
+        } else {
+            throw new JosmRuntimeException("Unknown token type: " + token.getClass());
+        }
     }
 
     public void setSaveToPreferences(boolean saveToPreferences) {
Index: core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java b/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java	(date 1707931030000)
@@ -52,8 +52,6 @@
     private final JosmTextField tfRequestTokenURL = new JosmTextField();
     private final JosmTextField tfAccessTokenURL = new JosmTextField();
     private final JosmTextField tfAuthoriseURL = new JosmTextField();
-    private final JosmTextField tfOsmLoginURL = new JosmTextField();
-    private final JosmTextField tfOsmLogoutURL = new JosmTextField();
     private final OAuthVersion oauthVersion;
     private transient UseDefaultItemListener ilUseDefault;
     private String apiUrl;
@@ -83,11 +81,7 @@
         gc.gridy = 1;
         gc.weightx = 0.0;
         gc.gridwidth = 1;
-        if (this.oauthVersion == OAuthVersion.OAuth10a) {
-            add(new JLabel(tr("Consumer Key:")), gc);
-        } else {
-            add(new JLabel(tr("Client ID:")), gc);
-        }
+        add(new JLabel(tr("Client ID:")), gc);
 
         gc.gridx = 1;
         gc.weightx = 1.0;
@@ -98,11 +92,7 @@
         gc.gridy++;
         gc.gridx = 0;
         gc.weightx = 0.0;
-        if (this.oauthVersion == OAuthVersion.OAuth10a) {
-            add(new JLabel(tr("Consumer Secret:")), gc);
-        } else {
-            add(new JLabel(tr("Client Secret:")), gc);
-        }
+        add(new JLabel(tr("Client Secret:")), gc);
 
         gc.gridx = 1;
         gc.weightx = 1.0;
@@ -113,11 +103,7 @@
         gc.gridy++;
         gc.gridx = 0;
         gc.weightx = 0.0;
-        if (this.oauthVersion == OAuthVersion.OAuth10a) {
-            add(new JLabel(tr("Request Token URL:")), gc);
-        } else {
-            add(new JLabel(tr("Redirect URL:")), gc);
-        }
+        add(new JLabel(tr("Redirect URL:")), gc);
 
         gc.gridx = 1;
         gc.weightx = 1.0;
@@ -146,36 +132,12 @@
         add(tfAuthoriseURL, gc);
         SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL);
 
-        if (this.oauthVersion == OAuthVersion.OAuth10a) {
-            // -- OSM login URL
-            gc.gridy++;
-            gc.gridx = 0;
-            gc.weightx = 0.0;
-            add(new JLabel(tr("OSM login URL:")), gc);
-
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            add(tfOsmLoginURL, gc);
-            SelectAllOnFocusGainedDecorator.decorate(tfOsmLoginURL);
-
-            // -- OSM logout URL
-            gc.gridy++;
-            gc.gridx = 0;
-            gc.weightx = 0.0;
-            add(new JLabel(tr("OSM logout URL:")), gc);
-
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            add(tfOsmLogoutURL, gc);
-            SelectAllOnFocusGainedDecorator.decorate(tfOsmLogoutURL);
-        }
-
         ilUseDefault = new UseDefaultItemListener();
         cbUseDefaults.addItemListener(ilUseDefault);
     }
 
     protected boolean hasCustomSettings() {
-        OAuthParameters params = OAuthParameters.createDefault(apiUrl);
+        IOAuthParameters params = OAuthParameters.createDefault(apiUrl, OAuthVersion.OAuth20);
         return !params.equals(getAdvancedParameters());
     }
 
@@ -213,16 +175,6 @@
         cbUseDefaults.setSelected(true);
         IOAuthParameters iParams = OAuthParameters.createDefault(apiUrl, this.oauthVersion);
         switch (this.oauthVersion) {
-            case OAuth10a:
-                OAuthParameters params = (OAuthParameters) iParams;
-                tfConsumerKey.setText(params.getConsumerKey());
-                tfConsumerSecret.setText(params.getConsumerSecret());
-                tfRequestTokenURL.setText(params.getRequestTokenUrl());
-                tfAccessTokenURL.setText(params.getAccessTokenUrl());
-                tfAuthoriseURL.setText(params.getAuthoriseUrl());
-                tfOsmLoginURL.setText(params.getOsmLoginUrl());
-                tfOsmLogoutURL.setText(params.getOsmLogoutUrl());
-                break;
             case OAuth20:
             case OAuth21:
                 OAuth20Parameters params20 = (OAuth20Parameters) iParams;
@@ -231,6 +183,9 @@
                 tfAccessTokenURL.setText(params20.getAccessTokenUrl());
                 tfAuthoriseURL.setText(params20.getAuthorizationUrl());
                 tfRequestTokenURL.setText(params20.getRedirectUri());
+                break;
+            default:
+                throw new UnsupportedOperationException("Unsupported OAuth version: " + this.oauthVersion);
         }
 
         setChildComponentsEnabled(false);
@@ -252,16 +207,6 @@
     public IOAuthParameters getAdvancedParameters() {
         if (cbUseDefaults.isSelected())
             return OAuthParameters.createDefault(apiUrl, this.oauthVersion);
-        if (this.oauthVersion == OAuthVersion.OAuth10a) {
-            return new OAuthParameters(
-                    tfConsumerKey.getText(),
-                    tfConsumerSecret.getText(),
-                    tfRequestTokenURL.getText(),
-                    tfAccessTokenURL.getText(),
-                    tfAuthoriseURL.getText(),
-                    tfOsmLoginURL.getText(),
-                    tfOsmLogoutURL.getText());
-        }
         return new OAuth20Parameters(
                 tfConsumerKey.getText(),
                 tfConsumerSecret.getText(),
@@ -285,16 +230,7 @@
         } else {
             cbUseDefaults.setSelected(false);
             setChildComponentsEnabled(true);
-            if (parameters instanceof OAuthParameters) {
-                OAuthParameters parameters10 = (OAuthParameters) parameters;
-                tfConsumerKey.setText(parameters10.getConsumerKey() == null ? "" : parameters10.getConsumerKey());
-                tfConsumerSecret.setText(parameters10.getConsumerSecret() == null ? "" : parameters10.getConsumerSecret());
-                tfRequestTokenURL.setText(parameters10.getRequestTokenUrl() == null ? "" : parameters10.getRequestTokenUrl());
-                tfAccessTokenURL.setText(parameters10.getAccessTokenUrl() == null ? "" : parameters10.getAccessTokenUrl());
-                tfAuthoriseURL.setText(parameters10.getAuthoriseUrl() == null ? "" : parameters10.getAuthoriseUrl());
-                tfOsmLoginURL.setText(parameters10.getOsmLoginUrl() == null ? "" : parameters10.getOsmLoginUrl());
-                tfOsmLogoutURL.setText(parameters10.getOsmLogoutUrl() == null ? "" : parameters10.getOsmLogoutUrl());
-            } else if (parameters instanceof OAuth20Parameters) {
+            if (parameters instanceof OAuth20Parameters) {
                 OAuth20Parameters parameters20 = (OAuth20Parameters) parameters;
                 tfConsumerKey.setText(parameters20.getClientId());
                 tfConsumerSecret.setText(parameters20.getClientSecret());
@@ -319,7 +255,7 @@
         if (useDefault) {
             resetToDefaultSettings();
         } else {
-            setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl));
+            setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl, OAuthVersion.OAuth20));
         }
         ilUseDefault.setEnabled(true);
     }
@@ -330,7 +266,7 @@
     public void rememberPreferences() {
         Config.getPref().putBoolean("oauth.settings.use-default", cbUseDefaults.isSelected());
         if (cbUseDefaults.isSelected()) {
-            new OAuthParameters(null, null, null, null, null, null, null).rememberPreferences();
+            OAuthParameters.createDefault().rememberPreferences();
         } else {
             getAdvancedParameters().rememberPreferences();
         }
Index: core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUI.java	(date 1707943535815)
@@ -12,8 +12,6 @@
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.io.IOException;
-import java.net.Authenticator.RequestorType;
-import java.net.PasswordAuthentication;
 import java.util.concurrent.Executor;
 
 import javax.swing.AbstractAction;
@@ -23,47 +21,29 @@
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTabbedPane;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.JTextComponent;
 import javax.swing.text.html.HTMLEditorKit;
 
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
+import org.openstreetmap.josm.data.oauth.IOAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.preferences.server.UserNameValidator;
 import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
-import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
-import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.OsmTransferException;
-import org.openstreetmap.josm.io.auth.CredentialsAgent;
-import org.openstreetmap.josm.io.auth.CredentialsAgentException;
-import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
-import org.openstreetmap.josm.tools.Utils;
 import org.xml.sax.SAXException;
 
 /**
- * This is an UI which supports a JOSM user to get an OAuth Access Token in a fully
+ * This is a UI which supports a JOSM user to get an OAuth Access Token in a fully
  * automatic process.
  *
  * @since 2746
  */
 public class FullyAutomaticAuthorizationUI extends AbstractAuthorizationUI {
-
-    private final JosmTextField tfUserName = new JosmTextField();
-    private final JosmPasswordField tfPassword = new JosmPasswordField();
-    private transient UserNameValidator valUserName;
-    private transient PasswordValidator valPassword;
     private final AccessTokenInfoPanel pnlAccessTokenInfo = new AccessTokenInfoPanel();
     private OsmPrivilegesPanel pnlOsmPrivileges;
     private JPanel pnlPropertiesPanel;
@@ -104,7 +84,7 @@
         pnlMessage.setText("<html><body><p class=\"warning-body\">"
                 + tr("Please enter your OSM user name and password. The password will <strong>not</strong> be saved "
                         + "in clear text in the JOSM preferences and it will be submitted to the OSM server <strong>only once</strong>. "
-                        + "Subsequent data upload requests don''t use your password any more.").replaceAll("\\. ", ".<br>")
+                        + "Subsequent data upload requests don''t use your password any more.").replace(". ", ".<br>")
                         + "</p>"
                         + "</body></html>");
         pnl.add(pnlMessage, gc);
@@ -120,10 +100,6 @@
 
         gc.gridx = 1;
         gc.weightx = 1.0;
-        pnl.add(tfUserName, gc);
-        SelectAllOnFocusGainedDecorator.decorate(tfUserName);
-        valUserName = new UserNameValidator(tfUserName);
-        valUserName.validate();
 
         // the password input field
         gc.anchor = GridBagConstraints.NORTHWEST;
@@ -135,10 +111,6 @@
 
         gc.gridx = 1;
         gc.weightx = 1.0;
-        pnl.add(tfPassword, gc);
-        SelectAllOnFocusGainedDecorator.decorate(tfPassword);
-        valPassword = new PasswordValidator(tfPassword);
-        valPassword.validate();
 
         // filler - grab remaining space
         gc.gridy = 4;
@@ -166,30 +138,6 @@
         return pnl;
     }
 
-    /**
-     * Initializes the panel with values from the preferences
-     * @param paramApiUrl the API URL
-     */
-    @Override
-    public void initialize(String paramApiUrl) {
-        super.initialize(paramApiUrl);
-        CredentialsAgent cm = CredentialsManager.getInstance();
-        try {
-            PasswordAuthentication pa = cm.lookup(RequestorType.SERVER, OsmApi.getOsmApi().getHost());
-            if (pa == null) {
-                tfUserName.setText("");
-                tfPassword.setText("");
-            } else {
-                tfUserName.setText(pa.getUserName() == null ? "" : pa.getUserName());
-                tfPassword.setText(pa.getPassword() == null ? "" : String.valueOf(pa.getPassword()));
-            }
-        } catch (CredentialsAgentException e) {
-            Logging.error(e);
-            tfUserName.setText("");
-            tfPassword.setText("");
-        }
-    }
-
     /**
      * Builds the panel with the action button  for starting the authorisation
      *
@@ -199,8 +147,6 @@
         JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
 
         RunAuthorisationAction runAuthorisationAction = new RunAuthorisationAction();
-        tfPassword.getDocument().addDocumentListener(runAuthorisationAction);
-        tfUserName.getDocument().addDocumentListener(runAuthorisationAction);
         pnl.add(new JButton(runAuthorisationAction));
         return pnl;
     }
@@ -288,22 +234,27 @@
         repaint();
     }
 
-    protected String getOsmUserName() {
-        return tfUserName.getText();
-    }
-
-    protected String getOsmPassword() {
-        return String.valueOf(tfPassword.getPassword());
-    }
-
     /**
      * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL.
      * @param apiUrl The OSM API URL
      * @param executor the executor used for running the HTTP requests for the authorization
      * @since 5422
+     * @deprecated since xxx
      */
+    @Deprecated
     public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor) {
-        super(apiUrl);
+        this(apiUrl, executor, OAuthVersion.OAuth10a);
+    }
+
+    /**
+     * Constructs a new {@code FullyAutomaticAuthorizationUI} for the given API URL.
+     * @param apiUrl The OSM API URL
+     * @param executor the executor used for running the HTTP requests for the authorization
+     * @param oAuthVersion The OAuth version to use for this UI
+     * @since xxx
+     */
+    public FullyAutomaticAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) {
+        super(apiUrl, oAuthVersion);
         this.executor = executor;
         build();
     }
@@ -314,7 +265,7 @@
     }
 
     @Override
-    protected void setAccessToken(OAuthToken accessToken) {
+    protected void setAccessToken(IOAuthToken accessToken) {
         super.setAccessToken(accessToken);
         pnlAccessTokenInfo.setAccessToken(accessToken);
     }
@@ -322,37 +273,17 @@
     /**
      * Starts the authorisation process
      */
-    class RunAuthorisationAction extends AbstractAction implements DocumentListener {
+    class RunAuthorisationAction extends AbstractAction {
         RunAuthorisationAction() {
             putValue(NAME, tr("Authorize now"));
             new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
             putValue(SHORT_DESCRIPTION, tr("Click to redirect you to the authorization form on the JOSM web site"));
-            updateEnabledState();
         }
 
         @Override
         public void actionPerformed(ActionEvent evt) {
             executor.execute(new FullyAutomaticAuthorisationTask(FullyAutomaticAuthorizationUI.this));
         }
-
-        protected final void updateEnabledState() {
-            setEnabled(valPassword.isValid() && valUserName.isValid());
-        }
-
-        @Override
-        public void changedUpdate(DocumentEvent e) {
-            updateEnabledState();
-        }
-
-        @Override
-        public void insertUpdate(DocumentEvent e) {
-            updateEnabledState();
-        }
-
-        @Override
-        public void removeUpdate(DocumentEvent e) {
-            updateEnabledState();
-        }
     }
 
     /**
@@ -385,18 +316,11 @@
             executor.execute(new TestAccessTokenTask(
                     FullyAutomaticAuthorizationUI.this,
                     getApiUrl(),
-                    (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
                     getAccessToken()
             ));
         }
     }
 
-    static class PasswordValidator extends DefaultTextComponentValidator {
-        PasswordValidator(JTextComponent tc) {
-            super(tc, tr("Please enter your OSM password"), tr("The password cannot be empty. Please enter your OSM password"));
-        }
-    }
-
     class FullyAutomaticAuthorisationTask extends PleaseWaitRunnable {
         private boolean canceled;
 
@@ -438,25 +362,7 @@
                             + "a valid login URL from the OAuth Authorize Endpoint URL ''{0}''.<br><br>"
                             + "Please check your advanced setting and try again."
                             + "</html>",
-                            ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getAuthoriseUrl()),
-                    tr("OAuth authorization failed"),
-                    JOptionPane.ERROR_MESSAGE,
-                    HelpUtil.ht("/Dialog/OAuthAuthorisationWizard#FullyAutomaticProcessFailed")
-            );
-        }
-
-        protected void alertLoginFailed() {
-            final String loginUrl = ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getOsmLoginUrl();
-            HelpAwareOptionPane.showOptionDialog(
-                    FullyAutomaticAuthorizationUI.this,
-                    tr("<html>"
-                            + "The automatic process for retrieving an OAuth Access Token<br>"
-                            + "from the OSM server failed. JOSM failed to log into {0}<br>"
-                            + "for user {1}.<br><br>"
-                            + "Please check username and password and try again."
-                            +"</html>",
-                            loginUrl,
-                            Utils.escapeReservedCharactersHTML(getOsmUserName())),
+                            getAdvancedPropertiesPanel().getAdvancedParameters().getAuthorizationUrl()),
                     tr("OAuth authorization failed"),
                     JOptionPane.ERROR_MESSAGE,
                     HelpUtil.ht("/Dialog/OAuthAuthorisationWizard#FullyAutomaticProcessFailed")
@@ -464,50 +370,23 @@
         }
 
         protected void handleException(final OsmOAuthAuthorizationException e) {
-            Runnable r = () -> {
-                if (e instanceof OsmLoginFailedException) {
-                    alertLoginFailed();
-                } else {
-                    alertAuthorisationFailed();
-                }
-            };
             Logging.error(e);
-            GuiHelper.runInEDT(r);
+            GuiHelper.runInEDT(this::alertAuthorisationFailed);
         }
 
         @Override
         protected void realRun() throws SAXException, IOException, OsmTransferException {
-            try {
-                getProgressMonitor().setTicksCount(3);
-                OsmOAuthAuthorizationClient authClient = new OsmOAuthAuthorizationClient(
-                        (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()
-                );
-                OAuthToken requestToken = authClient.getRequestToken(
-                        getProgressMonitor().createSubTaskMonitor(1, false)
-                );
-                getProgressMonitor().worked(1);
-                if (canceled) return;
-                authClient.authorise(
-                        requestToken,
-                        getOsmUserName(),
-                        getOsmPassword(),
-                        pnlOsmPrivileges.getPrivileges(),
-                        getProgressMonitor().createSubTaskMonitor(1, false)
-                );
-                getProgressMonitor().worked(1);
-                if (canceled) return;
-                final OAuthToken accessToken = authClient.getAccessToken(
-                        getProgressMonitor().createSubTaskMonitor(1, false)
-                );
-                getProgressMonitor().worked(1);
-                if (canceled) return;
-                GuiHelper.runInEDT(() -> {
-                    prepareUIForResultDisplay();
-                    setAccessToken(accessToken);
-                });
-            } catch (final OsmOAuthAuthorizationException e) {
-                handleException(e);
-            }
+            getProgressMonitor().setTicksCount(2);
+            OAuthAuthorizationWizard.authorize(true, token -> {
+                if (!canceled) {
+                    getProgressMonitor().worked(1);
+                    GuiHelper.runInEDT(() -> {
+                        prepareUIForResultDisplay();
+                        setAccessToken(token.orElse(null));
+                    });
+                }
+            }, getApiUrl(), getOAuthVersion());
+            getProgressMonitor().worked(1);
         }
     }
 }
Index: core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUI.java	(date 1707936412856)
@@ -24,14 +24,16 @@
 import javax.swing.event.DocumentListener;
 import javax.swing.text.JTextComponent;
 
+import org.openstreetmap.josm.data.oauth.OAuth20Exception;
+import org.openstreetmap.josm.data.oauth.OAuth20Token;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.widgets.DefaultTextComponentValidator;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
 
 /**
  * This is an UI which supports a JOSM user to get an OAuth Access Token in a fully manual process.
@@ -42,8 +44,6 @@
 
     private final JosmTextField tfAccessTokenKey = new JosmTextField();
     private transient AccessTokenKeyValidator valAccessTokenKey;
-    private final JosmTextField tfAccessTokenSecret = new JosmTextField();
-    private transient AccessTokenSecretValidator valAccessTokenSecret;
     private final JCheckBox cbSaveToPreferences = new JCheckBox(tr("Save Access Token in preferences"));
     private final HtmlPanel pnlMessage = new HtmlPanel();
     private final transient Executor executor;
@@ -53,9 +53,24 @@
      * @param apiUrl The OSM API URL
      * @param executor the executor used for running the HTTP requests for the authorization
      * @since 5422
+     * @deprecated since xxx, use {@link ManualAuthorizationUI#ManualAuthorizationUI(String, Executor, OAuthVersion)}
+     * instead.
      */
+    @Deprecated
     public ManualAuthorizationUI(String apiUrl, Executor executor) {
-        super(/* dont pass apiURL because setApiUrl is overridden and references a local field */);
+        this(apiUrl, executor, OAuthVersion.OAuth10a);
+    }
+
+    /**
+     * Constructs a new {@code ManualAuthorizationUI} for the given API URL.
+     * @param apiUrl The OSM API URL
+     * @param executor the executor used for running the HTTP requests for the authorization
+     * @param oAuthVersion The OAuthVersion to use for this UI
+     * @since xxx
+     */
+    public ManualAuthorizationUI(String apiUrl, Executor executor, OAuthVersion oAuthVersion) {
+        super(null /* don't pass apiURL because setApiUrl is overridden and references a local field */,
+                oAuthVersion);
         setApiUrl(apiUrl);
         this.executor = executor;
         build();
@@ -94,20 +109,6 @@
         valAccessTokenKey.validate();
         tfAccessTokenKey.getDocument().addDocumentListener(accessTokenBuilder);
 
-        // the access token key input field
-        gc.gridy = 2;
-        gc.gridx = 0;
-        gc.weightx = 0.0;
-        pnl.add(new JLabel(tr("Access Token Secret:")), gc);
-
-        gc.gridx = 1;
-        gc.weightx = 1.0;
-        pnl.add(tfAccessTokenSecret, gc);
-        SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenSecret);
-        valAccessTokenSecret = new AccessTokenSecretValidator(tfAccessTokenSecret);
-        valAccessTokenSecret.validate();
-        tfAccessTokenSecret.getDocument().addDocumentListener(accessTokenBuilder);
-
         // the checkbox for saving to preferences
         gc.gridy = 3;
         gc.gridx = 0;
@@ -184,20 +185,18 @@
         }
     }
 
-    private static class AccessTokenSecretValidator extends DefaultTextComponentValidator {
-        AccessTokenSecretValidator(JTextComponent tc) {
-            super(tc, tr("Please enter an Access Token Secret"),
-                      tr("The Access Token Secret must not be empty. Please enter an Access Token Secret"));
-        }
-    }
-
     class AccessTokenBuilder implements DocumentListener {
 
         public void build() {
-            if (!valAccessTokenKey.isValid() || !valAccessTokenSecret.isValid()) {
+            if (!valAccessTokenKey.isValid()) {
                 setAccessToken(null);
             } else {
-                setAccessToken(new OAuthToken(tfAccessTokenKey.getText().trim(), tfAccessTokenSecret.getText().trim()));
+                try {
+                    setAccessToken(new OAuth20Token(getOAuthParameters(), "{\"token_type\":\"bearer\", \"access_token\""
+                            + tfAccessTokenKey.getText().trim() + "\"}"));
+                } catch (OAuth20Exception e) {
+                    throw new JosmRuntimeException(e);
+                }
             }
         }
 
@@ -233,7 +232,6 @@
             TestAccessTokenTask task = new TestAccessTokenTask(
                     ManualAuthorizationUI.this,
                     getApiUrl(),
-                    (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
                     getAccessToken()
             );
             executor.execute(task);
Index: core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java b/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java	(date 1707943795390)
@@ -19,22 +19,29 @@
 import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.Executor;
 import java.util.concurrent.FutureTask;
+import java.util.function.Consumer;
 
 import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JDialog;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.text.html.HTMLEditorKit;
 
+import org.openstreetmap.josm.data.oauth.IOAuthParameters;
+import org.openstreetmap.josm.data.oauth.IOAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuth20Authorization;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuthVersion;
+import org.openstreetmap.josm.data.oauth.osm.OsmScopes;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
 import org.openstreetmap.josm.gui.help.HelpUtil;
@@ -42,6 +49,8 @@
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
+import org.openstreetmap.josm.io.auth.CredentialsManager;
+import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -58,28 +67,67 @@
     private boolean canceled;
     private final AuthorizationProcedure procedure;
     private final String apiUrl;
+    private final OAuthVersion oAuthVersion;
 
     private FullyAutomaticAuthorizationUI pnlFullyAutomaticAuthorisationUI;
-    private SemiAutomaticAuthorizationUI pnlSemiAutomaticAuthorisationUI;
     private ManualAuthorizationUI pnlManualAuthorisationUI;
     private JScrollPane spAuthorisationProcedureUI;
     private final transient Executor executor;
 
     /**
-     * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken(OAuthToken) sets the token}
+     * Launches the wizard, {@link OAuthAccessTokenHolder#setAccessToken(String, IOAuthToken)} sets the token
      * and {@link OAuthAccessTokenHolder#setSaveToPreferences(boolean) saves to preferences}.
+     * @param callback Callback to run when authorization is finished
      * @throws UserCancelException if user cancels the operation
      */
-    public void showDialog() throws UserCancelException {
-        setVisible(true);
-        if (isCanceled()) {
-            throw new UserCancelException();
+    public void showDialog(Consumer<Optional<IOAuthToken>> callback) throws UserCancelException {
+        if ((this.oAuthVersion == OAuthVersion.OAuth20 || this.oAuthVersion == OAuthVersion.OAuth21)
+        && this.procedure == AuthorizationProcedure.FULLY_AUTOMATIC) {
+            authorize(true, callback, this.apiUrl, this.oAuthVersion);
+        } else {
+            setVisible(true);
+            if (isCanceled()) {
+                throw new UserCancelException();
+            }
         }
         OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
-        holder.setAccessToken(getAccessToken());
+        holder.setAccessToken(apiUrl, getAccessToken());
         holder.setSaveToPreferences(isSaveAccessTokenToPreferences());
     }
 
+    /**
+     * Perform the oauth dance
+     * @param startRemoteControl {@code true} to start remote control if it is not already running
+     * @param callback The callback to use to notify that the OAuth dance succeeded
+     * @param apiUrl The API URL to get the token for
+     * @param oAuthVersion The OAuth version that the authorization dance is force
+     */
+    static void authorize(boolean startRemoteControl, Consumer<Optional<IOAuthToken>> callback, String apiUrl, OAuthVersion oAuthVersion) {
+        final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get());
+        // TODO: Ask user if they want to start remote control?
+        if (!remoteControlIsRunning && startRemoteControl) {
+            RemoteControl.start();
+        }
+        new OAuth20Authorization().authorize(OAuthParameters.createDefault(apiUrl, oAuthVersion), token -> {
+                    if (!remoteControlIsRunning) {
+                        RemoteControl.stop();
+                    }
+                    OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, token.orElse(null));
+                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
+                    if (!token.isPresent()) {
+                        GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(),
+                                tr("Authentication failed, please check browser for details."),
+                                tr("OAuth Authentication Failed"),
+                                JOptionPane.ERROR_MESSAGE));
+                    }
+                    if (callback != null) {
+                        callback.accept(token);
+                    }
+                }, OsmScopes.read_gpx, OsmScopes.write_gpx,
+                OsmScopes.read_prefs, OsmScopes.write_prefs,
+                OsmScopes.write_api, OsmScopes.write_notes);
+    }
+
     /**
      * Builds the row with the action buttons
      *
@@ -90,7 +138,6 @@
 
         AcceptAccessTokenAction actAcceptAccessToken = new AcceptAccessTokenAction();
         pnlFullyAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
-        pnlSemiAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
         pnlManualAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
 
         pnl.add(new JButton(actAcceptAccessToken));
@@ -153,14 +200,12 @@
             spAuthorisationProcedureUI.getViewport().setView(pnlFullyAutomaticAuthorisationUI);
             pnlFullyAutomaticAuthorisationUI.revalidate();
             break;
-        case SEMI_AUTOMATIC:
-            spAuthorisationProcedureUI.getViewport().setView(pnlSemiAutomaticAuthorisationUI);
-            pnlSemiAutomaticAuthorisationUI.revalidate();
-            break;
         case MANUALLY:
             spAuthorisationProcedureUI.getViewport().setView(pnlManualAuthorisationUI);
             pnlManualAuthorisationUI.revalidate();
             break;
+        default:
+            throw new UnsupportedOperationException("Unsupported auth type: " + procedure);
         }
         validate();
         repaint();
@@ -176,9 +221,8 @@
         setTitle(tr("Get an Access Token for ''{0}''", apiUrl));
         this.setMinimumSize(new Dimension(500, 300));
 
-        pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor);
-        pnlSemiAutomaticAuthorisationUI = new SemiAutomaticAuthorizationUI(apiUrl, executor);
-        pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor);
+        pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl, executor, oAuthVersion);
+        pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl, executor, oAuthVersion);
 
         spAuthorisationProcedureUI = GuiHelper.embedInVerticalScrollPane(new JPanel());
         spAuthorisationProcedureUI.getVerticalScrollBar().addComponentListener(
@@ -212,13 +256,16 @@
      * @param procedure the authorization procedure to use
      * @param apiUrl the API URL. Must not be null.
      * @param executor the executor used for running the HTTP requests for the authorization
+     * @param oAuthVersion The OAuth version this wizard is for
      * @throws IllegalArgumentException if apiUrl is null
      */
-    public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl, Executor executor) {
+    public OAuthAuthorizationWizard(Component parent, AuthorizationProcedure procedure, String apiUrl,
+                                    Executor executor, OAuthVersion oAuthVersion) {
         super(GuiHelper.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
         this.procedure = Objects.requireNonNull(procedure, "procedure");
         this.apiUrl = Objects.requireNonNull(apiUrl, "apiUrl");
         this.executor = executor;
+        this.oAuthVersion = oAuthVersion;
         build();
     }
 
@@ -235,7 +282,6 @@
         switch(procedure) {
         case FULLY_AUTOMATIC: return pnlFullyAutomaticAuthorisationUI;
         case MANUALLY: return pnlManualAuthorisationUI;
-        case SEMI_AUTOMATIC: return pnlSemiAutomaticAuthorisationUI;
         default: return null;
         }
     }
@@ -245,7 +291,7 @@
      *
      * @return the access token. May be null if the wizard was canceled.
      */
-    public OAuthToken getAccessToken() {
+    public IOAuthToken getAccessToken() {
         return getCurrentAuthorisationUI().getAccessToken();
     }
 
@@ -254,8 +300,8 @@
      *
      * @return the current OAuth parameters.
      */
-    public OAuthParameters getOAuthParameters() {
-        return (OAuthParameters) getCurrentAuthorisationUI().getOAuthParameters();
+    public IOAuthParameters getOAuthParameters() {
+        return getCurrentAuthorisationUI().getOAuthParameters();
     }
 
     /**
@@ -275,7 +321,6 @@
      */
     public void initFromPreferences() {
         pnlFullyAutomaticAuthorisationUI.initialize(apiUrl);
-        pnlSemiAutomaticAuthorisationUI.initialize(apiUrl);
         pnlManualAuthorisationUI.initialize(apiUrl);
     }
 
@@ -315,8 +360,9 @@
             final OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
                     MainApplication.getMainFrame(),
                     AuthorizationProcedure.FULLY_AUTOMATIC,
-                    serverUrl.toExternalForm(), Utils.newDirectExecutor());
-            wizard.showDialog();
+                    serverUrl.toString(), Utils.newDirectExecutor(),
+                    OAuthVersion.OAuth20);
+            wizard.showDialog(null);
             return wizard;
         });
         // exception handling differs from implementation at GuiHelper.runInEDTAndWait()
@@ -367,7 +413,12 @@
             setVisible(false);
         }
 
-        public final void updateEnabledState(OAuthToken token) {
+        /**
+         * Update the enabled state
+         * @param token The token to use
+         * @since xxx
+         */
+        public final void updateEnabledState(IOAuthToken token) {
             setEnabled(token != null);
         }
 
@@ -375,7 +426,7 @@
         public void propertyChange(PropertyChangeEvent evt) {
             if (!evt.getPropertyName().equals(AbstractAuthorizationUI.ACCESS_TOKEN_PROP))
                 return;
-            updateEnabledState((OAuthToken) evt.getNewValue());
+            updateEnabledState((IOAuthToken) evt.getNewValue());
         }
     }
 
Index: core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java b/core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/gui/oauth/OsmLoginFailedException.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,17 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-/**
- * OSM login failure exception.
- * @since 2746
- */
-public class OsmLoginFailedException extends OsmOAuthAuthorizationException {
-
-    /**
-     * Constructs a new {@code OsmLoginFailedException} with the specified cause.
-     * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method).
-     */
-    public OsmLoginFailedException(Throwable cause) {
-        super(cause);
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java b/core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,457 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.net.CookieHandler;
-import java.net.HttpURLConnection;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.data.oauth.OsmPrivileges;
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
-import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.io.OsmTransferCanceledException;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.HttpClient;
-import org.openstreetmap.josm.tools.Logging;
-import org.openstreetmap.josm.tools.Utils;
-
-import oauth.signpost.OAuth;
-import oauth.signpost.OAuthConsumer;
-import oauth.signpost.OAuthProvider;
-import oauth.signpost.exception.OAuthException;
-
-/**
- * An OAuth 1.0 authorization client.
- * @since 2746
- */
-public class OsmOAuthAuthorizationClient {
-    private final OAuthParameters oauthProviderParameters;
-    private final OAuthConsumer consumer;
-    private final OAuthProvider provider;
-    private boolean canceled;
-    private HttpClient connection;
-
-    protected static class SessionId {
-        protected String id;
-        protected String token;
-        protected String userName;
-    }
-
-    /**
-     * Creates a new authorisation client with the parameters <code>parameters</code>.
-     *
-     * @param parameters the OAuth parameters. Must not be null.
-     * @throws IllegalArgumentException if parameters is null
-     */
-    public OsmOAuthAuthorizationClient(OAuthParameters parameters) {
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
-        oauthProviderParameters = new OAuthParameters(parameters);
-        consumer = oauthProviderParameters.buildConsumer();
-        provider = oauthProviderParameters.buildProvider(consumer);
-    }
-
-    /**
-     * Creates a new authorisation client with the parameters <code>parameters</code>
-     * and an already known Request Token.
-     *
-     * @param parameters the OAuth parameters. Must not be null.
-     * @param requestToken the request token. Must not be null.
-     * @throws IllegalArgumentException if parameters is null
-     * @throws IllegalArgumentException if requestToken is null
-     */
-    public OsmOAuthAuthorizationClient(OAuthParameters parameters, OAuthToken requestToken) {
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
-        oauthProviderParameters = new OAuthParameters(parameters);
-        consumer = oauthProviderParameters.buildConsumer();
-        provider = oauthProviderParameters.buildProvider(consumer);
-        consumer.setTokenWithSecret(requestToken.getKey(), requestToken.getSecret());
-    }
-
-    /**
-     * Cancels the current OAuth operation.
-     */
-    public void cancel() {
-        canceled = true;
-        synchronized (this) {
-            if (connection != null) {
-                connection.disconnect();
-            }
-        }
-    }
-
-    /**
-     * Submits a request for a Request Token to the Request Token Endpoint Url of the OAuth Service
-     * Provider and replies the request token.
-     *
-     * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
-     * @return the OAuth Request Token
-     * @throws OsmOAuthAuthorizationException if something goes wrong when retrieving the request token
-     * @throws OsmTransferCanceledException if the user canceled the request
-     */
-    public OAuthToken getRequestToken(ProgressMonitor monitor) throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
-        if (monitor == null) {
-            monitor = NullProgressMonitor.INSTANCE;
-        }
-        try {
-            monitor.beginTask("");
-            monitor.indeterminateSubTask(tr("Retrieving OAuth Request Token from ''{0}''", oauthProviderParameters.getRequestTokenUrl()));
-            provider.retrieveRequestToken(consumer, "");
-            return OAuthToken.createToken(consumer);
-        } catch (OAuthException e) {
-            if (canceled)
-                throw new OsmTransferCanceledException(e);
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            monitor.finishTask();
-        }
-    }
-
-    /**
-     * Submits a request for an Access Token to the Access Token Endpoint Url of the OAuth Service
-     * Provider and replies the request token.
-     *
-     * You must have requested a Request Token using {@link #getRequestToken(ProgressMonitor)} first.
-     *
-     * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
-     * @return the OAuth Access Token
-     * @throws OsmOAuthAuthorizationException if something goes wrong when retrieving the request token
-     * @throws OsmTransferCanceledException if the user canceled the request
-     * @see #getRequestToken(ProgressMonitor)
-     */
-    public OAuthToken getAccessToken(ProgressMonitor monitor) throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
-        if (monitor == null) {
-            monitor = NullProgressMonitor.INSTANCE;
-        }
-        try {
-            monitor.beginTask("");
-            monitor.indeterminateSubTask(tr("Retrieving OAuth Access Token from ''{0}''", oauthProviderParameters.getAccessTokenUrl()));
-            provider.retrieveAccessToken(consumer, null);
-            return OAuthToken.createToken(consumer);
-        } catch (OAuthException e) {
-            if (canceled)
-                throw new OsmTransferCanceledException(e);
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            monitor.finishTask();
-        }
-    }
-
-    /**
-     * Builds the authorise URL for a given Request Token. Users can be redirected to this URL.
-     * There they can login to OSM and authorise the request.
-     *
-     * @param requestToken  the request token
-     * @return  the authorise URL for this request
-     */
-    public String getAuthoriseUrl(OAuthToken requestToken) {
-        StringBuilder sb = new StringBuilder(32);
-
-        // OSM is an OAuth 1.0 provider and JOSM isn't a web app. We just add the oauth request token to
-        // the authorisation request, no callback parameter.
-        //
-        sb.append(oauthProviderParameters.getAuthoriseUrl()).append('?'+OAuth.OAUTH_TOKEN+'=').append(requestToken.getKey());
-        return sb.toString();
-    }
-
-    protected String extractToken() {
-        try (BufferedReader r = connection.getResponse().getContentReader()) {
-            String c;
-            Pattern p = Pattern.compile(".*authenticity_token.*value=\"([^\"]+)\".*");
-            while ((c = r.readLine()) != null) {
-                Matcher m = p.matcher(c);
-                if (m.find()) {
-                    return m.group(1);
-                }
-            }
-        } catch (IOException e) {
-            Logging.error(e);
-            return null;
-        }
-        Logging.warn("No authenticity_token found in response!");
-        return null;
-    }
-
-    protected SessionId extractOsmSession() throws IOException, URISyntaxException {
-        // response headers might not contain the cookie, see #12584
-        final List<String> setCookies = CookieHandler.getDefault()
-                .get(connection.getURL().toURI(), Collections.<String, List<String>>emptyMap())
-                .get("Cookie");
-        if (setCookies == null) {
-            Logging.warn("No 'Set-Cookie' in response header!");
-            return null;
-        }
-
-        for (String setCookie: setCookies) {
-            String[] kvPairs = setCookie.split(";", -1);
-            for (String kvPair : kvPairs) {
-                kvPair = kvPair.trim();
-                String[] kv = kvPair.split("=", -1);
-                if (kv.length != 2) {
-                    continue;
-                }
-                if ("_osm_session".equals(kv[0])) {
-                    // osm session cookie found
-                    String token = extractToken();
-                    if (token == null)
-                        return null;
-                    SessionId si = new SessionId();
-                    si.id = kv[1];
-                    si.token = token;
-                    return si;
-                }
-            }
-        }
-        Logging.warn("No suitable 'Set-Cookie' in response header found! {0}", setCookies);
-        return null;
-    }
-
-    protected static String buildPostRequest(Map<String, String> parameters) {
-        StringBuilder sb = new StringBuilder(32);
-
-        for (Iterator<Entry<String, String>> it = parameters.entrySet().iterator(); it.hasNext();) {
-            Entry<String, String> entry = it.next();
-            String value = entry.getValue();
-            value = (value == null) ? "" : value;
-            sb.append(entry.getKey()).append('=').append(Utils.encodeUrl(value));
-            if (it.hasNext()) {
-                sb.append('&');
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Submits a request to the OSM website for a login form. The OSM website replies a session ID in
-     * a cookie.
-     *
-     * @return the session ID structure
-     * @throws OsmOAuthAuthorizationException if something went wrong
-     */
-    protected SessionId fetchOsmWebsiteSessionId() throws OsmOAuthAuthorizationException {
-        try {
-            final URL url = new URL(oauthProviderParameters.getOsmLoginUrl() + "?cookie_test=true");
-            synchronized (this) {
-                connection = HttpClient.create(url).useCache(false);
-                connection.connect();
-            }
-            SessionId sessionId = extractOsmSession();
-            if (sessionId == null)
-                throw new OsmOAuthAuthorizationException(
-                        tr("OSM website did not return a session cookie in response to ''{0}'',", url.toString()));
-            return sessionId;
-        } catch (IOException | URISyntaxException e) {
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            synchronized (this) {
-                connection = null;
-            }
-        }
-    }
-
-    /**
-     * Submits a request to the OSM website for a OAuth form. The OSM website replies a session token in
-     * a hidden parameter.
-     * @param sessionId session id
-     * @param requestToken request token
-     *
-     * @throws OsmOAuthAuthorizationException if something went wrong
-     */
-    protected void fetchOAuthToken(SessionId sessionId, OAuthToken requestToken) throws OsmOAuthAuthorizationException {
-        try {
-            URL url = new URL(getAuthoriseUrl(requestToken));
-            synchronized (this) {
-                connection = HttpClient.create(url)
-                        .useCache(false)
-                        .setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName);
-                connection.connect();
-            }
-            sessionId.token = extractToken();
-            if (sessionId.token == null)
-                throw new OsmOAuthAuthorizationException(tr("OSM website did not return a session cookie in response to ''{0}'',",
-                        url.toString()));
-        } catch (IOException e) {
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            synchronized (this) {
-                connection = null;
-            }
-        }
-    }
-
-    protected void authenticateOsmSession(SessionId sessionId, String userName, String password) throws OsmLoginFailedException {
-        try {
-            final URL url = new URL(oauthProviderParameters.getOsmLoginUrl());
-            final HttpClient client = HttpClient.create(url, "POST").useCache(false);
-
-            Map<String, String> parameters = new HashMap<>();
-            parameters.put("username", userName);
-            parameters.put("password", password);
-            parameters.put("referer", "/");
-            parameters.put("commit", "Login");
-            parameters.put("authenticity_token", sessionId.token);
-            client.setRequestBody(buildPostRequest(parameters).getBytes(StandardCharsets.UTF_8));
-
-            client.setHeader("Content-Type", "application/x-www-form-urlencoded");
-            client.setHeader("Cookie", "_osm_session=" + sessionId.id);
-            // make sure we can catch 302 Moved Temporarily below
-            client.setMaxRedirects(-1);
-
-            synchronized (this) {
-                connection = client;
-                connection.connect();
-            }
-
-            // after a successful login the OSM website sends a redirect to a follow up page. Everything
-            // else, including a 200 OK, is a failed login. A 200 OK is replied if the login form with
-            // an error page is sent to back to the user.
-            //
-            int retCode = connection.getResponse().getResponseCode();
-            if (retCode != HttpURLConnection.HTTP_MOVED_TEMP)
-                throw new OsmOAuthAuthorizationException(tr("Failed to authenticate user ''{0}'' with password ''***'' as OAuth user",
-                        userName));
-        } catch (OsmOAuthAuthorizationException | IOException e) {
-            throw new OsmLoginFailedException(e);
-        } finally {
-            synchronized (this) {
-                connection = null;
-            }
-        }
-    }
-
-    protected void logoutOsmSession(SessionId sessionId) throws OsmOAuthAuthorizationException {
-        try {
-            URL url = new URL(oauthProviderParameters.getOsmLogoutUrl());
-            synchronized (this) {
-                connection = HttpClient.create(url).setMaxRedirects(-1);
-                connection.connect();
-            }
-        } catch (IOException e) {
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            synchronized (this) {
-                connection = null;
-            }
-        }
-    }
-
-    protected void sendAuthorisationRequest(SessionId sessionId, OAuthToken requestToken, OsmPrivileges privileges)
-            throws OsmOAuthAuthorizationException {
-        Map<String, String> parameters = new HashMap<>();
-        fetchOAuthToken(sessionId, requestToken);
-        parameters.put("oauth_token", requestToken.getKey());
-        parameters.put("oauth_callback", "");
-        parameters.put("authenticity_token", sessionId.token);
-        parameters.put("allow_write_api", booleanParam(privileges.isAllowWriteApi()));
-        parameters.put("allow_write_gpx", booleanParam(privileges.isAllowWriteGpx()));
-        parameters.put("allow_read_gpx", booleanParam(privileges.isAllowReadGpx()));
-        parameters.put("allow_write_prefs", booleanParam(privileges.isAllowWritePrefs()));
-        parameters.put("allow_read_prefs", booleanParam(privileges.isAllowReadPrefs()));
-        parameters.put("allow_write_notes", booleanParam(privileges.isAllowModifyNotes()));
-        parameters.put("allow_write_diary", booleanParam(privileges.isAllowWriteDiary()));
-
-        String request = buildPostRequest(parameters);
-        try {
-            URL url = new URL(oauthProviderParameters.getAuthoriseUrl());
-            final HttpClient client = HttpClient.create(url, "POST").useCache(false);
-            client.setHeader("Content-Type", "application/x-www-form-urlencoded");
-            client.setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName);
-            client.setMaxRedirects(-1);
-            client.setRequestBody(request.getBytes(StandardCharsets.UTF_8));
-
-            synchronized (this) {
-                connection = client;
-                connection.connect();
-            }
-
-            int retCode = connection.getResponse().getResponseCode();
-            if (retCode != HttpURLConnection.HTTP_OK)
-                throw new OsmOAuthAuthorizationException(tr("Failed to authorize OAuth request  ''{0}''", requestToken.getKey()));
-        } catch (IOException e) {
-            throw new OsmOAuthAuthorizationException(e);
-        } finally {
-            synchronized (this) {
-                connection = null;
-            }
-        }
-    }
-
-    private static String booleanParam(boolean param) {
-        return param ? "1" : "0";
-    }
-
-    /**
-     * Automatically authorises a request token for a set of privileges.
-     *
-     * @param requestToken the request token. Must not be null.
-     * @param userName the OSM user name. Must not be null.
-     * @param password the OSM password. Must not be null.
-     * @param privileges the set of privileges. Must not be null.
-     * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
-     * @throws IllegalArgumentException if requestToken is null
-     * @throws IllegalArgumentException if osmUserName is null
-     * @throws IllegalArgumentException if osmPassword is null
-     * @throws IllegalArgumentException if privileges is null
-     * @throws OsmOAuthAuthorizationException if the authorisation fails
-     * @throws OsmTransferCanceledException if the task is canceled by the user
-     */
-    public void authorise(OAuthToken requestToken, String userName, String password, OsmPrivileges privileges, ProgressMonitor monitor)
-            throws OsmOAuthAuthorizationException, OsmTransferCanceledException {
-        CheckParameterUtil.ensureParameterNotNull(requestToken, "requestToken");
-        CheckParameterUtil.ensureParameterNotNull(userName, "userName");
-        CheckParameterUtil.ensureParameterNotNull(password, "password");
-        CheckParameterUtil.ensureParameterNotNull(privileges, "privileges");
-
-        if (monitor == null) {
-            monitor = NullProgressMonitor.INSTANCE;
-        }
-        try {
-            monitor.beginTask(tr("Authorizing OAuth Request token ''{0}'' at the OSM website ...", requestToken.getKey()));
-            monitor.setTicksCount(4);
-            monitor.indeterminateSubTask(tr("Initializing a session at the OSM website..."));
-            SessionId sessionId = fetchOsmWebsiteSessionId();
-            sessionId.userName = userName;
-            if (canceled)
-                throw new OsmTransferCanceledException("Authorization canceled");
-            monitor.worked(1);
-
-            monitor.indeterminateSubTask(tr("Authenticating the session for user ''{0}''...", userName));
-            authenticateOsmSession(sessionId, userName, password);
-            if (canceled)
-                throw new OsmTransferCanceledException("Authorization canceled");
-            monitor.worked(1);
-
-            monitor.indeterminateSubTask(tr("Authorizing request token ''{0}''...", requestToken.getKey()));
-            sendAuthorisationRequest(sessionId, requestToken, privileges);
-            if (canceled)
-                throw new OsmTransferCanceledException("Authorization canceled");
-            monitor.worked(1);
-
-            monitor.indeterminateSubTask(tr("Logging out session ''{0}''...", sessionId));
-            logoutOsmSession(sessionId);
-            if (canceled)
-                throw new OsmTransferCanceledException("Authorization canceled");
-            monitor.worked(1);
-        } catch (OsmOAuthAuthorizationException e) {
-            if (canceled)
-                throw new OsmTransferCanceledException(e);
-            throw e;
-        } finally {
-            monitor.finishTask();
-        }
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveAccessTokenTask.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,118 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Component;
-import java.io.IOException;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.gui.HelpAwareOptionPane;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.io.OsmTransferCanceledException;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Logging;
-import org.xml.sax.SAXException;
-
-/**
- * Asynchronous task for retrieving an Access Token.
- *
- */
-public class RetrieveAccessTokenTask extends PleaseWaitRunnable {
-
-    private boolean canceled;
-    private OAuthToken accessToken;
-    private final OAuthParameters parameters;
-    private OsmOAuthAuthorizationClient client;
-    private final OAuthToken requestToken;
-    private final Component parent;
-
-    /**
-     * Creates the task
-     *
-     * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog
-     * is displayed
-     * @param parameters the OAuth parameters. Must not be null.
-     * @param requestToken the request token for which an Access Token is retrieved. Must not be null.
-     * @throws IllegalArgumentException if parameters is null.
-     * @throws IllegalArgumentException if requestToken is null.
-     */
-    public RetrieveAccessTokenTask(Component parent, OAuthParameters parameters, OAuthToken requestToken) {
-        super(parent, tr("Retrieving OAuth Access Token..."), false /* don't ignore exceptions */);
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
-        CheckParameterUtil.ensureParameterNotNull(requestToken, "requestToken");
-        this.parameters = parameters;
-        this.requestToken = requestToken;
-        this.parent = parent;
-    }
-
-    @Override
-    protected void cancel() {
-        canceled = true;
-        synchronized (this) {
-            if (client != null) {
-                client.cancel();
-            }
-        }
-    }
-
-    @Override
-    protected void finish() { /* not used in this task */}
-
-    protected void alertRetrievingAccessTokenFailed() {
-        HelpAwareOptionPane.showOptionDialog(
-                parent,
-                tr(
-                        "<html>Retrieving an OAuth Access Token from ''{0}'' failed.</html>",
-                        parameters.getAccessTokenUrl()
-                ),
-                tr("Request Failed"),
-                JOptionPane.ERROR_MESSAGE,
-                HelpUtil.ht("/OAuth#NotAuthorizedException")
-        );
-    }
-
-    @Override
-    protected void realRun() throws SAXException, IOException, OsmTransferException {
-        try {
-            synchronized (this) {
-                client = new OsmOAuthAuthorizationClient(parameters, requestToken);
-            }
-            accessToken = client.getAccessToken(getProgressMonitor().createSubTaskMonitor(0, false));
-        } catch (OsmTransferCanceledException e) {
-            Logging.trace(e);
-        } catch (final OsmOAuthAuthorizationException e) {
-            Logging.error(e);
-            GuiHelper.runInEDT(this::alertRetrievingAccessTokenFailed);
-            accessToken = null;
-        } finally {
-            synchronized (this) {
-                client = null;
-            }
-        }
-    }
-
-    /**
-     * Replies true if the task was canceled.
-     *
-     * @return {@code true} if user aborted operation
-     */
-    public boolean isCanceled() {
-        return canceled;
-    }
-
-    /**
-     * Replies the retrieved Access Token. null, if something went wrong.
-     *
-     * @return the retrieved Access Token
-     */
-    public OAuthToken getAccessToken() {
-        return accessToken;
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/gui/oauth/RetrieveRequestTokenTask.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,112 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Component;
-import java.io.IOException;
-
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.gui.HelpAwareOptionPane;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.gui.help.HelpUtil;
-import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.io.OsmTransferCanceledException;
-import org.openstreetmap.josm.io.OsmTransferException;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Logging;
-import org.xml.sax.SAXException;
-
-/**
- * Asynchronous task for retrieving a request token
- */
-public class RetrieveRequestTokenTask extends PleaseWaitRunnable {
-
-    private boolean canceled;
-    private OAuthToken requestToken;
-    private final OAuthParameters parameters;
-    private OsmOAuthAuthorizationClient client;
-    private final Component parent;
-
-    /**
-     * Creates the task
-     *
-     * @param parent the parent component relative to which the {@link PleaseWaitRunnable}-Dialog
-     * is displayed
-     * @param parameters the OAuth parameters. Must not be null.
-     * @throws IllegalArgumentException if parameters is null.
-     */
-    public RetrieveRequestTokenTask(Component parent, OAuthParameters parameters) {
-        super(parent, tr("Retrieving OAuth Request Token..."), false /* don't ignore exceptions */);
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
-        this.parameters = parameters;
-        this.parent = parent;
-    }
-
-    @Override
-    protected void cancel() {
-        canceled = true;
-        synchronized (this) {
-            if (client != null) {
-                client.cancel();
-            }
-        }
-    }
-
-    @Override
-    protected void finish() { /* not used in this task */}
-
-    protected void alertRetrievingRequestTokenFailed() {
-        HelpAwareOptionPane.showOptionDialog(
-                parent,
-                tr(
-                        "<html>Retrieving an OAuth Request Token from ''{0}'' failed.</html>",
-                        parameters.getRequestTokenUrl()
-                ),
-                tr("Request Failed"),
-                JOptionPane.ERROR_MESSAGE,
-                HelpUtil.ht("/OAuth#NotAuthorizedException")
-        );
-    }
-
-    @Override
-    protected void realRun() throws SAXException, IOException, OsmTransferException {
-        try {
-            synchronized (this) {
-                client = new OsmOAuthAuthorizationClient(parameters);
-            }
-            requestToken = client.getRequestToken(getProgressMonitor().createSubTaskMonitor(0, false));
-        } catch (OsmTransferCanceledException e) {
-            Logging.trace(e);
-        } catch (final OsmOAuthAuthorizationException e) {
-            Logging.error(e);
-            GuiHelper.runInEDT(this::alertRetrievingRequestTokenFailed);
-            requestToken = null;
-        } finally {
-            synchronized (this) {
-                client = null;
-            }
-        }
-    }
-
-    /**
-     * Replies true if the task was canceled
-     *
-     * @return true if the task was canceled
-     */
-    public boolean isCanceled() {
-        return canceled;
-    }
-
-    /**
-     * Replies the request token. null, if something went wrong.
-     *
-     * @return the request token
-     */
-    public OAuthToken getRequestToken() {
-        return requestToken;
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java b/core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java
deleted file mode 100644
--- a/core/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,460 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.FlowLayout;
-import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.util.concurrent.Executor;
-
-import javax.swing.AbstractAction;
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.gui.widgets.HtmlPanel;
-import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
-import org.openstreetmap.josm.gui.widgets.JosmTextField;
-import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.OpenBrowser;
-
-/**
- * This is the UI for running a semi-automatic authorisation procedure.
- *
- * In contrast to the fully-automatic procedure the user is dispatched to an
- * external browser for login and authorisation.
- *
- * @since 2746
- */
-public class SemiAutomaticAuthorizationUI extends AbstractAuthorizationUI {
-    private final AccessTokenInfoPanel pnlAccessTokenInfo = new AccessTokenInfoPanel();
-    private transient OAuthToken requestToken;
-
-    private RetrieveRequestTokenPanel pnlRetrieveRequestToken;
-    private RetrieveAccessTokenPanel pnlRetrieveAccessToken;
-    private ShowAccessTokenPanel pnlShowAccessToken;
-    private final transient Executor executor;
-
-    /**
-     * build the UI
-     */
-    protected final void build() {
-        setLayout(new BorderLayout());
-        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
-        pnlRetrieveRequestToken = new RetrieveRequestTokenPanel();
-        pnlRetrieveAccessToken = new RetrieveAccessTokenPanel();
-        pnlShowAccessToken = new ShowAccessTokenPanel();
-        add(pnlRetrieveRequestToken, BorderLayout.CENTER);
-    }
-
-    /**
-     * Constructs a new {@code SemiAutomaticAuthorizationUI} for the given API URL.
-     * @param apiUrl The OSM API URL
-     * @param executor the executor used for running the HTTP requests for the authorization
-     * @since 5422
-     */
-    public SemiAutomaticAuthorizationUI(String apiUrl, Executor executor) {
-        super(apiUrl);
-        this.executor = executor;
-        build();
-    }
-
-    @Override
-    public boolean isSaveAccessTokenToPreferences() {
-        return pnlAccessTokenInfo.isSaveToPreferences();
-    }
-
-    protected void transitionToRetrieveAccessToken() {
-        OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(
-                (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()
-        );
-        String authoriseUrl = client.getAuthoriseUrl(requestToken);
-        OpenBrowser.displayUrl(authoriseUrl);
-
-        removeAll();
-        pnlRetrieveAccessToken.setAuthoriseUrl(authoriseUrl);
-        add(pnlRetrieveAccessToken, BorderLayout.CENTER);
-        pnlRetrieveAccessToken.invalidate();
-        validate();
-        repaint();
-    }
-
-    protected void transitionToRetrieveRequestToken() {
-        requestToken = null;
-        setAccessToken(null);
-        removeAll();
-        add(pnlRetrieveRequestToken, BorderLayout.CENTER);
-        pnlRetrieveRequestToken.invalidate();
-        validate();
-        repaint();
-    }
-
-    protected void transitionToShowAccessToken() {
-        removeAll();
-        add(pnlShowAccessToken, BorderLayout.CENTER);
-        pnlShowAccessToken.invalidate();
-        validate();
-        repaint();
-        pnlShowAccessToken.setAccessToken(getAccessToken());
-    }
-
-    static class StepLabel extends JLabel {
-        StepLabel(String text) {
-            super(text);
-            setFont(getFont().deriveFont(16f));
-        }
-    }
-
-    /**
-     * This is the panel displayed in the first step of the semi-automatic authorisation process.
-     */
-    private class RetrieveRequestTokenPanel extends JPanel {
-
-        /**
-         * Constructs a new {@code RetrieveRequestTokenPanel}.
-         */
-        RetrieveRequestTokenPanel() {
-            build();
-        }
-
-        protected JPanel buildAdvancedParametersPanel() {
-            JPanel pnl = new JPanel(new GridBagLayout());
-            GridBagConstraints gc = new GridBagConstraints();
-
-            gc.anchor = GridBagConstraints.NORTHWEST;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            gc.weightx = 0.0;
-            gc.insets = new Insets(0, 0, 0, 3);
-            JCheckBox cbShowAdvancedParameters = new JCheckBox();
-            pnl.add(cbShowAdvancedParameters, gc);
-            cbShowAdvancedParameters.setSelected(false);
-            cbShowAdvancedParameters.addItemListener(
-                    evt -> getAdvancedPropertiesPanel().setVisible(evt.getStateChange() == ItemEvent.SELECTED)
-            );
-
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            JMultilineLabel lbl = new JMultilineLabel(tr("Display Advanced OAuth Parameters"));
-            lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
-            pnl.add(lbl, gc);
-
-            gc.gridy = 1;
-            gc.gridx = 1;
-            gc.insets = new Insets(3, 0, 3, 0);
-            gc.fill = GridBagConstraints.BOTH;
-            gc.weightx = 1.0;
-            gc.weighty = 1.0;
-            pnl.add(getAdvancedPropertiesPanel(), gc);
-            getAdvancedPropertiesPanel().setBorder(
-                    BorderFactory.createCompoundBorder(
-                            BorderFactory.createLineBorder(Color.GRAY, 1),
-                            BorderFactory.createEmptyBorder(3, 3, 3, 3)
-                    )
-            );
-            getAdvancedPropertiesPanel().setVisible(false);
-            return pnl;
-        }
-
-        protected JPanel buildCommandPanel() {
-            JPanel pnl = new JPanel(new GridBagLayout());
-            GridBagConstraints gc = new GridBagConstraints();
-
-            gc.anchor = GridBagConstraints.NORTHWEST;
-            gc.fill = GridBagConstraints.BOTH;
-            gc.weightx = 1.0;
-            gc.weighty = 1.0;
-            gc.insets = new Insets(0, 0, 0, 3);
-
-
-            HtmlPanel h = new HtmlPanel();
-            h.setText(tr("<html>"
-                    + "Please click on <strong>{0}</strong> to retrieve an OAuth Request Token from "
-                    + "''{1}''.</html>",
-                    tr("Retrieve Request Token"),
-                    ((OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()).getRequestTokenUrl()
-            ));
-            pnl.add(h, gc);
-
-            JPanel pnl1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
-            pnl1.add(new JButton(new RetrieveRequestTokenAction()));
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            gc.weightx = 1.0;
-            gc.gridy = 1;
-            pnl.add(pnl1, gc);
-            return pnl;
-
-        }
-
-        protected final void build() {
-            setLayout(new BorderLayout(0, 5));
-            add(new StepLabel(tr("<html>Step 1/3: Retrieve an OAuth Request Token</html>")), BorderLayout.NORTH);
-            add(buildAdvancedParametersPanel(), BorderLayout.CENTER);
-            add(buildCommandPanel(), BorderLayout.SOUTH);
-        }
-    }
-
-    /**
-     * This is the panel displayed in the second step of the semi-automatic authorization process.
-     */
-    private class RetrieveAccessTokenPanel extends JPanel {
-
-        private final JosmTextField tfAuthoriseUrl = new JosmTextField(null, null, 0, false);
-
-        /**
-         * Constructs a new {@code RetrieveAccessTokenPanel}.
-         */
-        RetrieveAccessTokenPanel() {
-            build();
-        }
-
-        protected JPanel buildTitlePanel() {
-            JPanel pnl = new JPanel(new BorderLayout());
-            pnl.add(new StepLabel(tr("<html>Step 2/3: Authorize and retrieve an Access Token</html>")), BorderLayout.CENTER);
-            return pnl;
-        }
-
-        protected JPanel buildContentPanel() {
-            JPanel pnl = new JPanel(new GridBagLayout());
-            GridBagConstraints gc = new GridBagConstraints();
-
-            gc.anchor = GridBagConstraints.NORTHWEST;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            gc.weightx = 1.0;
-            gc.gridwidth = 2;
-            HtmlPanel html = new HtmlPanel();
-            html.setText(tr("<html>"
-                    + "JOSM successfully retrieved a Request Token. "
-                    + "JOSM is now launching an authorization page in an external browser. "
-                    + "Please login with your OSM username and password and follow the instructions "
-                    + "to authorize the Request Token. Then switch back to this dialog and click on "
-                    + "<strong>{0}</strong><br><br>"
-                    + "If launching the external browser fails you can copy the following authorize URL "
-                    + "and paste it into the address field of your browser.</html>",
-                    tr("Request Access Token")
-            ));
-            pnl.add(html, gc);
-
-            gc.gridx = 0;
-            gc.gridy = 1;
-            gc.weightx = 0.0;
-            gc.gridwidth = 1;
-            pnl.add(new JLabel(tr("Authorize URL:")), gc);
-
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            pnl.add(tfAuthoriseUrl, gc);
-            tfAuthoriseUrl.setEditable(false);
-
-            return pnl;
-        }
-
-        protected JPanel buildActionPanel() {
-            JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
-            pnl.add(new JButton(new BackAction()));
-            pnl.add(new JButton(new RetrieveAccessTokenAction()));
-            return pnl;
-        }
-
-        protected final void build() {
-            setLayout(new BorderLayout());
-            add(buildTitlePanel(), BorderLayout.NORTH);
-            add(buildContentPanel(), BorderLayout.CENTER);
-            add(buildActionPanel(), BorderLayout.SOUTH);
-        }
-
-        public void setAuthoriseUrl(String url) {
-            tfAuthoriseUrl.setText(url);
-        }
-
-        /**
-         * Action to go back to step 1 in the process
-         */
-        class BackAction extends AbstractAction {
-            BackAction() {
-                putValue(NAME, tr("Back"));
-                putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
-                new ImageProvider("dialogs", "previous").getResource().attachImageIcon(this);
-            }
-
-            @Override
-            public void actionPerformed(ActionEvent arg0) {
-                transitionToRetrieveRequestToken();
-            }
-        }
-    }
-
-    /**
-     * Displays the retrieved Access Token in step 3.
-     */
-    class ShowAccessTokenPanel extends JPanel {
-
-        /**
-         * Constructs a new {@code ShowAccessTokenPanel}.
-         */
-        ShowAccessTokenPanel() {
-            build();
-        }
-
-        protected JPanel buildTitlePanel() {
-            JPanel pnl = new JPanel(new BorderLayout());
-            pnl.add(new StepLabel(tr("<html>Step 3/3: Successfully retrieved an Access Token</html>")), BorderLayout.CENTER);
-            return pnl;
-        }
-
-        protected JPanel buildContentPanel() {
-            JPanel pnl = new JPanel(new GridBagLayout());
-            GridBagConstraints gc = new GridBagConstraints();
-
-            gc.anchor = GridBagConstraints.NORTHWEST;
-            gc.fill = GridBagConstraints.HORIZONTAL;
-            gc.weightx = 1.0;
-            HtmlPanel html = new HtmlPanel();
-            html.setText(tr("<html>"
-                    + "JOSM has successfully retrieved an Access Token. "
-                    + "You can now accept this token. JOSM will use it in the future for authentication "
-                    + "and authorization to the OSM server.<br><br>"
-                    + "The access token is: </html>"
-            ));
-            pnl.add(html, gc);
-
-            gc.gridx = 0;
-            gc.gridy = 1;
-            gc.weightx = 1.0;
-            gc.gridwidth = 1;
-            pnl.add(pnlAccessTokenInfo, gc);
-            pnlAccessTokenInfo.setSaveToPreferences(
-                    OAuthAccessTokenHolder.getInstance().isSaveToPreferences()
-            );
-            return pnl;
-        }
-
-        protected JPanel buildActionPanel() {
-            JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
-            pnl.add(new JButton(new RestartAction()));
-            pnl.add(new JButton(new TestAccessTokenAction()));
-            return pnl;
-        }
-
-        protected final void build() {
-            setLayout(new BorderLayout());
-            add(buildTitlePanel(), BorderLayout.NORTH);
-            add(buildContentPanel(), BorderLayout.CENTER);
-            add(buildActionPanel(), BorderLayout.SOUTH);
-        }
-
-        /**
-         * Action to go back to step 1 in the process
-         */
-        class RestartAction extends AbstractAction {
-            RestartAction() {
-                putValue(NAME, tr("Restart"));
-                putValue(SHORT_DESCRIPTION, tr("Go back to step 1/3"));
-                new ImageProvider("dialogs", "previous").getResource().attachImageIcon(this);
-            }
-
-            @Override
-            public void actionPerformed(ActionEvent arg0) {
-                transitionToRetrieveRequestToken();
-            }
-        }
-
-        public void setAccessToken(OAuthToken accessToken) {
-            pnlAccessTokenInfo.setAccessToken(accessToken);
-        }
-    }
-
-    /**
-     * Action for retrieving a request token
-     */
-    class RetrieveRequestTokenAction extends AbstractAction {
-
-        RetrieveRequestTokenAction() {
-            putValue(NAME, tr("Retrieve Request Token"));
-            new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
-            putValue(SHORT_DESCRIPTION, tr("Click to retrieve a Request Token"));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent evt) {
-            final RetrieveRequestTokenTask task = new RetrieveRequestTokenTask(
-                    SemiAutomaticAuthorizationUI.this,
-                    (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters()
-            );
-            executor.execute(task);
-            Runnable r = () -> {
-                if (task.isCanceled()) return;
-                if (task.getRequestToken() == null) return;
-                requestToken = task.getRequestToken();
-                GuiHelper.runInEDT(SemiAutomaticAuthorizationUI.this::transitionToRetrieveAccessToken);
-            };
-            executor.execute(r);
-        }
-    }
-
-    /**
-     * Action for retrieving an Access Token
-     */
-    class RetrieveAccessTokenAction extends AbstractAction {
-
-        RetrieveAccessTokenAction() {
-            putValue(NAME, tr("Retrieve Access Token"));
-            new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
-            putValue(SHORT_DESCRIPTION, tr("Click to retrieve an Access Token"));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent evt) {
-            final RetrieveAccessTokenTask task = new RetrieveAccessTokenTask(
-                    SemiAutomaticAuthorizationUI.this,
-                    (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
-                    requestToken
-            );
-            executor.execute(task);
-            Runnable r = () -> {
-                if (task.isCanceled()) return;
-                if (task.getAccessToken() == null) return;
-                GuiHelper.runInEDT(() -> {
-                    setAccessToken(task.getAccessToken());
-                    transitionToShowAccessToken();
-                });
-            };
-            executor.execute(r);
-        }
-    }
-
-    /**
-     * Action for testing an Access Token
-     */
-    class TestAccessTokenAction extends AbstractAction {
-
-        TestAccessTokenAction() {
-            putValue(NAME, tr("Test Access Token"));
-            new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
-            putValue(SHORT_DESCRIPTION, tr("Click to test the Access Token"));
-        }
-
-        @Override
-        public void actionPerformed(ActionEvent evt) {
-            TestAccessTokenTask task = new TestAccessTokenTask(
-                    SemiAutomaticAuthorizationUI.this,
-                    getApiUrl(),
-                    (OAuthParameters) getAdvancedPropertiesPanel().getAdvancedParameters(),
-                    getAccessToken()
-            );
-            executor.execute(task);
-        }
-    }
-}
Index: core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java b/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
--- a/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java	(date 1707934343804)
@@ -11,11 +11,9 @@
 import javax.swing.JOptionPane;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.openstreetmap.josm.data.oauth.IOAuthParameters;
 import org.openstreetmap.josm.data.oauth.IOAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
+import org.openstreetmap.josm.data.oauth.OAuthException;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
@@ -33,20 +31,15 @@
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
-import oauth.signpost.OAuthConsumer;
-import oauth.signpost.exception.OAuthException;
-
 /**
  * Checks whether an OSM API server can be accessed with a specific Access Token.
- *
+ * <p>
  * It retrieves the user details for the user which is authorized to access the server with
  * this token.
  *
  */
 public class TestAccessTokenTask extends PleaseWaitRunnable {
-    private final OAuthToken tokenOAuth1;
     private final IOAuthToken tokenOAuth2;
-    private final IOAuthParameters oauthParameters;
     private boolean canceled;
     private final Component parent;
     private final String apiUrl;
@@ -57,38 +50,14 @@
      *
      * @param parent the parent component relative to which the  {@link PleaseWaitRunnable}-Dialog is displayed
      * @param apiUrl the API URL. Must not be null.
-     * @param parameters the OAuth parameters. Must not be null.
-     * @param accessToken the Access Token. Must not be null.
-     */
-    public TestAccessTokenTask(Component parent, String apiUrl, OAuthParameters parameters, OAuthToken accessToken) {
-        super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */);
-        CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
-        CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken");
-        this.tokenOAuth1 = accessToken;
-        this.tokenOAuth2 = null;
-        this.oauthParameters = parameters;
-        this.parent = parent;
-        this.apiUrl = apiUrl;
-    }
-
-    /**
-     * Create the task
-     *
-     * @param parent the parent component relative to which the  {@link PleaseWaitRunnable}-Dialog is displayed
-     * @param apiUrl the API URL. Must not be null.
-     * @param parameters the OAuth parameters. Must not be null.
      * @param accessToken the Access Token. Must not be null.
-     * @since 18764
+     * @since xxx
      */
-    public TestAccessTokenTask(Component parent, String apiUrl, IOAuthParameters parameters, IOAuthToken accessToken) {
+    public TestAccessTokenTask(Component parent, String apiUrl, IOAuthToken accessToken) {
         super(parent, tr("Testing OAuth Access Token"), false /* don't ignore exceptions */);
         CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");
-        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
         CheckParameterUtil.ensureParameterNotNull(accessToken, "accessToken");
-        this.tokenOAuth1 = null;
         this.tokenOAuth2 = accessToken;
-        this.oauthParameters = parameters;
         this.parent = parent;
         this.apiUrl = apiUrl;
     }
@@ -109,18 +78,7 @@
     }
 
     protected void sign(HttpClient con) throws OAuthException {
-        if (oauthParameters instanceof OAuthParameters) {
-            OAuthConsumer consumer = ((OAuthParameters) oauthParameters).buildConsumer();
-            consumer.setTokenWithSecret(tokenOAuth1.getKey(), tokenOAuth1.getSecret());
-            consumer.sign(con);
-        } else {
-            try {
-                this.tokenOAuth2.sign(con);
-            } catch (org.openstreetmap.josm.data.oauth.OAuthException e) {
-                // Adapt our OAuthException to the SignPost OAuth exception
-                throw new OAuthException(e) {};
-            }
-        }
+        this.tokenOAuth2.sign(con);
     }
 
     protected String normalizeApiUrl(String url) {
@@ -314,12 +272,9 @@
     }
 
     private String getAuthKey() {
-        if (this.tokenOAuth1 != null) {
-            return this.tokenOAuth1.getKey();
-        }
         if (this.tokenOAuth2 instanceof OAuth20Token) {
             return ((OAuth20Token) this.tokenOAuth2).getBearerToken();
         }
-        throw new IllegalArgumentException("Only OAuth1 and OAuth2 tokens are understood: " + this.tokenOAuth2);
+        throw new IllegalArgumentException("Only OAuth2 tokens are understood: " + this.tokenOAuth2);
     }
 }
Index: core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java b/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java
--- a/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/preferences/server/AuthenticationPreferencesPanel.java	(date 1707933215321)
@@ -38,16 +38,12 @@
 
     /** indicates whether we use basic authentication */
     private final JRadioButton rbBasicAuthentication = new JRadioButton();
-    /** indicates whether we use OAuth 1.0a as authentication scheme */
-    private final JRadioButton rbOAuth = new JRadioButton();
     /** indicates whether we use OAuth 2.0 as authentication scheme */
     private final JRadioButton rbOAuth20 = new JRadioButton();
     /** the panel which contains the authentication parameters for the respective authentication scheme */
     private final JPanel pnlAuthenticationParameters = new JPanel(new BorderLayout());
     /** the panel for the basic authentication parameters */
     private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences;
-    /** the panel for the OAuth 1.0a authentication parameters */
-    private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;
     /** the panel for the OAuth 2.0 authentication parameters */
     private OAuthAuthenticationPreferencesPanel pnlOAuth20Preferences;
 
@@ -58,7 +54,6 @@
         final String authMethod = OsmApi.getAuthMethod();
         final boolean defaultApi = JosmUrls.getInstance().getDefaultOsmApiUrl().equals(apiUrl);
         rbBasicAuthentication.setEnabled(rbBasicAuthentication.isSelected() || "basic".equals(authMethod) || isExpert || !defaultApi);
-        rbOAuth.setEnabled(rbOAuth.isSelected() || "oauth".equals(authMethod) || isExpert || !defaultApi);
     };
 
     /**
@@ -84,13 +79,6 @@
         rbBasicAuthentication.setText(tr("Use Basic Authentication"));
         rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password"));
         rbBasicAuthentication.addItemListener(authChangeListener);
-
-        //-- radio button for OAuth 1.0a
-        buttonPanel.add(rbOAuth);
-        rbOAuth.setText(tr("Use OAuth {0}", "1.0a"));
-        rbOAuth.setToolTipText(tr("Select to use OAuth {0} as authentication mechanism", "1.0a"));
-        rbOAuth.addItemListener(authChangeListener);
-
         //-- radio button for OAuth 2.0
         buttonPanel.add(rbOAuth20);
         rbOAuth20.setText(tr("Use OAuth {0}", "2.0"));
@@ -101,7 +89,6 @@
         //-- radio button for OAuth
         ButtonGroup bg = new ButtonGroup();
         bg.add(rbBasicAuthentication);
-        bg.add(rbOAuth);
         bg.add(rbOAuth20);
 
         //-- add the panel which will hold the authentication parameters
@@ -118,7 +105,6 @@
 
         //-- the two panels for authentication parameters
         pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel();
-        pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth10a);
         pnlOAuth20Preferences = new OAuthAuthenticationPreferencesPanel(OAuthVersion.OAuth20);
 
         ExpertToggleAction.addExpertModeChangeListener(expertModeChangeListener, true);
@@ -132,23 +118,17 @@
      */
     public final void initFromPreferences() {
         final String authMethod = OsmApi.getAuthMethod();
-        switch (authMethod) {
-            case "basic":
-                rbBasicAuthentication.setSelected(true);
-                break;
-            case "oauth":
-                rbOAuth.setSelected(true);
-                break;
-            case "oauth20":
-                rbOAuth20.setSelected(true);
-                break;
-            default:
-                Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.",
-                        "osm-server.auth-method", authMethod));
-                rbBasicAuthentication.setSelected(true);
+        if ("basic".equals(authMethod)) {
+            rbBasicAuthentication.setSelected(true);
+        } else if ("oauth20".equals(authMethod)) {
+            rbOAuth20.setSelected(true);
+        } else {
+            Logging.warn(
+                    tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''OAuth 2.0 Authentication''.",
+                            "osm-server.auth-method", authMethod));
+            rbOAuth20.setSelected(true);
         }
         pnlBasicAuthPreferences.initFromPreferences();
-        pnlOAuthPreferences.initFromPreferences();
         pnlOAuth20Preferences.initFromPreferences();
     }
 
@@ -160,8 +140,6 @@
         String authMethod;
         if (rbBasicAuthentication.isSelected()) {
             authMethod = "basic";
-        } else if (rbOAuth.isSelected()) {
-            authMethod = "oauth";
         } else if (rbOAuth20.isSelected()) {
             authMethod = "oauth20";
         } else {
@@ -173,22 +151,19 @@
             pnlBasicAuthPreferences.saveToPreferences();
             OAuthAccessTokenHolder.getInstance().clear();
             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
-        } else if ("oauth".equals(authMethod)) {
-            // clear the password in the preferences
-            pnlBasicAuthPreferences.clearPassword();
-            pnlBasicAuthPreferences.saveToPreferences();
-            pnlOAuthPreferences.saveToPreferences();
-        } else { // oauth20
+        } else if ("oauth20".equals(authMethod)) {
+            // oauth20
             // clear the password in the preferences
             pnlBasicAuthPreferences.clearPassword();
-            pnlBasicAuthPreferences.saveToPreferences();
             pnlOAuth20Preferences.saveToPreferences();
         }
         if (initUser) {
             if ("basic".equals(authMethod)) {
                 UserIdentityManager.getInstance().initFromPreferences();
-            } else {
+            } else if (OsmApi.isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())) {
                 UserIdentityManager.getInstance().initFromOAuth();
+            } else {
+                UserIdentityManager.getInstance().setAnonymous();
             }
         }
         ExpertToggleAction.removeExpertModeChangeListener(this.expertModeChangeListener);
@@ -204,11 +179,6 @@
             if (rbBasicAuthentication.isSelected()) {
                 pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
                 pnlBasicAuthPreferences.revalidate();
-            } else if (rbOAuth.isSelected()) {
-                pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER);
-                pnlOAuthPreferences.saveToPreferences();
-                pnlOAuthPreferences.initFromPreferences();
-                pnlOAuthPreferences.revalidate();
             } else if (rbOAuth20.isSelected()) {
                 pnlAuthenticationParameters.add(pnlOAuth20Preferences, BorderLayout.CENTER);
                 pnlOAuth20Preferences.saveToPreferences();
@@ -221,9 +191,6 @@
 
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
-        if (pnlOAuthPreferences != null) {
-            pnlOAuthPreferences.propertyChange(evt);
-        }
         if (pnlOAuth20Preferences != null) {
             pnlOAuth20Preferences.propertyChange(evt);
         }
Index: core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java b/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java
--- a/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java	(date 1707931030527)
@@ -5,6 +5,7 @@
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.GridBagConstraints;
@@ -14,24 +15,22 @@
 import java.awt.event.ItemEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.util.Arrays;
+import java.util.Objects;
 
 import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 
 import org.openstreetmap.josm.actions.ExpertToggleAction;
 import org.openstreetmap.josm.data.oauth.IOAuthToken;
-import org.openstreetmap.josm.data.oauth.OAuth20Authorization;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthVersion;
-import org.openstreetmap.josm.data.oauth.osm.OsmScopes;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.oauth.AdvancedOAuthPropertiesPanel;
 import org.openstreetmap.josm.gui.oauth.AuthorizationProcedure;
@@ -42,11 +41,11 @@
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.auth.CredentialsManager;
-import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.UserCancelException;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
  * The preferences panel for the OAuth 1.0a preferences. This just a summary panel
@@ -67,13 +66,6 @@
     private final OAuthVersion oAuthVersion;
     private String apiUrl;
 
-    /**
-     * Create the panel. Uses {@link OAuthVersion#OAuth10a}.
-     */
-    public OAuthAuthenticationPreferencesPanel() {
-        this(OAuthVersion.OAuth10a);
-    }
-
     /**
      * Create the panel.
      * @param oAuthVersion The OAuth version to use
@@ -138,9 +130,7 @@
 
     protected void refreshView() {
         pnlAuthorisationMessage.removeAll();
-        if ((this.oAuthVersion == OAuthVersion.OAuth10a &&
-                OAuthAccessTokenHolder.getInstance().containsAccessToken())
-        || OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) {
+        if (OAuthAccessTokenHolder.getInstance().getAccessToken(this.apiUrl, this.oAuthVersion) != null) {
             pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER);
             pnlAlreadyAuthorised.refreshView();
             pnlAlreadyAuthorised.revalidate();
@@ -159,6 +149,13 @@
     public void setApiUrl(String apiUrl) {
         this.apiUrl = apiUrl;
         pnlAdvancedProperties.setApiUrl(apiUrl);
+        for (JPanel panel : Arrays.asList(this.pnlNotYetAuthorised, (JPanel) this.pnlAlreadyAuthorised.getComponent(6))) {
+            for (Component component : panel.getComponents()) {
+                if (component instanceof JButton && ((JButton) component).getAction() instanceof AuthoriseNowAction) {
+                    ((AuthoriseNowAction) ((JButton) component).getAction()).updateEnabledState();
+                }
+            }
+        }
     }
 
     /**
@@ -203,15 +200,10 @@
             lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
 
             // Action for authorising now
-            if (oAuthVersion == OAuthVersion.OAuth10a) {
-                add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol());
-            }
-            add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.SEMI_AUTOMATIC)), GBC.eol());
-            if (oAuthVersion == OAuthVersion.OAuth10a) {
-                JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY));
-                add(authManually, GBC.eol());
-                ExpertToggleAction.addVisibilitySwitcher(authManually);
-            }
+            add(new JButton(new AuthoriseNowAction(AuthorizationProcedure.FULLY_AUTOMATIC)), GBC.eol());
+            JButton authManually = new JButton(new AuthoriseNowAction(AuthorizationProcedure.MANUALLY));
+            add(authManually, GBC.eol());
+            ExpertToggleAction.addVisibilitySwitcher(authManually);
 
             // filler - grab remaining space
             add(new JPanel(), GBC.std().fill(GBC.BOTH));
@@ -224,7 +216,6 @@
      */
     private class AlreadyAuthorisedPanel extends JPanel {
         private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
-        private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
 
         /**
          * Constructs a new {@code AlreadyAuthorisedPanel}.
@@ -265,11 +256,6 @@
             gc.weightx = 0.0;
             add(new JLabel(tr("Access Token Secret:")), gc);
 
-            gc.gridx = 1;
-            gc.weightx = 1.0;
-            add(tfAccessTokenSecret, gc);
-            tfAccessTokenSecret.setEditable(false);
-
             // -- access token secret
             gc.gridy = 3;
             gc.gridx = 0;
@@ -280,11 +266,8 @@
 
             // -- action buttons
             JPanel btns = new JPanel(new FlowLayout(FlowLayout.LEFT));
-            if (oAuthVersion == OAuthVersion.OAuth10a) {
-                // these want the OAuth 1.0 token information
-                btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC)));
-            }
-            btns.add(new JButton(new TestAuthorisationAction(oAuthVersion)));
+            btns.add(new JButton(new RenewAuthorisationAction(AuthorizationProcedure.FULLY_AUTOMATIC)));
+            btns.add(new JButton(new TestAuthorisationAction()));
             btns.add(new JButton(new RemoveAuthorisationAction()));
             gc.gridy = 4;
             gc.gridx = 0;
@@ -309,13 +292,6 @@
 
         protected final void refreshView() {
             switch (oAuthVersion) {
-                case OAuth10a:
-                    String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey();
-                    tfAccessTokenKey.setText(v == null ? "" : v);
-                    v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret();
-                    tfAccessTokenSecret.setText(v == null ? "" : v);
-                    tfAccessTokenSecret.setVisible(true);
-                    break;
                 case OAuth20:
                 case OAuth21:
                     String token = "";
@@ -324,7 +300,8 @@
                         token = bearerToken == null ? "" : bearerToken.getBearerToken();
                     }
                     tfAccessTokenKey.setText(token == null ? "" : token);
-                    tfAccessTokenSecret.setVisible(false);
+                    break;
+                default:
             }
             cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences());
         }
@@ -340,51 +317,42 @@
             this.procedure = procedure;
             putValue(NAME, tr("{0} ({1})", tr("Authorize now"), procedure.getText()));
             putValue(SHORT_DESCRIPTION, procedure.getDescription());
-            if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC
-            || OAuthAuthenticationPreferencesPanel.this.oAuthVersion != OAuthVersion.OAuth10a) {
+            if (procedure == AuthorizationProcedure.FULLY_AUTOMATIC) {
                 new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
             }
+            updateEnabledState();
+        }
+
+        void updateEnabledState() {
+            if (procedure == AuthorizationProcedure.MANUALLY) {
+                this.setEnabled(true);
+            } else {
+                final String currentApiUrl = apiUrl;
+                MainApplication.worker.execute(() -> {
+                    final String clientId = OAuthParameters.createDefault(apiUrl, oAuthVersion).getClientId();
+                    if (Objects.equals(apiUrl, currentApiUrl)) {
+                        GuiHelper.runInEDT(() -> this.setEnabled(!Utils.isEmpty(clientId)));
+                    }
+                });
+            }
         }
 
         @Override
         public void actionPerformed(ActionEvent arg0) {
-            if (OAuthAuthenticationPreferencesPanel.this.oAuthVersion == OAuthVersion.OAuth10a) {
-                OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
-                        OAuthAuthenticationPreferencesPanel.this,
-                        procedure,
-                        apiUrl,
-                        MainApplication.worker);
-                try {
-                    wizard.showDialog();
-                } catch (UserCancelException ignore) {
-                    Logging.trace(ignore);
-                    return;
-                }
-                pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
-                refreshView();
-            } else {
-                final boolean remoteControlIsRunning = Boolean.TRUE.equals(RemoteControl.PROP_REMOTECONTROL_ENABLED.get());
-                // TODO: Ask user if they want to start remote control?
-                if (!remoteControlIsRunning) {
-                    RemoteControl.start();
-                }
-                new OAuth20Authorization().authorize(OAuthParameters.createDefault(OsmApi.getOsmApi().getServerUrl(), oAuthVersion), token -> {
-                    if (!remoteControlIsRunning) {
-                        RemoteControl.stop();
-                    }
-                    OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), token.orElse(null));
-                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
-                    GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView);
-                    if (!token.isPresent()) {
-                        GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(),
-                                tr("Authentication failed, please check browser for details."),
-                                tr("OAuth Authentication Failed"),
-                                JOptionPane.ERROR_MESSAGE));
-                    }
-                }, OsmScopes.read_gpx, OsmScopes.write_gpx,
-                        OsmScopes.read_prefs, OsmScopes.write_prefs,
-                        OsmScopes.write_api, OsmScopes.write_notes);
-            }
+            OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
+                    OAuthAuthenticationPreferencesPanel.this,
+                    procedure,
+                    apiUrl,
+                    MainApplication.worker,
+                    oAuthVersion);
+            try {
+                wizard.showDialog(token -> GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView));
+            } catch (UserCancelException userCancelException) {
+                Logging.trace(userCancelException);
+                return;
+            }
+            pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
+            refreshView();
         }
     }
 
@@ -400,11 +368,7 @@
 
         @Override
         public void actionPerformed(ActionEvent e) {
-            if (oAuthVersion == OAuthVersion.OAuth10a) {
-                OAuthAccessTokenHolder.getInstance().setAccessToken(null);
-            } else {
-                OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, (IOAuthToken) null);
-            }
+            OAuthAccessTokenHolder.getInstance().setAccessToken(apiUrl, null);
             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
             refreshView();
         }
@@ -429,13 +393,10 @@
      * Runs a test whether we can access the OSM server with the current Access Token
      */
     private class TestAuthorisationAction extends AbstractAction {
-        private final OAuthVersion oAuthVersion;
-
         /**
          * Constructs a new {@code TestAuthorisationAction}.
          */
-        TestAuthorisationAction(OAuthVersion oAuthVersion) {
-            this.oAuthVersion = oAuthVersion;
+        TestAuthorisationAction() {
             putValue(NAME, tr("Test Access Token"));
             putValue(SHORT_DESCRIPTION, tr("Click test access to the OSM server with the current access token"));
             new ImageProvider("oauth", "oauth-small").getResource().attachImageIcon(this);
@@ -443,26 +404,13 @@
 
         @Override
         public void actionPerformed(ActionEvent evt) {
-            if (this.oAuthVersion == OAuthVersion.OAuth10a) {
-                OAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken();
-                OAuthParameters parameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
-                TestAccessTokenTask task = new TestAccessTokenTask(
-                        OAuthAuthenticationPreferencesPanel.this,
-                        apiUrl,
-                        parameters,
-                        token
-                );
-                MainApplication.worker.submit(task);
-            } else {
-                IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
-                TestAccessTokenTask task = new TestAccessTokenTask(
-                        OAuthAuthenticationPreferencesPanel.this,
-                        apiUrl,
-                        token.getParameters(),
-                        token
-                );
-                MainApplication.worker.submit(task);
-            }
+            IOAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
+            TestAccessTokenTask task = new TestAccessTokenTask(
+                    OAuthAuthenticationPreferencesPanel.this,
+                    apiUrl,
+                    token
+            );
+            MainApplication.worker.submit(task);
         }
     }
 
Index: core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java b/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
--- a/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java	(date 1707931030567)
@@ -6,7 +6,6 @@
 import java.net.PasswordAuthentication;
 
 import org.openstreetmap.josm.data.oauth.IOAuthToken;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 
 import jakarta.annotation.Nullable;
 
@@ -64,8 +63,12 @@
      *
      * @return the current OAuth Access Token to access the OSM server.
      * @throws CredentialsAgentException if something goes wrong
+     * @deprecated since xxx -- OAuth 1.0 is being removed from the OSM API
      */
-    OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException;
+    @Deprecated
+    default IOAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
+        throw new CredentialsAgentException("Call to deprecated method");
+    }
 
     /**
      * Lookup the current OAuth Access Token to access the specified server. Replies null, if no
@@ -84,15 +87,19 @@
      *
      * @param accessToken the access Token. null, to remove the Access Token.
      * @throws CredentialsAgentException if something goes wrong
+     * @deprecated since xxx -- OAuth 1.0 is being removed from the OSM API
      */
-    void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException;
+    @Deprecated
+    default void storeOAuthAccessToken(IOAuthToken accessToken) throws CredentialsAgentException {
+        throw new CredentialsAgentException("Call to deprecated method");
+    }
 
     /**
      * Stores the OAuth Access Token <code>accessToken</code>.
      *
      * @param host The host the access token is for
      * @param accessToken the access Token. null, to remove the Access Token. This will remove all IOAuthTokens <i>not</i> managed by
-     *                    {@link #storeOAuthAccessToken(OAuthToken)}.
+     *                    {@link #storeOAuthAccessToken(IOAuthToken)}.
      * @throws CredentialsAgentException if something goes wrong
      * @since 18650
      */
Index: core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java b/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
--- a/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(date 1707931030608)
@@ -8,7 +8,6 @@
 
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.oauth.IOAuthToken;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Logging;
@@ -16,7 +15,7 @@
 
 /**
  * CredentialManager is a factory for the single credential agent used.
- *
+ * <p>
  * Currently, it defaults to replying an instance of {@link JosmPreferencesCredentialAgent}.
  * @since 2641
  */
@@ -156,21 +155,11 @@
         return credentials;
     }
 
-    @Override
-    public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
-        return delegate.lookupOAuthAccessToken();
-    }
-
     @Override
     public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
         return delegate.lookupOAuthAccessToken(host);
     }
 
-    @Override
-    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
-        delegate.storeOAuthAccessToken(accessToken);
-    }
-
     @Override
     public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException {
         delegate.storeOAuthAccessToken(host, accessToken);
Index: core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java b/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java
--- a/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialAgent.java	(date 1707931030651)
@@ -17,7 +17,6 @@
 import org.openstreetmap.josm.data.oauth.OAuth20Exception;
 import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.io.DefaultProxySelector;
@@ -102,22 +101,6 @@
         }
     }
 
-    /**
-     * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
-     * Access Token is currently managed by this CredentialManager.
-     *
-     * @return the current OAuth Access Token to access the OSM server.
-     * @throws CredentialsAgentException if something goes wrong
-     */
-    @Override
-    public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
-        String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);
-        String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);
-        if (accessTokenKey == null && accessTokenSecret == null)
-            return null;
-        return new OAuthToken(accessTokenKey, accessTokenSecret);
-    }
-
     @Override
     public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
         Set<String> keySet = new HashSet<>(Config.getPref().getKeySet());
@@ -142,23 +125,6 @@
         return null;
     }
 
-    /**
-     * Stores the OAuth Access Token <code>accessToken</code>.
-     *
-     * @param accessToken the access Token. null, to remove the Access Token.
-     * @throws CredentialsAgentException if something goes wrong
-     */
-    @Override
-    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsAgentException {
-        if (accessToken == null) {
-            Config.getPref().put("oauth.access-token.key", null);
-            Config.getPref().put("oauth.access-token.secret", null);
-        } else {
-            Config.getPref().put("oauth.access-token.key", accessToken.getKey());
-            Config.getPref().put("oauth.access-token.secret", accessToken.getSecret());
-        }
-    }
-
     @Override
     public void storeOAuthAccessToken(String host, IOAuthToken accessToken) throws CredentialsAgentException {
         Objects.requireNonNull(host, "host");
Index: core/src/org/openstreetmap/josm/io/MessageNotifier.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/MessageNotifier.java b/core/src/org/openstreetmap/josm/io/MessageNotifier.java
--- a/core/src/org/openstreetmap/josm/io/MessageNotifier.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/MessageNotifier.java	(date 1707931030690)
@@ -144,9 +144,7 @@
             CredentialsManager credManager = CredentialsManager.getInstance();
             try {
                 if (JosmPreferencesCredentialAgent.class.equals(credManager.getCredentialsAgentClass())) {
-                    if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) {
-                        return credManager.lookupOAuthAccessToken() != null;
-                    } else if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) {
+                    if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20) || OsmApi.isUsingOAuth(OAuthVersion.OAuth21)) {
                         return credManager.lookupOAuthAccessToken(OsmApi.getOsmApi().getHost()) != null;
                     } else if (OsmApi.isUsingOAuth()) {
                         // Ensure we do not forget to update this section
Index: core/src/org/openstreetmap/josm/io/OsmApi.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/OsmApi.java b/core/src/org/openstreetmap/josm/io/OsmApi.java
--- a/core/src/org/openstreetmap/josm/io/OsmApi.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/OsmApi.java	(date 1707935653408)
@@ -51,6 +51,8 @@
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
+import jakarta.annotation.Nullable;
+
 /**
  * Class that encapsulates the communications with the <a href="http://wiki.openstreetmap.org/wiki/API_v0.6">OSM API</a>.<br><br>
  *
@@ -84,8 +86,6 @@
     private static final Map<String, OsmApi> instances = new HashMap<>();
 
     private static final ListenerList<OsmApiInitializationListener> listeners = ListenerList.create();
-    /** This is used to make certain we have set osm-server.auth-method to the "right" default */
-    private static boolean oauthCompatibilitySwitch;
 
     private URL url;
 
@@ -652,8 +652,7 @@
      * @since 6349
      */
     public static boolean isUsingOAuth() {
-        return isUsingOAuth(OAuthVersion.OAuth10a)
-                || isUsingOAuth(OAuthVersion.OAuth20)
+        return isUsingOAuth(OAuthVersion.OAuth20)
                 || isUsingOAuth(OAuthVersion.OAuth21);
     }
 
@@ -664,10 +663,8 @@
      * @since 18650
      */
     public static boolean isUsingOAuth(OAuthVersion version) {
-        if (version == OAuthVersion.OAuth10a) {
-            return "oauth".equalsIgnoreCase(getAuthMethod());
-        } else if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) {
-            return "oauth20".equalsIgnoreCase(getAuthMethod());
+        if (version == OAuthVersion.OAuth20 || version == OAuthVersion.OAuth21) {
+            return getAuthMethodVersion() == OAuthVersion.OAuth20 || getAuthMethodVersion() == OAuthVersion.OAuth21;
         }
         return false;
     }
@@ -679,9 +676,6 @@
      */
     public static boolean isUsingOAuthAndOAuthSetUp(OsmApi api) {
         if (OsmApi.isUsingOAuth()) {
-            if (OsmApi.isUsingOAuth(OAuthVersion.OAuth10a)) {
-                return OAuthAccessTokenHolder.getInstance().containsAccessToken();
-            }
             if (OsmApi.isUsingOAuth(OAuthVersion.OAuth20)) {
                 return OAuthAccessTokenHolder.getInstance().getAccessToken(api.getBaseUrl(), OAuthVersion.OAuth20) != null;
             }
@@ -697,24 +691,23 @@
      * @return the authentication method
      */
     public static String getAuthMethod() {
-        setCurrentAuthMethod();
         return Config.getPref().get("osm-server.auth-method", "oauth20");
     }
 
     /**
-     * This is a compatibility method for users who currently use OAuth 1.0 -- we are changing the default from oauth to oauth20,
-     * but since oauth was the default, pre-existing users will suddenly be switched to oauth20.
-     * This should be removed whenever {@link OAuthVersion#OAuth10a} support is removed.
+     * Returns the authentication method set in the preferences
+     * @return the authentication method
+     * @since xxx
      */
-    private static void setCurrentAuthMethod() {
-        if (!oauthCompatibilitySwitch) {
-            oauthCompatibilitySwitch = true;
-            final String prefKey = "osm-server.auth-method";
-            if ("oauth20".equals(Config.getPref().get(prefKey, "oauth20"))
-                && !isUsingOAuthAndOAuthSetUp(OsmApi.getOsmApi())
-                && OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
-                Config.getPref().put(prefKey, "oauth");
-            }
+    @Nullable
+    public static OAuthVersion getAuthMethodVersion() {
+        switch (getAuthMethod()) {
+            case "oauth20": return OAuthVersion.OAuth20;
+            case "oauth21": return OAuthVersion.OAuth21;
+            case "basic": return null;
+            default:
+                Config.getPref().put("osm-server.auth-method", null);
+                return getAuthMethodVersion();
         }
     }
 
Index: core/src/org/openstreetmap/josm/io/OsmConnection.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/io/OsmConnection.java b/core/src/org/openstreetmap/josm/io/OsmConnection.java
--- a/core/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/io/OsmConnection.java	(date 1707938498919)
@@ -5,7 +5,6 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.net.Authenticator.RequestorType;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
@@ -35,9 +34,6 @@
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Logging;
 
-import oauth.signpost.OAuthConsumer;
-import oauth.signpost.exception.OAuthException;
-
 /**
  * Base class that handles common things like authentication for the reader and writer
  * to the osm server.
@@ -50,7 +46,6 @@
 
     protected boolean cancel;
     protected HttpClient activeConnection;
-    protected OAuthParameters oauthParameters;
     protected IOAuthParameters oAuth20Parameters;
 
     /**
@@ -144,57 +139,6 @@
         }
     }
 
-    /**
-     * Signs the connection with an OAuth authentication header
-     *
-     * @param connection the connection
-     *
-     * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured
-     * @throws OsmTransferException if signing fails
-     */
-    protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
-        if (oauthParameters == null) {
-            oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
-        }
-        OAuthConsumer consumer = oauthParameters.buildConsumer();
-        OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
-        if (!holder.containsAccessToken()) {
-            obtainAccessToken(connection);
-        }
-        if (!holder.containsAccessToken()) { // check if wizard completed
-            throw new MissingOAuthAccessTokenException();
-        }
-        consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());
-        try {
-            consumer.sign(connection);
-        } catch (OAuthException e) {
-            throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);
-        }
-    }
-
-    /**
-     * Obtains an OAuth access token for the connection.
-     * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
-     * @param connection connection for which the access token should be obtained
-     * @throws MissingOAuthAccessTokenException if the process cannot be completed successfully
-     */
-    protected void obtainAccessToken(final HttpClient connection) throws MissingOAuthAccessTokenException {
-        try {
-            final URL apiUrl = new URL(OsmApi.getOsmApi().getServerUrl());
-            if (!Objects.equals(apiUrl.getHost(), connection.getURL().getHost())) {
-                throw new MissingOAuthAccessTokenException();
-            }
-            fetcher.obtainAccessToken(apiUrl);
-            OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true);
-            OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
-        } catch (MalformedURLException | InvocationTargetException e) {
-            throw new MissingOAuthAccessTokenException(e);
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-            throw new MissingOAuthAccessTokenException(e);
-        }
-    }
-
     /**
      * Obtains an OAuth access token for the connection.
      * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
@@ -220,7 +164,6 @@
                         RemoteControl.stop();
                     }
                     // Clean up old token/password
-                    OAuthAccessTokenHolder.getInstance().setAccessToken(null);
                     OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), authToken.orElse(null));
                     OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
                     done.countDown();
@@ -279,9 +222,6 @@
         switch (authMethod) {
             case "basic":
                 addBasicAuthorizationHeader(connection);
-                return;
-            case "oauth":
-                addOAuthAuthorizationHeader(connection);
                 return;
             case "oauth20":
                 addOAuth20AuthorizationHeader(connection);
Index: core/src/org/openstreetmap/josm/tools/ExceptionUtil.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java b/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java
--- a/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java	(revision 18985)
+++ b/core/src/org/openstreetmap/josm/tools/ExceptionUtil.java	(date 1707931030958)
@@ -297,7 +297,7 @@
                 + "Authentication at the OSM server with the OAuth token ''{0}'' failed.<br>"
                 + "Please launch the preferences dialog and retrieve another OAuth token."
                 + "</html>",
-                OAuthAccessTokenHolder.getInstance().getAccessTokenKey()
+                OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion())
         );
     }
 
@@ -343,7 +343,7 @@
                 + "''{1}''.<br>"
                 + "Please launch the preferences dialog and retrieve another OAuth token."
                 + "</html>",
-                OAuthAccessTokenHolder.getInstance().getAccessTokenKey(),
+                OAuthAccessTokenHolder.getInstance().getAccessToken(e.getUrl(), OsmApi.getAuthMethodVersion()),
                 e.getAccessedUrl() == null ? tr("unknown") : e.getAccessedUrl()
         );
     }
Index: core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java
--- a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java	(date 1707933052079)
@@ -185,7 +185,7 @@
         final OAuth20Authorization authorization = new OAuth20Authorization();
         OAuth20Parameters parameters = (OAuth20Parameters) OAuthParameters.createDefault(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
         RemoteControl.start();
-        authorization.authorize(new OAuth20Parameters(parameters.getClientId(), parameters.getClientSecret(),
+        authorization.authorize(new OAuth20Parameters(CLIENT_ID_VALUE, parameters.getClientSecret(),
                 wireMockRuntimeInfo.getHttpBaseUrl() + "/oauth2", wireMockRuntimeInfo.getHttpBaseUrl() + "/api",
                 parameters.getRedirectUri()), consumer::set, OsmScopes.read_gpx);
         assertEquals(1, OpenBrowserMocker.getCalledURIs().size());
Index: core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java
--- a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java	(date 1707941986919)
@@ -23,16 +23,14 @@
     @Test
     @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
     void testCreateDefault() {
-        OAuthParameters def = OAuthParameters.createDefault();
+        IOAuthParameters def = OAuthParameters.createDefault();
         assertNotNull(def);
-        assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl()));
-        OAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api");
+        assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20));
+        IOAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api", OAuthVersion.OAuth20);
         assertNotNull(dev);
         assertNotEquals(def, dev);
         Logging.setLogLevel(Logging.LEVEL_TRACE); // enable trace for line coverage
-        assertEquals(def, OAuthParameters.createDefault("wrong_url"));
-        OAuthParameters dev2 = new OAuthParameters(dev);
-        assertEquals(dev, dev2);
+        assertEquals(def, OAuthParameters.createDefault("wrong_url", OAuthVersion.OAuth20));
     }
 
     /**
@@ -41,6 +39,6 @@
     @Test
     void testEqualsContract() {
         TestUtils.assumeWorkingEqualsVerifier();
-        EqualsVerifier.forClass(OAuthParameters.class).usingGetClass().verify();
+        EqualsVerifier.forClass(OAuth20Parameters.class).usingGetClass().verify();
     }
 }
Index: core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java
deleted file mode 100644
--- a/core/test/unit/org/openstreetmap/josm/data/oauth/OAuthTokenTest.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,40 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.oauth;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.TestUtils;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
-import oauth.signpost.OAuthConsumer;
-
-/**
- * Unit tests for class {@link OAuthToken}.
- */
-class OAuthTokenTest {
-
-    /**
-     * Unit test of method {@link OAuthToken#createToken}.
-     */
-    @Test
-    void testCreateToken() {
-        OAuthConsumer defCon = OAuthParameters.createDefault().buildConsumer();
-        assertNotNull(defCon);
-        OAuthToken defTok = OAuthToken.createToken(defCon);
-        assertNotNull(defTok);
-        assertEquals(defCon.getToken(), defTok.getKey());
-        assertEquals(defCon.getTokenSecret(), defTok.getSecret());
-        assertEquals(defTok, new OAuthToken(defTok));
-    }
-
-    /**
-     * Unit test of methods {@link OAuthToken#equals} and {@link OAuthToken#hashCode}.
-     */
-    @Test
-    void testEqualsContract() {
-        TestUtils.assumeWorkingEqualsVerifier();
-        EqualsVerifier.forClass(OAuthToken.class).usingGetClass().verify();
-    }
-}
Index: core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java b/core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java
deleted file mode 100644
--- a/core/test/unit/org/openstreetmap/josm/data/oauth/SignpostAdaptersTest.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,99 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.data.oauth;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.data.oauth.SignpostAdapters.HttpRequest;
-import org.openstreetmap.josm.data.oauth.SignpostAdapters.HttpResponse;
-import org.openstreetmap.josm.data.oauth.SignpostAdapters.OAuthConsumer;
-import org.openstreetmap.josm.testutils.annotations.HTTPS;
-import org.openstreetmap.josm.tools.HttpClient;
-
-import net.trajano.commons.testing.UtilityClassTestUtil;
-
-/**
- * Unit tests for class {@link SignpostAdapters}.
- */
-@HTTPS
-class SignpostAdaptersTest {
-
-    private static HttpClient newClient() throws MalformedURLException {
-        return HttpClient.create(new URL("https://www.openstreetmap.org"));
-    }
-
-    /**
-     * Tests that {@code SignpostAdapters} satisfies utility class criteria.
-     * @throws ReflectiveOperationException if an error occurs
-     */
-    @Test
-    void testUtilityClass() throws ReflectiveOperationException {
-        UtilityClassTestUtil.assertUtilityClassWellDefined(SignpostAdapters.class);
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.OAuthConsumer#wrap}.
-     * @throws MalformedURLException never
-     */
-    @Test
-    void testOAuthConsumerWrap() throws MalformedURLException {
-        assertNotNull(new OAuthConsumer("", "").wrap(newClient()));
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpRequest#getMessagePayload}.
-     * @throws IOException never
-     */
-    @Test
-    void testHttpRequestGetMessagePayload() throws IOException {
-        assertNull(new HttpRequest(newClient()).getMessagePayload());
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpRequest#setRequestUrl}.
-     */
-    @Test
-    void testHttpRequestSetRequestUrl() {
-        assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).setRequestUrl(null));
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpRequest#getAllHeaders}.
-     */
-    @Test
-    void testHttpRequestGetAllHeaders() {
-        assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).getAllHeaders());
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpRequest#unwrap}.
-     */
-    @Test
-    void testHttpRequestUnwrap() {
-        assertThrows(IllegalStateException.class, () -> new HttpRequest(newClient()).unwrap());
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpResponse#getReasonPhrase()}.
-     * @throws Exception never
-     */
-    @Test
-    void testHttpResponseGetReasonPhrase() throws Exception {
-        assertEquals("OK", new HttpResponse(new HttpRequest(newClient()).request.connect()).getReasonPhrase());
-    }
-
-    /**
-     * Unit test of method {@link SignpostAdapters.HttpResponse#unwrap}.
-     */
-    @Test
-    void testHttpResponseUnwrap() {
-        assertThrows(IllegalStateException.class, () -> new HttpResponse(new HttpRequest(newClient()).request.connect()).unwrap());
-    }
-}
Index: core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java b/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java
--- a/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java	(date 1707938577690)
@@ -8,17 +8,16 @@
 
 import java.awt.GraphicsEnvironment;
 import java.net.URL;
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
-import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 import org.openstreetmap.josm.testutils.annotations.OsmApi;
 import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
@@ -62,14 +61,6 @@
         }
     }
 
-    /**
-     * These tests were written with {@link org.openstreetmap.josm.data.oauth.OAuthVersion#OAuth10a} as the default auth method.
-     */
-    @BeforeEach
-    void setup() {
-        Config.getPref().put("osm-server.auth-method", "oauth");
-    }
-
     /**
      * Test of {@link DownloadOpenChangesetsTask} class when anonymous.
      */
@@ -79,14 +70,12 @@
         if (GraphicsEnvironment.isHeadless()) {
             new WindowMocker();
         }
-        final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
-        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
-            Collections.singletonMap(
-                "<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
+        final Map<String, Object> optionPaneMock = new HashMap<>(2);
+        optionPaneMock.put("<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
                 + "your identity.<br>You have either chosen to work anonymously or you are not "
-                + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION
-            )
-        );
+                + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION);
+        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
+        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
 
         DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
         assertNull(task.getChangesets());
@@ -95,12 +84,14 @@
         task.run();
         assertNull(task.getChangesets());
 
-        assertEquals(1, jopsMocker.getInvocationLog().size());
-        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
+        assertEquals(2, jopsMocker.getInvocationLog().size());
+        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
         assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
         assertEquals("Missing user identity", invocationLogEntry[2]);
 
-        assertTrue(oaWizardMocker.called);
+        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
+        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
+        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
     }
 
     /**
@@ -112,10 +103,10 @@
         if (GraphicsEnvironment.isHeadless()) {
             new WindowMocker();
         }
-        final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
-        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
-            Collections.singletonMap("There are no open changesets", JOptionPane.OK_OPTION)
-        );
+        final Map<String, Object> optionPaneMock = new HashMap<>(2);
+        optionPaneMock.put("There are no open changesets", JOptionPane.OK_OPTION);
+        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
+        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
 
         DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
         UserIdentityManager.getInstance().setPartiallyIdentified(System.getProperty("osm.username", "josm_test"));
@@ -123,11 +114,13 @@
         task.run();
         assertNotNull(task.getChangesets());
 
-        assertEquals(1, jopsMocker.getInvocationLog().size());
-        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
+        assertEquals(2, jopsMocker.getInvocationLog().size());
+        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
         assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
         assertEquals("No open changesets", invocationLogEntry[2]);
 
-        assertTrue(oaWizardMocker.called);
+        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
+        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
+        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
     }
 }
Index: core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java
--- a/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java	(date 1707933063759)
@@ -1,13 +1,14 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.oauth;
 
-import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
-import org.junit.jupiter.api.Test;
-
 /**
  * Unit tests of {@link FullyAutomaticAuthorizationUI} class.
  */
@@ -16,8 +17,9 @@
     /**
      * Unit test of {@link FullyAutomaticAuthorizationUI#FullyAutomaticAuthorizationUI}.
      */
-    @Test
-    void testFullyAutomaticAuthorizationUI() {
-        assertNotNull(new FullyAutomaticAuthorizationUI("", MainApplication.worker));
+    @ParameterizedTest
+    @EnumSource(OAuthVersion.class)
+    void testFullyAutomaticAuthorizationUI(OAuthVersion version) {
+        assertDoesNotThrow(() -> new FullyAutomaticAuthorizationUI("", MainApplication.worker, version));
     }
 }
Index: core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java
--- a/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java	(date 1707933063860)
@@ -1,9 +1,10 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.oauth;
 
-import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 
 import org.junit.jupiter.api.Test;
+import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
@@ -17,6 +18,6 @@
      */
     @Test
     void testManualAuthorizationUI() {
-        assertNotNull(new ManualAuthorizationUI("", MainApplication.worker));
+        assertDoesNotThrow(() -> new ManualAuthorizationUI("", MainApplication.worker, OAuthVersion.OAuth20));
     }
 }
Index: core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java
deleted file mode 100644
--- a/core/test/unit/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClientTest.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,116 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.URI;
-import java.util.Collections;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-import org.openstreetmap.josm.data.oauth.OAuthParameters;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
-import org.openstreetmap.josm.io.OsmTransferCanceledException;
-import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
-import org.openstreetmap.josm.testutils.annotations.BasicWiremock;
-import org.openstreetmap.josm.testutils.annotations.HTTP;
-
-import com.github.tomakehurst.wiremock.WireMockServer;
-
-/**
- * Unit tests of {@link OsmOAuthAuthorizationClient} class.
- */
-@Timeout(20)
-@BasicWiremock
-// Needed for OAuthParameters
-@BasicPreferences
-@HTTP
-class OsmOAuthAuthorizationClientTest {
-    /**
-     * HTTP mock.
-     */
-    @BasicWiremock
-    WireMockServer wireMockServer;
-
-    /**
-     * Unit test of {@link OsmOAuthAuthorizationClient}.
-     * @throws OsmOAuthAuthorizationException if OAuth authorization error occurs
-     * @throws OsmTransferCanceledException  if OSM transfer error occurs
-     */
-    @Test
-    void testOsmOAuthAuthorizationClient() throws OsmTransferCanceledException, OsmOAuthAuthorizationException {
-        // request token
-        wireMockServer.stubFor(get(urlEqualTo("/oauth/request_token"))
-                .willReturn(aResponse().withStatus(200).withBody(String.join("&",
-                        "oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR",
-                        "oauth_token_secret=nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB"))));
-        OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(OAuthParameters.createDefault(
-                wireMockServer.url("/api")));
-
-        OAuthToken requestToken = client.getRequestToken(null);
-        assertEquals("entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR", requestToken.getKey(), "requestToken.key");
-        assertEquals("nsBD2Hr5lLGDUeNoh3SnLaGsUV1TiPYM4qUr7tPB", requestToken.getSecret(), "requestToken.secret");
-        String url = client.getAuthoriseUrl(requestToken);
-        assertEquals(wireMockServer.url("/oauth/authorize?oauth_token=entxUGuwRKV6KyVDF0OWScdGhbqXGMGmosXuiChR"), url, "url");
-
-        // access token
-        wireMockServer.stubFor(get(urlEqualTo("/oauth/access_token"))
-                .willReturn(aResponse().withStatus(200).withBody(String.join("&",
-                        "oauth_token=eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX",
-                        "oauth_token_secret=nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB"))));
-
-        OAuthToken accessToken = client.getAccessToken(null);
-        assertEquals("eGMGmosXuiChRntxUGuwRKV6KyVDF0OWScdGhbqX", accessToken.getKey(), "accessToken.key");
-        assertEquals("nsBUeNor7tPh3SHr5lLaGsGDUD2PYMV1TinL4qUB", accessToken.getSecret(), "accessToken.secret");
-    }
-
-    /**
-     * Unit test for correct cookie handling when logging in to the OSM website.
-     *
-     * https://josm.openstreetmap.de/ticket/12584
-     * @throws Exception if any error occurs
-     */
-    @Test
-    void testCookieHandlingMock() throws Exception {
-        wireMockServer.stubFor(get(urlEqualTo("/login?cookie_test=true"))
-                .willReturn(aResponse()
-                        .withStatus(200)
-                        .withHeader("Set-Cookie", "_osm_session=7fe8e2ea36c6b803cb902301b28e0a; path=/; HttpOnly; SameSite=Lax")
-                .withBody("<input type=\"hidden\" " +
-                        "name=\"authenticity_token\" " +
-                        "value=\"fzp6CWJhp6Vns09re3s2Tw==\" />")));
-        final OAuthParameters parameters = OAuthParameters.createDefault(wireMockServer.url("/api"));
-        final OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(parameters);
-        final OsmOAuthAuthorizationClient.SessionId sessionId = client.fetchOsmWebsiteSessionId();
-        assertNotNull(sessionId);
-        assertEquals("7fe8e2ea36c6b803cb902301b28e0a", sessionId.id, "sessionId.id");
-        assertEquals("fzp6CWJhp6Vns09re3s2Tw==", sessionId.token, "sessionId.token");
-        assertNull(sessionId.userName, "sessionId.userName");
-    }
-
-    /**
-     * Unit test for correct cookie handling when logging in to the OSM website.
-     *
-     * https://josm.openstreetmap.de/ticket/12584
-     * @throws Exception if any error occurs
-     */
-    @Test
-    void testCookieHandlingCookieManager() throws Exception {
-        // emulate Java Web Start behaviour
-        // see https://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/accessingCookies.html
-        final OAuthParameters parameters = OAuthParameters.createDefault();
-        final OsmOAuthAuthorizationClient client = new OsmOAuthAuthorizationClient(parameters);
-        final CookieManager cm = new CookieManager();
-        cm.put(new URI(parameters.getOsmLoginUrl()),
-                Collections.singletonMap("Cookie", Collections.singletonList("_osm_session=" + String.valueOf(Math.PI).substring(2))));
-        CookieHandler.setDefault(cm);
-        assertNotNull(client.fetchOsmWebsiteSessionId());
-    }
-}
Index: core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java b/core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java
deleted file mode 100644
--- a/core/test/unit/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUITest.java	(revision 18985)
+++ /dev/null	(revision 18985)
@@ -1,22 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.gui.oauth;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.gui.MainApplication;
-import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
-
-/**
- * Unit tests of {@link SemiAutomaticAuthorizationUI} class.
- */
-@BasicPreferences
-class SemiAutomaticAuthorizationUITest {
-    /**
-     * Unit test of {@link SemiAutomaticAuthorizationUI#SemiAutomaticAuthorizationUI}.
-     */
-    @Test
-    void testSemiAutomaticAuthorizationUI() {
-        assertNotNull(new SemiAutomaticAuthorizationUI("", MainApplication.worker));
-    }
-}
Index: core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java b/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java
--- a/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java	(date 1707938577696)
@@ -20,12 +20,10 @@
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
-import org.openstreetmap.josm.data.oauth.IOAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuth20Exception;
 import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
@@ -46,7 +44,7 @@
         }
         List<Exception> exceptionList = new ArrayList<>();
         try {
-            CredentialsManager.getInstance().storeOAuthAccessToken(null);
+            CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
         } catch (CredentialsAgentException exception) {
             exceptionList.add(exception);
         }
@@ -60,7 +58,7 @@
     }
 
     @ParameterizedTest
-    @EnumSource(value = OAuthVersion.class, names = {"OAuth10a", "OAuth20"})
+    @EnumSource(value = OAuthVersion.class, names = "OAuth20")
     void testRemoveToken(OAuthVersion oAuthVersion) throws ReflectiveOperationException, CredentialsAgentException, OAuth20Exception {
         final OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel(oAuthVersion);
         final Field pnlNotYetAuthorised = OAuthAuthenticationPreferencesPanel.class.getDeclaredField("pnlNotYetAuthorised");
@@ -75,8 +73,8 @@
         panel.initFromPreferences();
         assertSame(pnlAlreadyAuthorised.get(panel), holder.getComponent(0), "Authentication should now be set");
         assertNotNull(getAuthorization(oAuthVersion));
-        final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(6);
-        final JButton action = (JButton) buttons.getComponent(oAuthVersion == OAuthVersion.OAuth10a ? 2 : 1);
+        final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(5);
+        final JButton action = (JButton) buttons.getComponent(2);
         assertEquals(tr("Remove token"), action.getText(), "The selected button should be for removing the token");
         action.getAction().actionPerformed(null);
         panel.saveToPreferences(); // Save to preferences should make the removal permanent
@@ -96,9 +94,6 @@
      */
     private static void addAuthorization(OAuthVersion oAuthVersion) throws CredentialsAgentException, OAuth20Exception {
         switch (oAuthVersion) {
-            case OAuth10a:
-                CredentialsManager.getInstance().storeOAuthAccessToken(new OAuthToken("fake_key", "fake_secret"));
-                break;
             case OAuth20:
             case OAuth21:
                 CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getHost(),
@@ -116,17 +111,9 @@
      */
     private static Object getAuthorization(OAuthVersion oAuthVersion) {
         OAuthAccessTokenHolder.getInstance().clear();
-        OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getHost(), (IOAuthToken) null);
+        OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
         OAuthAccessTokenHolder.getInstance().init(CredentialsManager.getInstance());
         // Ensure that we are not saving authorization data
-        switch (oAuthVersion) {
-            case OAuth10a:
-                return OAuthAccessTokenHolder.getInstance().getAccessToken();
-            case OAuth20:
-            case OAuth21:
-                return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getHost(), oAuthVersion);
-            default:
-                throw new AssertionError("OAuth version not understood");
-        }
+        return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getServerUrl(), oAuthVersion);
     }
 }
Index: core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java b/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java
--- a/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java	(date 1707933064663)
@@ -18,7 +18,6 @@
 import org.openstreetmap.josm.data.oauth.OAuth20Exception;
 import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
@@ -75,18 +74,6 @@
         assertNull(agent.lookup(null, null));
     }
 
-    @Test
-    default void testLookUpAndStoreOAuth10() throws CredentialsAgentException {
-        final T agent = createAgent();
-        assertNull(agent.lookupOAuthAccessToken());
-        final OAuthToken token = new OAuthToken("foo", "bar");
-        agent.storeOAuthAccessToken(token);
-        final OAuthToken actual = agent.lookupOAuthAccessToken();
-        assertEquals(token, actual);
-        agent.storeOAuthAccessToken(null);
-        assertNull(agent.lookupOAuthAccessToken());
-    }
-
     @ParameterizedTest
     @MethodSource("getHosts")
     default void testLookupAndStoreOAuthTokens(final String host) throws CredentialsAgentException, OAuth20Exception {
Index: core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java b/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java
--- a/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java	(date 1707933064779)
@@ -64,6 +64,9 @@
         public void afterEach(ExtensionContext context) throws Exception {
             if (AnnotationSupport.isAnnotated(context.getElement(), BasicPreferences.class)) {
                 this.afterAll(context);
+                if (AnnotationSupport.isAnnotated(context.getTestClass(), BasicPreferences.class)) {
+                    this.beforeAll(context);
+                }
             }
         }
 
Index: core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java b/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java
--- a/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java	(date 1707938902568)
@@ -9,7 +9,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.net.Authenticator;
-import java.net.PasswordAuthentication;
 
 import org.junit.jupiter.api.extension.AfterEachCallback;
 import org.junit.jupiter.api.extension.BeforeAllCallback;
@@ -18,6 +17,9 @@
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.data.UserIdentityManager;
+import org.openstreetmap.josm.data.oauth.OAuth20Token;
+import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
+import org.openstreetmap.josm.data.oauth.OAuthParameters;
 import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Utils;
@@ -50,17 +52,20 @@
         @Override
         public void beforeEach(ExtensionContext context) throws Exception {
             assumeTrue(TestUtils.areCredentialsProvided(),
-                    "OSM DEV API credentials not provided. Please define them with -Dosm.username and -Dosm.password");
-            final String username = Utils.getSystemProperty("osm.username");
-            final String password = Utils.getSystemProperty("osm.password");
-            assumeTrue(username != null && !username.isEmpty(), "Please add -Dosm.username for the OSM DEV API");
-            assumeTrue(password != null && !password.isEmpty(), "Please add -Dosm.password for the OSM DEV API");
-            Config.getPref().put("osm-server.auth-method", "basic");
+                    "OSM DEV API credentials not provided. Please define them with -Dosm.oauth2");
+            final String oauth2 = Utils.getSystemProperty("osm.oauth2");
+            Config.getPref().put("osm-server.auth-method", "oauth20");
 
             // don't use atomic upload, the test API server can't cope with large diff uploads
             Config.getPref().putBoolean("osm-server.atomic-upload", false);
-            CredentialsManager.getInstance().store(Authenticator.RequestorType.SERVER, org.openstreetmap.josm.io.OsmApi.getOsmApi().getHost(),
-                    new PasswordAuthentication(username, password.toCharArray()));
+            final String serverUrl = org.openstreetmap.josm.io.OsmApi.getOsmApi().getServerUrl();
+            final OAuth20Token token = new OAuth20Token(OAuthParameters.createDefault(),
+                    "{\"token_type\":\"bearer\", \"access_token\": \"" + oauth2 + "\"}");
+            OAuthAccessTokenHolder.getInstance().setAccessToken(serverUrl, token);
+            CredentialsManager.getInstance().storeOAuthAccessToken(serverUrl, token);
+            if (!UserIdentityManager.getInstance().isFullyIdentified()) {
+                UserIdentityManager.getInstance().initFromOAuth();
+            }
         }
     }
 }
Index: core/test/unit/org/openstreetmap/josm/TestUtils.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/test/unit/org/openstreetmap/josm/TestUtils.java b/core/test/unit/org/openstreetmap/josm/TestUtils.java
--- a/core/test/unit/org/openstreetmap/josm/TestUtils.java	(revision 18985)
+++ b/core/test/unit/org/openstreetmap/josm/TestUtils.java	(date 1707933073342)
@@ -658,10 +658,10 @@
 
     /**
      * Determines if OSM DEV_API credential have been provided. Required for functional tests.
-     * @return {@code true} if {@code osm.username} and {@code osm.password} have been defined on the command line
+     * @return {@code true} if {@code osm.oauth2} have been defined on the command line
      */
     public static boolean areCredentialsProvided() {
-        return Utils.getSystemProperty("osm.username") != null && Utils.getSystemProperty("osm.password") != null;
+        return Utils.getSystemProperty("osm.oauth2") != null;
     }
 
     /**
Index: core/ivy.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/ivy.xml b/core/ivy.xml
--- a/core/ivy.xml	(revision 18985)
+++ b/core/ivy.xml	(date 1707933073447)
@@ -37,7 +37,6 @@
         <dependency conf="api->default" org="com.drewnoakes" name="metadata-extractor" rev="2.19.0" transitive="false"/>
         <dependency conf="api->default" org="com.formdev" name="svgSalamander" rev="1.1.4"/>
         <dependency conf="api->default" org="ch.poole" name="OpeningHoursParser" rev="0.28.1"/>
-        <dependency conf="api->default" org="oauth.signpost" name="signpost-core" rev="2.1.1"/>
         <!-- Don't forget to update org.openstreetmap.josm.tools.Tag2Link#PREF_SOURCE -->
         <dependency conf="api->default" org="org.webjars.npm" name="tag2link" rev="2024.2.8"/>
         <!-- sources->sources -->
@@ -56,7 +55,6 @@
         <dependency conf="sources->sources" org="com.drewnoakes" name="metadata-extractor" rev="2.19.0" transitive="false"/>
         <dependency conf="sources->sources" org="com.formdev" name="svgSalamander" rev="1.1.4"/>
         <dependency conf="sources->sources" org="ch.poole" name="OpeningHoursParser" rev="0.28.1"/>
-        <dependency conf="sources->sources" org="oauth.signpost" name="signpost-core" rev="2.1.1"/>
         <dependency conf="sources->default" org="org.webjars.npm" name="tag2link" rev="2024.2.8"/><!-- sources->default sic! (tag2link-sources.jar is empty, see #19335) -->
         <!-- commonslang->default -->
         <dependency conf="commonslang->default" org="org.apache.commons" name="commons-lang3" rev="3.14.0"/>
Index: plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java
--- a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java	(revision 36208)
+++ b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/InitializationWizard.java	(date 1707933073641)
@@ -40,12 +40,10 @@
 import javax.swing.border.EtchedBorder;
 
 import org.netbeans.spi.keyring.KeyringProvider;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.io.DefaultProxySelector;
-import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
 import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -55,7 +53,7 @@
 
 public class InitializationWizard extends JDialog {
 
-    protected boolean canceled = false;
+    protected boolean canceled;
     protected JButton btnCancel, btnBack, btnNext;
     protected Action nextAction, finishAction;
     protected JPanel cardPanel;
@@ -66,7 +64,8 @@
     private CardLayout cardLayout;
     
     public InitializationWizard() {
-        super(JOptionPane.getFrameForComponent(MainApplication.getMainFrame()), tr("Native password manager plugin"), ModalityType.DOCUMENT_MODAL);
+        super(JOptionPane.getFrameForComponent(MainApplication.getMainFrame()),
+                tr("Native password manager plugin"), ModalityType.DOCUMENT_MODAL);
         build();
         NPMType npm = detectNativePasswordManager();
         WizardPanel firstPanel;
@@ -145,8 +144,8 @@
         /* The action to execute, when the user finall hits 'OK' and not 'Cancel' */
         void onOkAction();
     }
-    
-    abstract private static class AbstractWizardPanel implements WizardPanel {
+
+    private abstract static class AbstractWizardPanel implements WizardPanel {
         
         /**
          * Put a logo to the left, as is customary for wizard dialogs
@@ -174,7 +173,7 @@
             return getClass().getCanonicalName();
         }
 
-        abstract protected JPanel getContentPanel();
+        protected abstract JPanel getContentPanel();
     }
     
     private static class NothingFoundPanel extends AbstractWizardPanel {
@@ -228,8 +227,8 @@
     
     private static class SelectionPanel extends AbstractWizardPanel implements ActionListener {
         
-        private NPMType type;
-        private InitializationWizard wizard;
+        private final NPMType type;
+        private final InitializationWizard wizard;
         
         private JRadioButton rbManage, rbPlain;
                 
@@ -349,27 +348,13 @@
         public void onOkAction() {
             
             CredentialsManager cm = CredentialsManager.getInstance();
-            
-            String server_username = Config.getPref().get("osm-server.username", null);
-            String server_password = Config.getPref().get("osm-server.password", null);
-            if (server_username != null || server_password != null) {
-                try {
-                    cm.store(RequestorType.SERVER, OsmApi.getOsmApi().getHost(), new PasswordAuthentication(string(server_username), toCharArray(server_password)));
-                    if (rbClear.isSelected()) {
-                        Config.getPref().put("osm-server.username", null);
-                        Config.getPref().put("osm-server.password", null);
-                    }
-                } catch (CredentialsAgentException ex) {
-                    Logging.error(ex);
-                }
-            }
-            
-            String proxy_username = Config.getPref().get(DefaultProxySelector.PROXY_USER, null);
-            String proxy_password = Config.getPref().get(DefaultProxySelector.PROXY_PASS, null);
-            String proxy_host = Config.getPref().get(DefaultProxySelector.PROXY_HTTP_HOST, null);
-            if (proxy_username != null || proxy_password != null) {
+
+            String proxyUsername = Config.getPref().get(DefaultProxySelector.PROXY_USER, null);
+            String proxyPassword = Config.getPref().get(DefaultProxySelector.PROXY_PASS, null);
+            String proxyHost = Config.getPref().get(DefaultProxySelector.PROXY_HTTP_HOST, null);
+            if (proxyUsername != null || proxyPassword != null) {
                 try {
-                    cm.store(RequestorType.PROXY, proxy_host, new PasswordAuthentication(string(proxy_username), toCharArray(proxy_password)));
+                    cm.store(RequestorType.PROXY, proxyHost, new PasswordAuthentication(string(proxyUsername), toCharArray(proxyPassword)));
                     if (rbClear.isSelected()) {
                         Config.getPref().put(DefaultProxySelector.PROXY_USER, null);
                         Config.getPref().put(DefaultProxySelector.PROXY_PASS, null);
@@ -378,24 +363,10 @@
                     Logging.error(ex);
                 }
             }
-            
-            String oauth_key = Config.getPref().get("oauth.access-token.key", null);
-            String oauth_secret = Config.getPref().get("oauth.access-token.secret", null);
-            if (oauth_key != null || oauth_secret != null) {
-                try {
-                    cm.storeOAuthAccessToken(new OAuthToken(string(oauth_key), string(oauth_secret)));
-                    if (rbClear.isSelected()) {
-                        Config.getPref().put("oauth.access-token.key", null);
-                        Config.getPref().put("oauth.access-token.secret", null);
-                    }
-                } catch (CredentialsAgentException ex) {
-                    Logging.error(ex);
-                }
-            }
         }
     }
 
-    private final static String NPM = "Native Password Manager Plugin: ";
+    private static final String NPM = "Native Password Manager Plugin: ";
 
     private static NPMType detectNativePasswordManager() {
         NPMType[] potentialManagers;
@@ -444,7 +415,7 @@
                             new Dimension(600,400)
                     )
             ).applySafe(this);
-        } else if (!visible && isShowing()){
+        } else if (isShowing()){
             new WindowGeometry(this).remember(getClass().getName() + ".geometry");
         }
         super.setVisible(visible);
@@ -492,7 +463,8 @@
         @Override
         public void actionPerformed(ActionEvent evt) {
             if (panelIndex <= 0)
-                throw new RuntimeException();
+                // Java 9 will let us pass the panelIndex by itself
+                throw new IndexOutOfBoundsException("Index out of range: " + panelIndex);
             panelIndex--;
             cardLayout.show(cardPanel, panels.get(panelIndex).getId());
             updateButtons();
Index: plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java
--- a/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java	(revision 36208)
+++ b/plugins/native-password-manager/src/org/openstreetmap/josm/plugins/npm/NPMCredentialsAgent.java	(date 1707933073701)
@@ -24,7 +24,6 @@
 import org.openstreetmap.josm.data.oauth.OAuth20Exception;
 import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
 import org.openstreetmap.josm.data.oauth.OAuth20Token;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.data.oauth.OAuthVersion;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.io.DefaultProxySelector;
@@ -51,7 +50,7 @@
      * In contrast, this cache avoids read request the backend in general.
      */
     private final Map<RequestorType, PasswordAuthentication> credentialsCache = new EnumMap<>(RequestorType.class);
-    private OAuthToken oauthCache;
+
 
     /**
      * Create a new {@link NPMCredentialsAgent}
@@ -188,16 +187,6 @@
         }
     }
 
-    @Override
-    public OAuthToken lookupOAuthAccessToken() {
-        if (oauthCache != null)
-            return oauthCache;
-        String prolog = getOAuthDescriptor();
-        char[] key = getProvider().read(prolog+".key");
-        char[] secret = getProvider().read(prolog+".secret");
-        return new OAuthToken(stringNotNull(key), stringNotNull(secret));
-    }
-
     @Override
     public IOAuthToken lookupOAuthAccessToken(String host) throws CredentialsAgentException {
         String prolog = getOAuthDescriptor();
@@ -221,28 +210,6 @@
         return null;
     }
 
-    @Override
-    public void storeOAuthAccessToken(OAuthToken oat) {
-        String key, secret;
-        if (oat == null) {
-            key = null;
-            secret = null;
-        } else {
-            key = oat.getKey();
-            secret = oat.getSecret();
-        }
-        String prolog = getOAuthDescriptor();
-        if (key == null || key.isEmpty() || secret == null || secret.isEmpty()) {
-            getProvider().delete(prolog+".key");
-            getProvider().delete(prolog+".secret");
-            oauthCache = null;
-        } else {
-            getProvider().save(prolog+".key", key.toCharArray(), tr("JOSM/OAuth/OSM API/Key"));
-            getProvider().save(prolog+".secret", secret.toCharArray(), tr("JOSM/OAuth/OSM API/Secret"));
-            oauthCache = new OAuthToken(key, secret);
-        }
-    }
-
     @Override
     public void storeOAuthAccessToken(String host, IOAuthToken accessToken) {
         String prolog = getOAuthDescriptor();
Index: plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java b/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java
--- a/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java	(revision 36208)
+++ b/plugins/sds/src/org/openstreetmap/hot/sds/SdsCredentialAgent.java	(date 1707933073802)
@@ -12,7 +12,6 @@
 import javax.swing.text.html.HTMLEditorKit;
 
 import org.openstreetmap.josm.data.oauth.IOAuthToken;
-import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.gui.io.CredentialDialog;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.io.DefaultProxySelector;
@@ -82,21 +81,6 @@
         }
     }
 
-    /**
-     * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
-     * Access Token is currently managed by this CredentialManager.
-     *
-     * @return the current OAuth Access Token to access the OSM server.
-     */
-    @Override
-    public OAuthToken lookupOAuthAccessToken() {
-        String accessTokenKey = Config.getPref().get("oauth.access-token.key", null);
-        String accessTokenSecret = Config.getPref().get("oauth.access-token.secret", null);
-        if (accessTokenKey == null && accessTokenSecret == null)
-            return null;
-        return new OAuthToken(accessTokenKey, accessTokenSecret);
-    }
-
     @Override
     public IOAuthToken lookupOAuthAccessToken(String host) {
         throw new UnsupportedOperationException("SDS does not support OAuth tokens");
@@ -126,11 +110,6 @@
         return tr("Save user and password (unencrypted)");
     }
 
-    @Override
-    public void storeOAuthAccessToken(OAuthToken accessToken) {
-        // no-op
-    }
-
     @Override
     public void storeOAuthAccessToken(String host, IOAuthToken accessToken) {
         throw new UnsupportedOperationException("SDS does not support OAuth tokens");
