source: josm/trunk/test/unit/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanelTest.java@ 18991

Last change on this file since 18991 was 18991, checked in by taylor.smock, 3 months ago

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 size: 6.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.server;
3
4import static org.junit.jupiter.api.Assertions.assertAll;
5import static org.junit.jupiter.api.Assertions.assertEquals;
6import static org.junit.jupiter.api.Assertions.assertNotNull;
7import static org.junit.jupiter.api.Assertions.assertNull;
8import static org.junit.jupiter.api.Assertions.assertSame;
9import static org.junit.jupiter.api.Assertions.fail;
10import static org.openstreetmap.josm.tools.I18n.tr;
11
12import java.lang.reflect.Field;
13import java.net.Authenticator;
14import java.util.ArrayList;
15import java.util.List;
16
17import javax.swing.JButton;
18import javax.swing.JPanel;
19
20import org.junit.jupiter.api.AfterEach;
21import org.junit.jupiter.params.ParameterizedTest;
22import org.junit.jupiter.params.provider.EnumSource;
23import org.openstreetmap.josm.data.oauth.OAuth20Exception;
24import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
25import org.openstreetmap.josm.data.oauth.OAuth20Token;
26import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
27import org.openstreetmap.josm.data.oauth.OAuthVersion;
28import org.openstreetmap.josm.io.OsmApi;
29import org.openstreetmap.josm.io.auth.CredentialsAgentException;
30import org.openstreetmap.josm.io.auth.CredentialsManager;
31import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
32import org.openstreetmap.josm.tools.ReflectionUtils;
33
34/**
35 * Test class for {@link OAuthAuthenticationPreferencesPanel}
36 */
37@BasicPreferences
38class OAuthAuthenticationPreferencesPanelTest {
39 @AfterEach
40 void tearDown() {
41 OAuthAccessTokenHolder.getInstance().clear();
42 for (Authenticator.RequestorType type : Authenticator.RequestorType.values()) {
43 CredentialsManager.getInstance().purgeCredentialsCache(type);
44 }
45 List<Exception> exceptionList = new ArrayList<>();
46 try {
47 CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
48 } catch (CredentialsAgentException exception) {
49 exceptionList.add(exception);
50 }
51 try {
52 CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getHost(), null);
53 } catch (CredentialsAgentException exception) {
54 exceptionList.add(exception);
55 }
56
57 assertAll(exceptionList.stream().map(e -> () -> fail(e)));
58 }
59
60 @ParameterizedTest
61 @EnumSource(value = OAuthVersion.class, names = "OAuth20")
62 void testRemoveToken(OAuthVersion oAuthVersion) throws ReflectiveOperationException, CredentialsAgentException, OAuth20Exception {
63 final OAuthAuthenticationPreferencesPanel panel = new OAuthAuthenticationPreferencesPanel(oAuthVersion);
64 final Field pnlNotYetAuthorised = OAuthAuthenticationPreferencesPanel.class.getDeclaredField("pnlNotYetAuthorised");
65 final Field pnlAlreadyAuthorised = OAuthAuthenticationPreferencesPanel.class.getDeclaredField("pnlAlreadyAuthorised");
66 final JPanel holder = (JPanel) panel.getComponent(0);
67 ReflectionUtils.setObjectsAccessible(pnlNotYetAuthorised, pnlAlreadyAuthorised);
68 panel.initFromPreferences();
69 assertNull(getAuthorization(oAuthVersion));
70 assertSame(pnlNotYetAuthorised.get(panel), holder.getComponent(0), "No authentication should be set yet");
71 addAuthorization(oAuthVersion);
72 assertNotNull(getAuthorization(oAuthVersion));
73 panel.initFromPreferences();
74 assertSame(pnlAlreadyAuthorised.get(panel), holder.getComponent(0), "Authentication should now be set");
75 assertNotNull(getAuthorization(oAuthVersion));
76 final JPanel buttons = (JPanel) ((JPanel) pnlAlreadyAuthorised.get(panel)).getComponent(5);
77 final JButton action = (JButton) buttons.getComponent(2);
78 assertEquals(tr("Remove token"), action.getText(), "The selected button should be for removing the token");
79 action.getAction().actionPerformed(null);
80 panel.saveToPreferences(); // Save to preferences should make the removal permanent
81 // Ensure that the token holder has been reset for OAuth 1.0a
82 OAuthAccessTokenHolder.getInstance().clear();
83 OAuthAccessTokenHolder.getInstance().init(CredentialsManager.getInstance());
84 assertNull(getAuthorization(oAuthVersion), "No authentication data should be stored");
85 panel.initFromPreferences();
86 assertSame(pnlNotYetAuthorised.get(panel), holder.getComponent(0), "No authentication should be set");
87 }
88
89 /**
90 * Add authorization preferences for the specified oauth version
91 * @param oAuthVersion The oauth version to use
92 * @throws CredentialsAgentException If something goes wrong
93 * @throws OAuth20Exception If something goes wrong
94 */
95 private static void addAuthorization(OAuthVersion oAuthVersion) throws CredentialsAgentException, OAuth20Exception {
96 switch (oAuthVersion) {
97 case OAuth20:
98 case OAuth21:
99 CredentialsManager.getInstance().storeOAuthAccessToken(OsmApi.getOsmApi().getHost(),
100 new OAuth20Token(new OAuth20Parameters("fake_id", "fake_secret", "https://fake.url/token",
101 "https://fake.url/authorize", OsmApi.getOsmApi().getBaseUrl(), "http://127.0.0.1:8111/oauth_authorization"),
102 "{\"access_token\": \"fake_token\", \"token_type\": \"bearer\"}"));
103 }
104 assertNotNull(getAuthorization(oAuthVersion));
105 }
106
107 /**
108 * Get the authorization token
109 * @param oAuthVersion The oauth version
110 * @return The token
111 */
112 private static Object getAuthorization(OAuthVersion oAuthVersion) {
113 OAuthAccessTokenHolder.getInstance().clear();
114 OAuthAccessTokenHolder.getInstance().setAccessToken(OsmApi.getOsmApi().getServerUrl(), null);
115 OAuthAccessTokenHolder.getInstance().init(CredentialsManager.getInstance());
116 // Ensure that we are not saving authorization data
117 return OAuthAccessTokenHolder.getInstance().getAccessToken(OsmApi.getOsmApi().getServerUrl(), oAuthVersion);
118 }
119}
Note: See TracBrowser for help on using the repository browser.