Index: src/org/openstreetmap/josm/data/UserIdentityManager.java
===================================================================
--- src/org/openstreetmap/josm/data/UserIdentityManager.java	(revision 14961)
+++ src/org/openstreetmap/josm/data/UserIdentityManager.java	(working copy)
@@ -4,6 +4,10 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.osm.User;
@@ -78,16 +82,20 @@
                 instance.initFromPreferences();
             }
             Config.getPref().addPreferenceChangeListener(instance);
+            instance.populateAllUsers();
         }
         return instance;
     }
 
-    private String userName;
-    private UserInfo userInfo;
     private boolean accessTokenKeyChanged;
     private boolean accessTokenSecretChanged;
 
+    private String userName;
+    private UserInfo userInfo;
+    private LinkedHashMap<String, UserInfo> users;
+
     private UserIdentityManager() {
+        users = new LinkedHashMap<>();
     }
 
     /**
@@ -112,7 +120,7 @@
         if (trimmedUserName.isEmpty())
             throw new IllegalArgumentException(
                     MessageFormat.format("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
-        this.userName = trimmedUserName;
+        userName = trimmedUserName;
         userInfo = null;
     }
 
@@ -132,7 +140,7 @@
         if (trimmedUserName.isEmpty())
             throw new IllegalArgumentException(tr("Expected non-empty value for parameter ''{0}'', got ''{1}''", "userName", userName));
         CheckParameterUtil.ensureParameterNotNull(userInfo, "userInfo");
-        this.userName = trimmedUserName;
+        userName = trimmedUserName;
         this.userInfo = userInfo;
     }
 
@@ -238,6 +246,59 @@
     }
 
     /**
+     * Initializes the user identity manager from OAuth request of user details.
+     * @param oauth The {@code OAuthAccessTokenHolder} with the key and secret
+     * @see #initFromPreferences
+     * @since xxx
+     */
+    public void initFromOauth(OAuthAccessTokenHolder oauth) {
+        try {
+            OsmServerUserInfoReader osmServerReader = new OsmServerUserInfoReader();
+            UserInfo info = osmServerReader.fetchUserInfo(NullProgressMonitor.INSTANCE, oauth);
+            setFullyIdentified(info.getDisplayName(), info);
+        } catch (IllegalArgumentException | OsmTransferException e) {
+            Logging.error(e);
+        }
+    }
+
+
+    private List<List<String>> getDefaultOAuthList() {
+        List<String> variables = new ArrayList<>();
+        variables.add(Config.getPref().get("oauth.settings.access-token-url"));
+        variables.add(Config.getPref().get("oauth.access-token.key"));
+        variables.add(Config.getPref().get("oauth.access-token.secret"));
+        List<List<String>> rList = new ArrayList<>();
+        rList.add(variables);
+        return rList;
+    }
+    /**
+     * Populate the users
+     * @since xxx
+     */
+    public void populateAllUsers() {
+        if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() &&
+                !NetworkManager.isOffline(OnlineResource.OSM_API)) {
+            OAuthAccessTokenHolder oauth = new OAuthAccessTokenHolder();
+            List<List<String>> authList = Config.getPref().getListOfLists("oauth.all-tokens", getDefaultOAuthList());
+            for (List<String> list : authList) { // TODO fix
+                oauth.setAccessToken(list.get(1), list.get(2));
+                instance.initFromOauth(oauth);
+                users.put(getUserName(), getUserInfo());
+            }
+            try {
+                instance.initFromOAuth();
+            } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
+                Logging.error(e);
+                // Fall back to preferences if OAuth identification fails for any reason
+                instance.initFromPreferences();
+            }
+        } else {
+            instance.initFromPreferences();
+        }
+
+    }
+
+    /**
      * Replies true if the user with name <code>username</code> is the current user
      *
      * @param userName the user name
@@ -264,6 +325,14 @@
         }
     }
 
+    /**
+     * Get all information on all users that have logged in to JOSM
+     * @return A {@code HashMap} with username/UserInfo pairs.
+     */
+    public Map<String, UserInfo> getAllUserInformation() {
+        return users;
+    }
+
     /* ------------------------------------------------------------------- */
     /* interface PreferenceChangeListener                                  */
     /* ------------------------------------------------------------------- */
