Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 12992)
@@ -9,4 +9,5 @@
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.net.Authenticator.RequestorType;
 import java.net.ConnectException;
 import java.net.HttpURLConnection;
@@ -33,4 +34,5 @@
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.Capabilities.CapabilitiesParser;
+import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -704,8 +706,9 @@
                     else
                         throw new OsmApiException(retCode, errorHeader, errorBody);
+                case HttpURLConnection.HTTP_UNAUTHORIZED:
                 case HttpURLConnection.HTTP_FORBIDDEN:
-                    OsmApiException e = new OsmApiException(retCode, errorHeader, errorBody);
-                    e.setAccessedUrl(activeConnection.getURL().toString());
-                    throw e;
+                    CredentialsManager.getInstance().purgeCredentialsCache(RequestorType.SERVER);
+                    throw new OsmApiException(retCode, errorHeader, errorBody, activeConnection.getURL().toString(),
+                            doAuthenticate ? retrieveBasicAuthorizationLogin(client) : null);
                 default:
                     throw new OsmApiException(retCode, errorHeader, errorBody);
Index: trunk/src/org/openstreetmap/josm/io/OsmApiException.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 12992)
@@ -15,4 +15,5 @@
     private String errorBody;
     private String accessedUrl;
+    private String login;
 
     /**
@@ -23,11 +24,26 @@
      * @param errorBody The error body, as transmitted in the HTTP response body
      * @param accessedUrl The complete URL accessed when this error occured
-     * @since 5584
-     */
-    public OsmApiException(int responseCode, String errorHeader, String errorBody, String accessedUrl) {
+     * @param login the login used to connect to OSM API (can be null)
+     * @since 12992
+     */
+    public OsmApiException(int responseCode, String errorHeader, String errorBody, String accessedUrl, String login) {
         this.responseCode = responseCode;
         this.errorHeader = errorHeader;
         this.errorBody = errorBody;
         this.accessedUrl = accessedUrl;
+        this.login = login;
+    }
+
+    /**
+     * Constructs an {@code OsmApiException} with the specified response code, error header and error body
+     * @param responseCode The HTTP response code replied by the OSM server.
+     * See {@link java.net.HttpURLConnection HttpURLConnection} for predefined HTTP response code values
+     * @param errorHeader The error header, as transmitted in the {@code Error} field of the HTTP response header
+     * @param errorBody The error body, as transmitted in the HTTP response body
+     * @param accessedUrl The complete URL accessed when this error occured
+     * @since 5584
+     */
+    public OsmApiException(int responseCode, String errorHeader, String errorBody, String accessedUrl) {
+        this(responseCode, errorHeader, errorBody, accessedUrl, null);
     }
 
@@ -199,3 +215,21 @@
         return accessedUrl;
     }
