Ignore:
Timestamp:
2024-02-21T21:26:18+01:00 (3 months ago)
Author:
taylor.smock
Message:

Fix #22810: OSM OAuth 1.0a/Basic auth deprecation and removal

As of 2024-02-15, something changed in the OSM server configuration. This broke
our OAuth 1.0a implementation (see #23475). As such, we are removing OAuth 1.0a
from JOSM now instead of when the OSM server removes support in June 2024.

For third-party OpenStreetMap servers, the Basic Authentication method has been
kept. However, they should be made aware that it may be removed if a non-trivial
bug occurs with it. We highly recommend that the third-party servers update to
the current OpenStreetMap website implementation (if only for their own security).

Failing that, the third-party server can implement RFC8414. As of this commit,
we currently use the authorization_endpoint and token_endpoint fields.
To check and see if their third-party server implements RFC8414, they can go
to <server host>/.well-known/oauth-authorization-server.

Prominent third-party OpenStreetMap servers may give us a client id for their
specific server. That client id may be added to the hard-coded client id list
at maintainer discretion. At a minimum, the server must be publicly
available and have a significant user base.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/OsmConnection.java

    r18665 r18991  
    66import java.lang.reflect.InvocationTargetException;
    77import java.net.Authenticator.RequestorType;
    8 import java.net.MalformedURLException;
    98import java.net.URL;
    109import java.nio.charset.StandardCharsets;
     
    3635import org.openstreetmap.josm.tools.Logging;
    3736
    38 import oauth.signpost.OAuthConsumer;
    39 import oauth.signpost.exception.OAuthException;
    40 
    4137/**
    4238 * Base class that handles common things like authentication for the reader and writer
     
    5147    protected boolean cancel;
    5248    protected HttpClient activeConnection;
    53     protected OAuthParameters oauthParameters;
    5449    protected IOAuthParameters oAuth20Parameters;
    5550
     
    146141
    147142    /**
    148      * Signs the connection with an OAuth authentication header
    149      *
    150      * @param connection the connection
    151      *
    152      * @throws MissingOAuthAccessTokenException if there is currently no OAuth Access Token configured
    153      * @throws OsmTransferException if signing fails
    154      */
    155     protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException {
    156         if (oauthParameters == null) {
    157             oauthParameters = OAuthParameters.createFromApiUrl(OsmApi.getOsmApi().getServerUrl());
    158         }
    159         OAuthConsumer consumer = oauthParameters.buildConsumer();
    160         OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
    161         if (!holder.containsAccessToken()) {
    162             obtainAccessToken(connection);
    163         }
    164         if (!holder.containsAccessToken()) { // check if wizard completed
    165             throw new MissingOAuthAccessTokenException();
    166         }
    167         consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());
    168         try {
    169             consumer.sign(connection);
    170         } catch (OAuthException e) {
    171             throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);
    172         }
    173     }
    174 
    175     /**
    176      * Obtains an OAuth access token for the connection.
    177      * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
    178      * @param connection connection for which the access token should be obtained
    179      * @throws MissingOAuthAccessTokenException if the process cannot be completed successfully
    180      */
    181     protected void obtainAccessToken(final HttpClient connection) throws MissingOAuthAccessTokenException {
    182         try {
    183             final URL apiUrl = new URL(OsmApi.getOsmApi().getServerUrl());
    184             if (!Objects.equals(apiUrl.getHost(), connection.getURL().getHost())) {
    185                 throw new MissingOAuthAccessTokenException();
    186             }
    187             fetcher.obtainAccessToken(apiUrl);
    188             OAuthAccessTokenHolder.getInstance().setSaveToPreferences(true);
    189             OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    190         } catch (MalformedURLException | InvocationTargetException e) {
    191             throw new MissingOAuthAccessTokenException(e);
    192         } catch (InterruptedException e) {
    193             Thread.currentThread().interrupt();
    194             throw new MissingOAuthAccessTokenException(e);
    195         }
    196     }
    197 
    198     /**
    199143     * Obtains an OAuth access token for the connection.
    200144     * Afterwards, the token is accessible via {@link OAuthAccessTokenHolder} / {@link CredentialsManager}.
     
    221165                    }
    222166                    // Clean up old token/password
    223                     OAuthAccessTokenHolder.getInstance().setAccessToken(null);
    224167                    OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), authToken.orElse(null));
    225168                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
     
    281224                addBasicAuthorizationHeader(connection);
    282225                return;
    283             case "oauth":
    284                 addOAuthAuthorizationHeader(connection);
    285                 return;
    286226            case "oauth20":
    287227                addOAuth20AuthorizationHeader(connection);
Note: See TracChangeset for help on using the changeset viewer.