Index: src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java
===================================================================
--- src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java	(revision 14961)
+++ src/org/openstreetmap/josm/data/oauth/OAuthAccessTokenHolder.java	(working copy)
@@ -3,6 +3,7 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.io.auth.CredentialsAgent;
 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -16,6 +17,8 @@
 public class OAuthAccessTokenHolder {
     private static OAuthAccessTokenHolder instance;
 
+    private OsmApi osmApi = OsmApi.getOsmApi();
+
     /**
      * Replies the unique instance.
      * @return The unique instance of {@code OAuthAccessTokenHolder}
@@ -186,6 +189,23 @@
     }
 
     /**
+     * Set the API to use with the user
+     * @param serverUrl The URL for the OSM server
+     * @since xxx
+     */
+    public void setOsmApi(String serverUrl) {
+        osmApi = OsmApi.getOsmApi(serverUrl);
+    }
+
+    /**
+     * Get the osmApi for use with this oauth object
+     * @return The OsmApi to use
+     */
+    public OsmApi getOsmApi() {
+        return osmApi;
+    }
+
+    /**
      * Clears the content of this holder
      */
     public void clear() {
Index: src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java
===================================================================
--- src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java	(revision 14961)
+++ src/org/openstreetmap/josm/gui/io/UploadParameterSummaryPanel.java	(working copy)
@@ -10,12 +10,16 @@
 import java.util.Optional;
 
 import javax.swing.BorderFactory;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 
+import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
 import org.openstreetmap.josm.io.Capabilities;
 import org.openstreetmap.josm.io.OsmApi;
@@ -114,6 +118,15 @@
         return msg;
     }
 
+    protected JComboBox<String> buildPossibleUserBox() {
+        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
+        UserInfo user = UserIdentityManager.getInstance().getUserInfo();
+        String userName = user.getDisplayName() != null ? user.getDisplayName() : tr("Please login");
+        model.addElement(userName);
+        JComboBox<String> rBox = new JComboBox<>(model);
+        return rBox;
+    }
+
     protected void build() {
         jepMessage = new JMultilineLabel("");
         jepMessage.addHyperlinkListener(this);
@@ -128,6 +141,7 @@
         JPanel pnl = new JPanel(new BorderLayout());
         pnl.add(lblWarning, BorderLayout.NORTH);
         add(pnl, BorderLayout.WEST);
+        add(buildPossibleUserBox(), BorderLayout.SOUTH);
     }
 
     public void setConfigurationParameterRequestListener(ConfigurationParameterRequestHandler handler) {
Index: src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmConnection.java	(revision 14961)
+++ src/org/openstreetmap/josm/io/OsmConnection.java	(working copy)
@@ -104,18 +104,9 @@
      * Adds an authentication header for basic authentication
      *
      * @param con the connection
-     * @throws OsmTransferException if something went wrong. Check for nested exceptions
+     * @param response the response with username/password information
      */
-    protected void addBasicAuthorizationHeader(HttpClient con) throws OsmTransferException {
-        CredentialsAgentResponse response;
-        try {
-            synchronized (CredentialsManager.getInstance()) {
-                response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
-                con.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
-            }
-        } catch (CredentialsAgentException e) {
-            throw new OsmTransferException(e);
-        }
+    protected void addBasicAuthorizationHeader(HttpClient con, CredentialsAgentResponse response) {
         if (response != null) {
             if (response.isCanceled()) {
                 cancel = true;
@@ -132,16 +123,16 @@
      * Signs the connection with an OAuth authentication header
      *
      * @param connection the connection
+     * @param holder specific OAuth access token
      *
      * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured
      * @throws OsmTransferException if signing fails
      */
-    protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
+    protected void addOAuthAuthorizationHeader(HttpClient connection, OAuthAccessTokenHolder holder) throws OsmTransferException {
         if (oauthParameters == null) {
             oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
         }
         OAuthConsumer consumer = oauthParameters.buildConsumer();
-        OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
         if (!holder.containsAccessToken()) {
             obtainAccessToken(connection);
         }
@@ -177,13 +168,45 @@
     }
 
     protected void addAuth(HttpClient connection) throws OsmTransferException {
-        final String authMethod = OsmApi.getAuthMethod();
-        if ("basic".equals(authMethod)) {
-            addBasicAuthorizationHeader(connection);
-        } else if ("oauth".equals(authMethod)) {
-            addOAuthAuthorizationHeader(connection);
+        addAuth(connection, null);
+    }
+
+    /**
+     * Add authorization information to a connection
+     * @param connection to add authorization information to
+     * @param holder A {@code CredentialsAgentResponse} for basic authorization,
+     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
+     * @throws OsmTransferException if the authorization is not valid
+     */
+    protected void addAuth(HttpClient connection, Object holder) throws OsmTransferException{
+        if (holder == null) {
+            final String authMethod = OsmApi.getAuthMethod();
+            if ("basic".equals(authMethod)) {
+                CredentialsAgentResponse response;
+                try {
+                    synchronized (CredentialsManager.getInstance()) {
+                        response = CredentialsManager.getInstance().getCredentials(RequestorType.SERVER,
+                        connection.getURL().getHost(), false /* don't know yet whether the credentials will succeed */);
+                    }
+                } catch (CredentialsAgentException e) {
+                    throw new OsmTransferException(e);
+                }
+                holder = response;
+            } else if ("oauth".equals(authMethod)) {
+                holder = OAuthAccessTokenHolder.getInstance();
+            } else {
+                String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
+                Logging.warn(msg);
+                throw new OsmTransferException(msg);
+            }
+        }
+
+        if (holder instanceof OAuthAccessTokenHolder) {
+            addOAuthAuthorizationHeader(connection, (OAuthAccessTokenHolder) holder);
+        } else if (holder instanceof CredentialsAgentResponse) {
+            addBasicAuthorizationHeader(connection, (CredentialsAgentResponse) holder);
         } else {
-            String msg = tr("Unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
+            String msg = tr("Unexpected object for authorizations. Got ''{0}''.", holder.getClass().getName());
             Logging.warn(msg);
             throw new OsmTransferException(msg);
         }
Index: src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 14961)
+++ src/org/openstreetmap/josm/io/OsmServerReader.java	(working copy)
@@ -79,10 +79,26 @@
      * @throws OsmTransferException if data transfer errors occur
      */
     protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor, String reason) throws OsmTransferException {
+        return getInputStream(urlStr, progressMonitor, reason, null);
+    }
+
+    /**
+     * Open a connection to the given url and return a reader on the input stream
+     * from that connection. In case of user cancel, return <code>null</code>.
+     * Relative URL's are directed to API base URL.
+     * @param urlStr The url to connect to.
+     * @param progressMonitor progress monitoring and abort handler
+     * @param reason The reason to show on console. Can be {@code null} if no reason is given
+     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
+     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
+     * @return A reader reading the input stream (servers answer) or <code>null</code>.
+     * @throws OsmTransferException if data transfer errors occur
+     */
+    protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor, String reason, Object authentication) throws OsmTransferException {
         try {
             api.initialize(progressMonitor);
             String url = urlStr.startsWith("http") ? urlStr : (getBaseUrl() + urlStr);
-            return getInputStreamRaw(url, progressMonitor, reason);
+            return getInputStreamRaw(url, progressMonitor, reason, authentication);
         } finally {
             progressMonitor.invalidate();
         }
@@ -122,6 +138,20 @@
     }
 
     /**
+     * Open a connection to the given url and return a reader on the input stream
+     * from that connection. In case of user cancel, return <code>null</code>.
+     * @param urlStr The exact url to connect to.
+     * @param progressMonitor progress monitoring and abort handler
+     * @param reason The reason to show on console. Can be {@code null} if no reason is given
+     * @return An reader reading the input stream (servers answer) or <code>null</code>.
+     * @throws OsmTransferException if data transfer errors occur
+     * @since xxx
+     */
+    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason, Object auth) throws OsmTransferException {
+        return getInputStreamRaw(urlStr, progressMonitor, reason, false, "GET", null, auth);
+    }
+
+    /**
      * Open a connection to the given url (if HTTP, trough a GET request) and return a reader on the input stream
      * from that connection. In case of user cancel, return <code>null</code>.
      * @param urlStr The exact url to connect to.
@@ -151,9 +181,31 @@
      * @throws OsmTransferException if data transfer errors occur
      * @since 12596
      */
+    protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason,
+            boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody) throws OsmTransferException {
+        return getInputStreamRaw(urlStr, progressMonitor, reason, uncompressAccordingToContentDisposition, httpMethod, requestBody, null);
+    }
+
+    /**
+     * Open a connection to the given url (if HTTP, with the specified method) and return a reader on the input stream
+     * from that connection. In case of user cancel, return <code>null</code>.
+     * @param urlStr The exact url to connect to.
+     * @param progressMonitor progress monitoring and abort handler
+     * @param reason The reason to show on console. Can be {@code null} if no reason is given
+     * @param uncompressAccordingToContentDisposition Whether to inspect the HTTP header {@code Content-Disposition}
+     *                                                for {@code filename} and uncompress a gzip/bzip2/xz/zip stream.
+     * @param httpMethod HTTP method ("GET", "POST" or "PUT")
+     * @param requestBody HTTP request body (for "POST" and "PUT" methods only). Must be null for "GET" method.
+     * @param auth A {@code CredentialsAgentResponse} for basic authorization,
+     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
+     * @return An reader reading the input stream (servers answer) or {@code null}.
+     * @throws OsmTransferException if data transfer errors occur
+     * @since xxx
+     */
     @SuppressWarnings("resource")
     protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason,
-            boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody) throws OsmTransferException {
+            boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody,
+            Object auth) throws OsmTransferException {
         try {
             OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlStr, Config.getUrls().getJOSMWebsite());
             OnlineResource.OSM_API.checkOfflineAccess(urlStr, OsmApi.getOsmApi().getServerUrl());
@@ -182,7 +234,7 @@
             activeConnection = client;
             adaptRequest(client);
             if (doAuthenticate) {
-                addAuth(client);
+                addAuth(client, auth);
             }
             if (cancel)
                 throw new OsmTransferCanceledException("Operation canceled");
@@ -415,10 +467,29 @@
      */
     public <T> T fetchData(String api, String subtask, DomParser<T> parser, ProgressMonitor monitor, String reason)
             throws OsmTransferException {
+        return fetchData(api, subtask, parser, monitor, reason, null);
+    }
+
+    /**
+     * Fetches generic data from the DOM document resulting an API call.
+     * @param api the OSM API call
+     * @param subtask the subtask translated message
+     * @param parser the parser converting the DOM document (OSM API result)
+     * @param <T> data type
+     * @param monitor The progress monitor
+     * @param reason The reason to show on console. Can be {@code null} if no reason is given
+     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
+     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
+     * @return The converted data
+     * @throws OsmTransferException if something goes wrong
+     * @since 12510
+     */
+    public <T> T fetchData(String api, String subtask, DomParser<T> parser, ProgressMonitor monitor, String reason, Object authentication)
+            throws OsmTransferException {
         try {
             monitor.beginTask("");
             monitor.indeterminateSubTask(subtask);
-            try (InputStream in = getInputStream(api, monitor.createSubTaskMonitor(1, true), reason)) {
+            try (InputStream in = getInputStream(api, monitor.createSubTaskMonitor(1, true), reason, authentication)) {
                 return parser.parse(XmlUtils.parseSafeDOM(in));
             }
         } catch (OsmTransferException e) {
Index: src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java	(revision 14961)
+++ src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java	(working copy)
@@ -13,9 +13,12 @@
 import javax.xml.xpath.XPathFactory;
 
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
+import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.UncheckedParseException;
 import org.openstreetmap.josm.tools.XmlParsingException;
 import org.openstreetmap.josm.tools.date.DateUtils;
@@ -159,6 +162,23 @@
     }
 
     /**
+     * Fetches user info without explicit reason with a specific authentication
+     * @param monitor The progress monitor
+     * @param authentication The authentication object ({@code OAuthAccessTokenHolder}
+     * or {@code CredentialsAgentResponse})
+     * @return The user info
+     * @throws OsmTransferException if something goes wrong
+     * @since xxx
+     */
+    public UserInfo fetchUserInfo(ProgressMonitor monitor, Object authentication) throws OsmTransferException {
+        if (authentication instanceof String) {
+            return fetchUserInfo(monitor, null, (String) authentication);
+        } else {
+            return fetchUserInfo(monitor, authentication, null);
+        }
+    }
+
+    /**
      * Fetches user info, with an explicit reason.
      * @param monitor The progress monitor
      * @param reason The reason to show on console. Can be {@code null} if no reason is given
@@ -167,7 +187,28 @@
      * @since 6695
      */
     public UserInfo fetchUserInfo(ProgressMonitor monitor, String reason) throws OsmTransferException {
-        return fetchData("user/details", tr("Reading user info ..."),
-                OsmServerUserInfoReader::buildFromXML, monitor, reason);
+        return fetchUserInfo(monitor, null, reason);
     }
+
+    /**
+     * Fetches user info, with an explicit reason.
+     * @param monitor The progress monitor
+     * @param authentication A {@code CredentialsAgentResponse} for basic authorization,
+     * {@code OAuthAccessTokenHolder} for OAuth, or {@code null} for defaults.
+     * @param reason The reason to show on console. Can be {@code null} if no reason is given
+     * @return The user info
+     * @throws OsmTransferException if something goes wrong
+     * @since xxx
+     */
+    public UserInfo fetchUserInfo(ProgressMonitor monitor, Object authentication , String reason) throws OsmTransferException {
+        if (authentication instanceof OAuthAccessTokenHolder || authentication instanceof CredentialsAgentResponse
+                || authentication == null) {
+            return fetchData("user/details", tr("Reading user info ..."),
+                    OsmServerUserInfoReader::buildFromXML, monitor, reason, authentication);
+        } else {
+            String msg = tr("We did not get a valid authentication object ({0})", authentication.getClass().getName());
+            Logging.warn(msg);
+            throw new OsmTransferException(msg);
+        }
+    }
 }
