Changeset 18786 in josm


Ignore:
Timestamp:
2023-07-27T15:47:48+02:00 (19 months ago)
Author:
taylor.smock
Message:

Fix #23083: SocketTimeoutException in OAuth20Authorization$OAuth20AuthorizationHandler.handleRequest

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/oauth/OAuth20Authorization.java

    r18665 r18786  
    102102                } catch (IOException | OAuth20Exception e) {
    103103                    consumer.accept(Optional.empty());
    104                     throw new JosmRuntimeException(e);
     104                    throw new RequestHandler.RequestHandlerErrorException(e);
    105105                } finally {
    106106                    tradeCodeForToken.disconnect();
    107107                }
    108108            } catch (MalformedURLException e) {
    109                 throw new JosmRuntimeException(e);
     109                consumer.accept(Optional.empty());
     110                throw new RequestHandler.RequestHandlerBadRequestException(e);
    110111            }
    111112            return null;
  • trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java

    r18764 r18786  
    2121import javax.swing.JCheckBox;
    2222import javax.swing.JLabel;
     23import javax.swing.JOptionPane;
    2324import javax.swing.JPanel;
    2425
     
    375376                    OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
    376377                    GuiHelper.runInEDT(OAuthAuthenticationPreferencesPanel.this::refreshView);
     378                    if (!token.isPresent()) {
     379                        GuiHelper.runInEDT(() -> JOptionPane.showMessageDialog(MainApplication.getMainPanel(),
     380                                tr("Authentication failed, please check browser for details."),
     381                                tr("OAuth Authentication Failed"),
     382                                JOptionPane.ERROR_MESSAGE));
     383                    }
    377384                }, OsmScopes.read_gpx, OsmScopes.write_gpx,
    378385                        OsmScopes.read_prefs, OsmScopes.write_prefs,
  • trunk/test/unit/org/openstreetmap/josm/data/oauth/OAuth20AuthorizationTest.java

    r18666 r18786  
    22package org.openstreetmap.josm.data.oauth;
    33
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    45import static org.junit.jupiter.api.Assertions.assertEquals;
    56import static org.junit.jupiter.api.Assertions.assertNotNull;
     
    89
    910import java.io.IOException;
     11import java.net.URL;
    1012import java.util.HashMap;
    1113import java.util.Map;
     
    2022import com.github.tomakehurst.wiremock.extension.Parameters;
    2123import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
     24import com.github.tomakehurst.wiremock.http.FixedDelayDistribution;
    2225import com.github.tomakehurst.wiremock.http.HttpHeader;
    2326import com.github.tomakehurst.wiremock.http.HttpHeaders;
     
    6265    private static final String CODE_CHALLENGE = "code_challenge";
    6366
     67    private enum ConnectionProblems {
     68        NONE,
     69        SOCKET_TIMEOUT
     70    }
     71
    6472    private static class OAuthServerWireMock extends ResponseTransformer {
    6573        String stateToReturn;
     74        ConnectionProblems connectionProblems = ConnectionProblems.NONE;
    6675        @Override
    6776        public Response transform(Request request, Response response, FileSource files, Parameters parameters) {
     
    8998                return Response.Builder.like(response).but().status(500).build();
    9099            }
    91             return Response.Builder.like(response).but().body("{\"token_type\": \"bearer\", \"access_token\": \"test_access_token\"}").build();
     100            switch (connectionProblems) {
     101                case SOCKET_TIMEOUT:
     102                    return Response.Builder.like(response).but().configureDelay(null, null,
     103                                    10_000, new FixedDelayDistribution(0)).build();
     104                case NONE:
     105                default:
     106                    return Response.Builder.like(response).but()
     107                            .body("{\"token_type\": \"bearer\", \"access_token\": \"test_access_token\"}").build();
     108            }
    92109        }
    93110
     
    136153        RemoteControl.stop(); // Ensure remote control is stopped
    137154        oauthServer.stateToReturn = null;
     155        oauthServer.connectionProblems = ConnectionProblems.NONE;
    138156    }
    139157
     
    164182    }
    165183
    166     @Test
    167     void testAuthorize(WireMockRuntimeInfo wireMockRuntimeInfo) throws IOException {
     184    private HttpClient generateClient(WireMockRuntimeInfo wireMockRuntimeInfo, AtomicReference<Optional<IOAuthToken>> consumer) {
    168185        final OAuth20Authorization authorization = new OAuth20Authorization();
    169         final AtomicReference<Optional<IOAuthToken>> consumer = new AtomicReference<>();
    170186        OAuth20Parameters parameters = (OAuth20Parameters) OAuthParameters.createDefault(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
    171187        RemoteControl.start();
     
    174190                parameters.getRedirectUri()), consumer::set, OsmScopes.read_gpx);
    175191        assertEquals(1, OpenBrowserMocker.getCalledURIs().size());
    176         HttpClient client = HttpClient.create(OpenBrowserMocker.getCalledURIs().get(0).toURL());
     192        final URL url = assertDoesNotThrow(() -> OpenBrowserMocker.getCalledURIs().get(0).toURL());
     193        return HttpClient.create(url);
     194    }
     195
     196    @Test
     197    void testAuthorize(WireMockRuntimeInfo wireMockRuntimeInfo) throws IOException {
     198        final AtomicReference<Optional<IOAuthToken>> consumer = new AtomicReference<>();
     199        final HttpClient client = generateClient(wireMockRuntimeInfo, consumer);
    177200        try {
    178201            HttpClient.Response response = client.connect();
     
    191214    void testAuthorizeBadState(WireMockRuntimeInfo wireMockRuntimeInfo) throws IOException {
    192215        oauthServer.stateToReturn = "Bad_State";
    193         final OAuth20Authorization authorization = new OAuth20Authorization();
    194216        final AtomicReference<Optional<IOAuthToken>> consumer = new AtomicReference<>();
    195         OAuth20Parameters parameters = (OAuth20Parameters) OAuthParameters.createDefault(OsmApi.getOsmApi().getBaseUrl(), OAuthVersion.OAuth20);
    196         RemoteControl.start();
    197         authorization.authorize(new OAuth20Parameters(parameters.getClientId(), parameters.getClientSecret(),
    198                 wireMockRuntimeInfo.getHttpBaseUrl() + "/oauth2", wireMockRuntimeInfo.getHttpBaseUrl() + "/api",
    199                 parameters.getRedirectUri()), consumer::set, OsmScopes.read_gpx);
    200         assertEquals(1, OpenBrowserMocker.getCalledURIs().size());
    201         HttpClient client = HttpClient.create(OpenBrowserMocker.getCalledURIs().get(0).toURL());
     217        final HttpClient client = generateClient(wireMockRuntimeInfo, consumer);
    202218        try {
    203219            HttpClient.Response response = client.connect();
     
    210226        assertNull(consumer.get(), "The OAuth consumer should not be called since the state does not match");
    211227    }
     228
     229    @Test
     230    void testSocketTimeout(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception {
     231        // 1s before timeout
     232        Config.getPref().putInt("socket.timeout.connect", 1);
     233        Config.getPref().putInt("socket.timeout.read", 1);
     234        oauthServer.connectionProblems = ConnectionProblems.SOCKET_TIMEOUT;
     235
     236        final AtomicReference<Optional<IOAuthToken>> consumer = new AtomicReference<>();
     237        final HttpClient client = generateClient(wireMockRuntimeInfo, consumer)
     238                .setConnectTimeout(15_000).setReadTimeout(30_000);
     239        try {
     240            HttpClient.Response response = client.connect();
     241            assertEquals(500, response.getResponseCode());
     242            String content = response.fetchContent();
     243            assertTrue(content.contains("java.net.SocketTimeoutException: Read timed out"));
     244        } finally {
     245            client.disconnect();
     246        }
     247        assertEquals(Optional.empty(), consumer.get());
     248    }
    212249}
Note: See TracChangeset for help on using the changeset viewer.