+
+    /**
+     * Sets the login used to connect to OSM API.
+     * @param login the login used to connect to OSM API
+     * @since 12992
+     */
+    public void setLogin(String login) {
+        this.login = login;
+    }
+
+    /**
+     * Replies the login used to connect to OSM API.
+     * @return the login used to connect to OSM API, or {@code null}
+     * @since 12992
+     */
+    public String getLogin() {
+        return login;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 12992)
@@ -31,4 +31,7 @@
  */
 public class OsmConnection {
+
+    private static final String BASIC_AUTH = "Basic ";
+
     protected boolean cancel;
     protected HttpClient activeConnection;
@@ -75,4 +78,28 @@
 
     /**
+     * Retrieves login from basic authentication header, if set.
+     *
+     * @param con the connection
+     * @return login from basic authentication header, or {@code null}
+     * @throws OsmTransferException if something went wrong. Check for nested exceptions
+     * @since 12992
+     */
+    protected String retrieveBasicAuthorizationLogin(HttpClient con) throws OsmTransferException {
+        String auth = con.getRequestHeader("Authorization");
+        if (auth != null && auth.startsWith(BASIC_AUTH)) {
+            try {
+                String[] token = new String(Base64.getDecoder().decode(auth.substring(BASIC_AUTH.length())),
+                        StandardCharsets.UTF_8).split(":");
+                if (token.length == 2) {
+                    return token[0];
+                }
+            } catch (IllegalArgumentException e) {
+                Logging.error(e);
+            }
+        }
+        return null;
+    }
+
+    /**
      * Adds an authentication header for basic authentication
      *
@@ -98,5 +125,5 @@
                 String password = response.getPassword() == null ? "" : String.valueOf(response.getPassword());
                 String token = username + ':' + password;
-                con.setHeader("Authorization", "Basic "+Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8)));
+                con.setHeader("Authorization", BASIC_AUTH + Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8)));
             }
         }
Index: trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 12992)
@@ -6,4 +6,5 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.Authenticator.RequestorType;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
@@ -195,6 +196,8 @@
             }
             try {
-                if (response.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
+                if (response.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
+                    CredentialsManager.getInstance().purgeCredentialsCache(RequestorType.SERVER);
                     throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED, null, null);
+                }
 
                 if (response.getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH)
Index: trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/auth/AbstractCredentialsAgent.java	(revision 12992)
@@ -62,8 +62,6 @@
 
         /*
-         * Last request was successful and there was no credentials stored
-         * in file (or only the username is stored).
-         * -> Try to recall credentials that have been entered
-         * manually in this session.
+         * Last request was successful and there was no credentials stored in file (or only the username is stored).
+         * -> Try to recall credentials that have been entered manually in this session.
          */
         if (!noSuccessWithLastResponse && memoryCredentialsCache.containsKey(requestorType) &&
@@ -89,16 +87,10 @@
                         response.getPassword()
                 ));
-            /*
-             * User decides not to save credentials to file. Keep it
-             * in memory so we don't have to ask over and over again.
-             */
             } else {
-                PasswordAuthentication pa = new PasswordAuthentication(response.getUsername(), response.getPassword());
-                memoryCredentialsCache.put(requestorType, pa);
+                // User decides not to save credentials to file. Keep it in memory so we don't have to ask over and over again.
+                memoryCredentialsCache.put(requestorType, new PasswordAuthentication(response.getUsername(), response.getPassword()));
             }
-        /*
-         * We got it from file.
-         */
         } else {
+            // We got it from file.
             response.setUsername(username);
             response.setPassword(password.toCharArray());
@@ -106,4 +98,9 @@
         }
         return response;
+    }
+
+    @Override
+    public final void purgeCredentialsCache(RequestorType requestorType) {
+        memoryCredentialsCache.remove(requestorType);
     }
 
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsAgent.java	(revision 12992)
@@ -74,4 +74,12 @@
 
     /**
+     * Purges the internal credentials cache for the given requestor type.
+     * @param requestorType the type of service.
+     * {@link RequestorType#SERVER} for the OSM API server, {@link RequestorType#PROXY} for a proxy server
+     * @since 12992
+     */
+    void purgeCredentialsCache(RequestorType requestorType);
+
+    /**
      * Provide a Panel that is shown below the API password / username fields
      * in the JOSM Preferences. (E.g. a warning that password is saved unencrypted.)
Index: trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 12937)
+++ trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 12992)
@@ -43,6 +43,13 @@
     private static CredentialsAgentFactory agentFactory;
 
+    /**
+     * Credentials agent factory.
+     */
     @FunctionalInterface
     public interface CredentialsAgentFactory {
+        /**
+         * Returns the credentials agent instance.
+         * @return the credentials agent instance
+         */
         CredentialsAgent getCredentialsAgent();
     }
@@ -148,3 +155,8 @@
         return delegate.getPreferencesDecorationPanel();
     }
+
+    @Override
+    public void purgeCredentialsCache(RequestorType requestorType) {
+        delegate.purgeCredentialsCache(requestorType);
+    }
 }
