Changeset 18991 in josm for trunk/test/unit


Ignore:
Timestamp:
2024-02-21T21:26:18+01:00 (10 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.

Location:
trunk/test/unit/org/openstreetmap/josm
Files:
4 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/TestUtils.java

    r18799 r18991  
    659659    /**
    660660     * Determines if OSM DEV_API credential have been provided. Required for functional tests.
    661      * @return {@code true} if {@code osm.username} and {@code osm.password} have been defined on the command line
     661     * @return {@code true} if {@code osm.oauth2} have been defined on the command line
    662662     */
    663663    public static boolean areCredentialsProvided() {
    664         return Utils.getSystemProperty("osm.username") != null && Utils.getSystemProperty("osm.password") != null;
     664        return Utils.getSystemProperty("osm.oauth2") != null;
    665665    }
    666666
  • trunk/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java

    r18786 r18991  
    186186        OAuth20Parameters parameters = (OAuth20Parameters) OAuthParameters.createDefault(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
    187187        RemoteControl.start();
    188         authorization.authorize(new OAuth20Parameters(parameters.getClientId(), parameters.getClientSecret(),
     188        authorization.authorize(new OAuth20Parameters(CLIENT_ID_VALUE, parameters.getClientSecret(),
    189189                wireMockRuntimeInfo.getHttpBaseUrl() + "/oauth2", wireMockRuntimeInfo.getHttpBaseUrl() + "/api",
    190190                parameters.getRedirectUri()), consumer::set, OsmScopes.read_gpx);
  • trunk/test/unit/org/openstreetmap/josm/data/oauth/OAuthParametersTest.java

    r18853 r18991  
    2424    @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
    2525    void testCreateDefault() {
    26         OAuthParameters def = OAuthParameters.createDefault();
     26        IOAuthParameters def = OAuthParameters.createDefault();
    2727        assertNotNull(def);
    28         assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl()));
    29         OAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api");
     28        assertEquals(def, OAuthParameters.createDefault(Config.getUrls().getDefaultOsmApiUrl(), OAuthVersion.OAuth20));
     29        IOAuthParameters dev = OAuthParameters.createDefault("https://api06.dev.openstreetmap.org/api", OAuthVersion.OAuth20);
    3030        assertNotNull(dev);
    3131        assertNotEquals(def, dev);
    3232        Logging.setLogLevel(Logging.LEVEL_TRACE); // enable trace for line coverage
    33         assertEquals(def, OAuthParameters.createDefault("wrong_url"));
    34         OAuthParameters dev2 = new OAuthParameters(dev);
    35         assertEquals(dev, dev2);
     33        assertEquals(def, OAuthParameters.createDefault("wrong_url", OAuthVersion.OAuth20));
    3634    }
    3735
     
    4240    void testEqualsContract() {
    4341        TestUtils.assumeWorkingEqualsVerifier();
    44         EqualsVerifier.forClass(OAuthParameters.class).usingGetClass().verify();
     42        EqualsVerifier.forClass(OAuth20Parameters.class).usingGetClass().verify();
    4543    }
    4644}
  • trunk/test/unit/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTaskTest.java

    r18870 r18991  
    99import java.awt.GraphicsEnvironment;
    1010import java.net.URL;
    11 import java.util.Collections;
     11import java.util.HashMap;
     12import java.util.Map;
    1213
    1314import javax.swing.JOptionPane;
    1415import javax.swing.JPanel;
    1516
    16 import org.junit.jupiter.api.BeforeEach;
    1717import org.junit.jupiter.api.Test;
    1818import org.openstreetmap.josm.TestUtils;
    1919import org.openstreetmap.josm.data.UserIdentityManager;
    2020import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
    21 import org.openstreetmap.josm.spi.preferences.Config;
    2221import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    2322import org.openstreetmap.josm.testutils.annotations.OsmApi;
     
    6463
    6564    /**
    66      * These tests were written with {@link org.openstreetmap.josm.data.oauth.OAuthVersion#OAuth10a} as the default auth method.
    67      */
    68     @BeforeEach
    69     void setup() {
    70         Config.getPref().put("osm-server.auth-method", "oauth");
    71     }
    72 
    73     /**
    7465     * Test of {@link DownloadOpenChangesetsTask} class when anonymous.
    7566     */
     
    8071            new WindowMocker();
    8172        }
    82         final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
    83         final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
    84             Collections.singletonMap(
    85                 "<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
     73        final Map<String, Object> optionPaneMock = new HashMap<>(2);
     74        optionPaneMock.put("<html>Could not retrieve the list of your open changesets because<br>JOSM does not know "
    8675                + "your identity.<br>You have either chosen to work anonymously or you are not "
    87                 + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION
    88             )
    89         );
     76                + "entitled<br>to know the identity of the user on whose behalf you are working.</html>", JOptionPane.OK_OPTION);
     77        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
     78        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
    9079
    9180        DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
     
    9685        assertNull(task.getChangesets());
    9786
    98         assertEquals(1, jopsMocker.getInvocationLog().size());
    99         Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     87        assertEquals(2, jopsMocker.getInvocationLog().size());
     88        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
    10089        assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
    10190        assertEquals("Missing user identity", invocationLogEntry[2]);
    10291
    103         assertTrue(oaWizardMocker.called);
     92        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     93        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
     94        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
    10495    }
    10596
     
    113104            new WindowMocker();
    114105        }
    115         final OAuthWizardMocker oaWizardMocker = new OAuthWizardMocker();
    116         final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(
    117             Collections.singletonMap("There are no open changesets", JOptionPane.OK_OPTION)
    118         );
     106        final Map<String, Object> optionPaneMock = new HashMap<>(2);
     107        optionPaneMock.put("There are no open changesets", JOptionPane.OK_OPTION);
     108        optionPaneMock.put("Obtain OAuth 2.0 token for authentication?", JOptionPane.NO_OPTION);
     109        final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker(optionPaneMock);
    119110
    120111        DownloadOpenChangesetsTask task = new DownloadOpenChangesetsTask(new JPanel());
     
    124115        assertNotNull(task.getChangesets());
    125116
    126         assertEquals(1, jopsMocker.getInvocationLog().size());
    127         Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     117        assertEquals(2, jopsMocker.getInvocationLog().size());
     118        Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(1);
    128119        assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
    129120        assertEquals("No open changesets", invocationLogEntry[2]);
    130121
    131         assertTrue(oaWizardMocker.called);
     122        invocationLogEntry = jopsMocker.getInvocationLog().get(0);
     123        assertEquals(JOptionPane.NO_OPTION, (int) invocationLogEntry[0]);
     124        assertEquals("Obtain authentication to OSM servers", invocationLogEntry[2]);
    132125    }
    133126}
  • trunk/test/unit/org/openstreetmap/josm/gui/oauth/FullyAutomaticAuthorizationUITest.java

    r18037 r18991  
    22package org.openstreetmap.josm.gui.oauth;
    33
    4 import static org.junit.jupiter.api.Assertions.assertNotNull;
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    55
     6import org.junit.jupiter.params.ParameterizedTest;
     7import org.junit.jupiter.params.provider.EnumSource;
     8import org.openstreetmap.josm.data.oauth.OAuthVersion;
    69import org.openstreetmap.josm.gui.MainApplication;
    710import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
    8 
    9 import org.junit.jupiter.api.Test;
    1011
    1112/**
     
    1718     * Unit test of {@link FullyAutomaticAuthorizationUI#FullyAutomaticAuthorizationUI}.
    1819     */
    19     @Test
    20     void testFullyAutomaticAuthorizationUI() {
    21         assertNotNull(new FullyAutomaticAuthorizationUI("", MainApplication.worker));
     20    @ParameterizedTest
     21    @EnumSource(OAuthVersion.class)
     22    void testFullyAutomaticAuthorizationUI(OAuthVersion version) {
     23        assertDoesNotThrow(() -> new FullyAutomaticAuthorizationUI("", MainApplication.worker, version));
    2224    }
    2325}
  • trunk/test/unit/org/openstreetmap/josm/gui/oauth/ManualAuthorizationUITest.java

    r18037 r18991  
    22package org.openstreetmap.josm.gui.oauth;
    33
    4 import static org.junit.jupiter.api.Assertions.assertNotNull;
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    55
    66import org.junit.jupiter.api.Test;
     7import org.openstreetmap.josm.data.oauth.OAuthVersion;
    78import org.openstreetmap.josm.gui.MainApplication;
    89import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
     
    1819    @Test
    1920    void testManualAuthorizationUI() {
    20         assertNotNull(new ManualAuthorizationUI("", MainApplication.worker));
     21        assertDoesNotThrow(() -> new ManualAuthorizationUI("", MainApplication.worker, OAuthVersion.OAuth20));
    2122    }
    2223}
  • trunk/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java

    r18765 r18991  
    2121import org.junit.jupiter.params.ParameterizedTest;
    2222import org.junit.jupiter.params.provider.EnumSource;
    23 import org.openstreetmap.josm.data.oauth.IOAuthToken;
    2423import org.openstreetmap.josm.data.oauth.OAuth20Exception;
    2524import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    2625import org.openstreetmap.josm.data.oauth.OAuth20Token;
    2726import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
    28 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2927import org.openstreetmap.josm.data.oauth.OAuthVersion;
    3028import org.openstreetmap.josm.io.OsmApi;
     
    4745        List<Exception> exceptionList = new ArrayList<>();
    4846        try {
    49             CredentialsManager.getInstance().storeOAuthAccessToken(null);
     47            CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
    5048        } catch (CredentialsAgentException exception) {
    5149            exceptionList.add(exception);
     
    6159
    6260    @ParameterizedTest
    63     @EnumSource(value = OAuthVersion.class, names = {"OAuth10a", "OAuth20"})
     61    @EnumSource(value = OAuthVersion.class, names = "OAuth20")
    6462    void testRemoveToken(OAuthVersion oAuthVersion) throws ReflectiveOperationException, CredentialsAgentException, OAuth20Exception {
    6563        final OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel(oAuthVersion);
     
    7674        assertSame(pnlAlreadyAuthorised.get(panel), holder.getComponent(0), "Authentication should now be set");
    7775        assertNotNull(getAuthorization(oAuthVersion));
    78         final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(6);
    79         final JButton action = (JButton) buttons.getComponent(oAuthVersion == OAuthVersion.OAuth10a ? 2 : 1);
     76        final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(5);
     77        final JButton action = (JButton) buttons.getComponent(2);
    8078        assertEquals(tr("Remove token"), action.getText(), "The selected button should be for removing the token");
    8179        action.getAction().actionPerformed(null);
     
    9795    private static void addAuthorization(OAuthVersion oAuthVersion) throws CredentialsAgentException, OAuth20Exception {
    9896        switch (oAuthVersion) {
    99             case OAuth10a:
    100                 CredentialsManager.getInstance().storeOAuthAccessToken(new OAuthToken("fake_key", "fake_secret"));
    101                 break;
    10297            case OAuth20:
    10398            case OAuth21:
     
    117112    private static Object getAuthorization(OAuthVersion oAuthVersion) {
    118113        OAuthAccessTokenHolder.getInstance().clear();
    119         OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getHost(), (IOAuthToken) null);
     114        OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
    120115        OAuthAccessTokenHolder.getInstance().init(CredentialsManager.getInstance());
    121116        // Ensure that we are not saving authorization data
    122         switch (oAuthVersion) {
    123             case OAuth10a:
    124                 return OAuthAccessTokenHolder.getInstance().getAccessToken();
    125             case OAuth20:
    126             case OAuth21:
    127                 return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getHost(), oAuthVersion);
    128             default:
    129                 throw new AssertionError("OAuth version not understood");
    130         }
     117        return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getServerUrl(), oAuthVersion);
    131118    }
    132119}
  • trunk/test/unit/org/openstreetmap/josm/io/auth/CredentialsAgentTest.java

    r18650 r18991  
    1919import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
    2020import org.openstreetmap.josm.data.oauth.OAuth20Token;
    21 import org.openstreetmap.josm.data.oauth.OAuthToken;
    2221import org.openstreetmap.josm.io.OsmApi;
    2322import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
     
    7675    }
    7776
    78     @Test
    79     default void testLookUpAndStoreOAuth10() throws CredentialsAgentException {
    80         final T agent = createAgent();
    81         assertNull(agent.lookupOAuthAccessToken());
    82         final OAuthToken token = new OAuthToken("foo", "bar");
    83         agent.storeOAuthAccessToken(token);
    84         final OAuthToken actual = agent.lookupOAuthAccessToken();
    85         assertEquals(token, actual);
    86         agent.storeOAuthAccessToken(null);
    87         assertNull(agent.lookupOAuthAccessToken());
    88     }
    89 
    9077    @ParameterizedTest
    9178    @MethodSource("getHosts")
  • trunk/test/unit/org/openstreetmap/josm/testutils/annotations/BasicPreferences.java

    r18870 r18991  
    6565            if (AnnotationSupport.isAnnotated(context.getElement(), BasicPreferences.class)) {
    6666                this.afterAll(context);
     67                if (AnnotationSupport.isAnnotated(context.getTestClass(), BasicPreferences.class)) {
     68                    this.beforeAll(context);
     69                }
    6770            }
    6871        }
  • trunk/test/unit/org/openstreetmap/josm/testutils/annotations/TestUser.java

    r18974 r18991  
    1010import java.lang.annotation.Target;
    1111import java.net.Authenticator;
    12 import java.net.PasswordAuthentication;
    1312
    1413import org.junit.jupiter.api.extension.AfterEachCallback;
     
    1918import org.openstreetmap.josm.TestUtils;
    2019import org.openstreetmap.josm.data.UserIdentityManager;
     20import org.openstreetmap.josm.data.oauth.OAuth20Token;
     21import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
     22import org.openstreetmap.josm.data.oauth.OAuthParameters;
    2123import org.openstreetmap.josm.io.auth.CredentialsManager;
    2224import org.openstreetmap.josm.spi.preferences.Config;
     
    5153        public void beforeEach(ExtensionContext context) throws Exception {
    5254            assumeTrue(TestUtils.areCredentialsProvided(),
    53                     "OSM DEV API credentials not provided. Please define them with -Dosm.username and -Dosm.password");
    54             final String username = Utils.getSystemProperty("osm.username");
    55             final String password = Utils.getSystemProperty("osm.password");
    56             assumeTrue(username != null && !username.isEmpty(), "Please add -Dosm.username for the OSM DEV API");
    57             assumeTrue(password != null && !password.isEmpty(), "Please add -Dosm.password for the OSM DEV API");
    58             Config.getPref().put("osm-server.auth-method", "basic");
     55                    "OSM DEV API credentials not provided. Please define them with -Dosm.oauth2");
     56            final String oauth2 = Utils.getSystemProperty("osm.oauth2");
     57            Config.getPref().put("osm-server.auth-method", "oauth20");
    5958
    6059            // don't use atomic upload, the test API server can't cope with large diff uploads
    6160            Config.getPref().putBoolean("osm-server.atomic-upload", false);
    62             CredentialsManager.getInstance().store(Authenticator.RequestorType.SERVER, org.openstreetmap.josm.io.OsmApi.getOsmApi().getHost(),
    63                     new PasswordAuthentication(username, password.toCharArray()));
     61            final String serverUrl = org.openstreetmap.josm.io.OsmApi.getOsmApi().getServerUrl();
     62            final OAuth20Token token = new OAuth20Token(OAuthParameters.createDefault(),
     63                    "{\"token_type\":\"bearer\", \"access_token\": \"" + oauth2 + "\"}");
     64            OAuthAccessTokenHolder.getInstance().setAccessToken(serverUrl, token);
     65            CredentialsManager.getInstance().storeOAuthAccessToken(serverUrl, token);
     66            if (!UserIdentityManager.getInstance().isFullyIdentified()) {
     67                UserIdentityManager.getInstance().initFromOAuth();
     68            }
    6469        }
    6570    }
Note: See TracChangeset for help on using the changeset viewer.