Changes between Initial Version and Version 4 of Ticket #24928


Ignore:
Timestamp:
2026-10-04T15:09:04+02:00 (11 hours ago)
Author:
wangi
Comment:

Thanks, i've updated the description to match; the changes are marked in place, with answers in section 3.

1) Basic Auth stays, for experts. The option is shown only in expert mode, or when it is the method currently selected, so that a profile still using it doesn't lose sight of its own setting. It stays disabled for the default OSM API, as it is today. The code behind it is untouched, so the migration question goes away.

2) A manual path stays. The window goes, but pasting an access token stays, as a field next to the other OAuth parameters. To make it a real fallback for "if everything breaks", a pasted token must work with nothing else: no client id, no endpoints, no RFC 8414 discovery, no remote control, no browser. That isn't true today — OAuth20Token needs complete OAuth20Parameters — so it becomes an explicit requirement. One part of your question is still open: these are public classes, but I assume there is no need for a deprecation cycle for OAuthAuthorizationWizard, ManualAuthorizationUI and friends, and a straight removal is fine?

3) The host. JosmPreferencesCredentialAgent already stores the token, and the parameters it was issued with, under oauth.access-token.parameters.OAuth20.<host>. That is the same prefix rememberPreferences() writes to under the API URL, so today a configured server has two parameter entries. Keying by host means every stored token stays valid and nobody has to authorize again; only custom parameters are read once from their old key.

4) This falls out of 3: "use default settings" just means no custom parameters are stored for that host, and the global oauth.settings.use-default goes.

5) When discovery fails, the endpoints are pre-filled with <site>/oauth2/authorize and <site>/oauth2/token — correct for any openstreetmap-website instance, unlike today's <api url>/authorize — and stay editable. So the manual fallback covers this as well.

6) I'll write the server-operator page.

While checking 3) I found #24932: "Remove token" never deleted the token itself, only the parameters stored with it, so the bearer token stayed in the preferences in clear text. That patch touches the same method this ticket reworks, and what removing a token deletes has to be right before the token and the parameters share one key, so I've added it as a third prerequisite alongside #24907 and #24925.

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #24928

    • Property Summary [RFC] Rationalise OSM API authentication: OAuth 2 only, one authorization flow, one place to enter the parameters → [RFC] Rationalise OSM API authentication: one authorization flow, one place to enter the parameters
  • Ticket #24928 – Description

    initial v4  
     1''Updated after the feedback in comment:2.''
    12This is a request for comments before any code is written. It grows out of #24889, #24890 and #24925, which are all the same underlying problem seen from three directions: authenticating against an openstreetmap-website instance that is not openstreetmap.org or openhistoricalmap.org.
    23
    3 '''Prerequisites.''' Two bug fixes should land first. They are independent of each other and can go in either order, but both are assumed by what follows.
     4'''Prerequisites.''' Three bug fixes should land first. They are independent of each other and can go in any order, but all are assumed by what follows.
    45
    56 * '''#24907''' — a trailing slash on the API URL breaks OAuth authentication. It normalises the API URL in one place, which everything below relies on: there is no point agreeing on a single key for the OAuth parameters and the token while `https://example.org/api` and `https://example.org/api/` are still two different keys.
    67 * '''#24925''' — authentication on upload fails against a server with no built-in client id. The OAuth parameters are stored under the API URL but were looked up with the host of the request, so the lookup missed and JOSM opened the browser with an empty `client_id`. Fixed there; the reason it belongs here is that nothing stopped the two keys drifting apart in the first place, and the next caller holding only one of them will hit the same wall. Settling that is point (d) below.
     8 * '''#24932''' — "Remove token" leaves the OAuth access token in the preferences. It fixes the method that (d) reworks, and what removing a token deletes has to be right before the token and the parameters share one key.
    79
    810== 1. What the code looks like today ==
    … …  
    3739== 2. Proposal ==
    3840
    39 '''(a) Drop Basic Authentication as an OSM API authentication method.''' Remove the radio buttons, `BasicAuthenticationPreferencesPanel`, `addBasicAuthorizationHeader()`, the `"basic"` branch of `OsmConnection.addAuth()`, the username/password branch of `MessageNotifier`, and `UserIdentityManager.initFromPreferences()`'s username path. The preference `osm-server.auth-method` becomes redundant.
     41'''(a) Basic Authentication for experts only.''' Keep it as an OSM API authentication method, as a quick way to test one's own server, but show the option only in expert mode — or when it is the method currently selected, so that a profile still using it does not lose sight of its own setting. As today, `AuthenticationPreferencesPanel.updateAcceptableAuthenticationMethods()` keeps it disabled for the default OSM API, which does not accept it. (Originally proposed for removal; changed after comment:2.)
    4042
    41 `CredentialsManager`, `CredentialsAgent`, `JosmPreferencesCredentialAgent` and `DefaultAuthenticator` '''stay''': they also serve proxy authentication and HTTP authentication for other hosts such as imagery servers. Only the OSM-API-as-basic-auth path goes.
    42 
    43 Note this is already half-done: `AuthenticationPreferencesPanel.updateAcceptableAuthenticationMethods()` disables the basic option for the default OSM API, because openstreetmap.org dropped it.
    44 
    45 On the servers we can speak for, nothing is left that needs it. openstreetmap.org has not accepted basic authentication for years; OpenGeofiction has moved to OAuth 2; and Arhet, the remaining third-party instance we know of, can speak OAuth 2 once the RFC 8414 `.well-known` file is in place. That last case is worth noting for point (e) below: publishing `/.well-known/oauth-authorization-server` is the supported way for a third-party instance to work with JOSM without needing a client id built into JOSM, and it is not documented anywhere a server operator would find it.
     43Publishing `/.well-known/oauth-authorization-server` is the supported way for a third-party instance to work with JOSM without needing a client id built into JOSM, and it is not documented anywhere a server operator would find it; see the wiki page in section 3.
    4644
    4745'''(a2) Remove what is left of OAuth 1.0a.''' The mechanism is already gone — `OAuthVersion` has only `OAuth20` and `OAuth21` — but the vocabulary and some classes outlived it:
    … …  
    5452 * `OAuthAuthenticationPreferencesPanel.AlreadyAuthorisedPanel` adds a `JLabel` reading '''"Access Token Secret:" with no field after it'''. OAuth 2 tokens have no secret; the label is a leftover and is visible in the preferences today.
    5553
    56 '''(b) and (c) One authorization flow, no wizard window.''' Delete `AuthorizationProcedure`, `OAuthAuthorizationWizard`, `FullyAutomaticAuthorizationUI`, `FullyAutomaticPropertiesPanel`, `ManualAuthorizationUI`, `AbstractAuthorizationUI`, `AccessTokenInfoPanel`, `OsmPrivilegesPanel` and the dead `OAuthAccessTokenFetcher`. What remains is one "Authorize now" button that runs the browser-based OAuth 2 dance with the parameters currently shown in the panel.
     54'''(b) and (c) One authorization flow, no wizard window.''' Delete `AuthorizationProcedure`, `OAuthAuthorizationWizard`, `FullyAutomaticAuthorizationUI`, `FullyAutomaticPropertiesPanel`, `ManualAuthorizationUI`, `AbstractAuthorizationUI`, `AccessTokenInfoPanel`, `OsmPrivilegesPanel` and the dead `OAuthAccessTokenFetcher`. What remains is one "Authorize now" button that runs the browser-based OAuth 2 dance with the parameters currently shown in the panel. The manual path stays: only its window goes, and a token obtained outside JOSM is pasted into the access token field of (d).
    5755
    58 '''(d) Access token becomes a field of the advanced parameters.''' Add "Access Token" to `AdvancedOAuthPropertiesPanel`, next to Client ID, Client Secret, Redirect URI, Authorize URL and Access Token URL. Show the whole group whenever "Use default settings" is unticked, rather than hiding it behind a second checkbox. Pasting a token then stores it against the same server as the parameters it was pasted next to, rather than depending on which of the two keys the caller happened to be holding.
     56'''(d) Access token becomes a field of the advanced parameters.''' Add "Access Token" to `AdvancedOAuthPropertiesPanel`, next to Client ID, Client Secret, Redirect URI, Authorize URL and Access Token URL. Show the whole group whenever "Use default settings" is unticked, rather than hiding it behind a second checkbox. Pasting a token then stores it against the same server as the parameters it was pasted next to, rather than depending on which of the two keys the caller happened to be holding. As the fallback for when everything else breaks, a pasted token must work with nothing else: no client id, no endpoints, no RFC 8414 discovery, no remote control and no browser. Today it cannot, because `OAuth20Token` requires complete `OAuth20Parameters`.
    5957
    60 While doing this, '''settle on one key''' for everything belonging to a server. The token is keyed by host today and the parameters by API URL; with the API URL normalised by #24907 either works, but it must be the same one in both places and in `OsmConnection`.
     58While doing this, '''settle on one key''' for everything belonging to a server: the '''host'''. `JosmPreferencesCredentialAgent` already stores the token, and the parameters it was issued with, under `oauth.access-token.parameters.OAuth20.<host>` — the same prefix `rememberPreferences()` writes to under the API URL, so a configured server ends up with two parameter entries. With the host, `rememberPreferences()` writes the entry the token store already uses, every stored token stays valid, and only custom parameters need reading once from their old key. Removing a token must then remove the token only, not the client id the user entered. The global `oauth.settings.use-default` goes too: "use default settings" simply means that no custom parameters are stored for that host.
    6159
    6260'''(e) Tooltips.''' Each field explains what it holds and where it comes from, e.g.:
    … …  
    6563 * '''Client Secret''' — only needed if the application is registered as confidential. The applications JOSM has built in are public clients and have none.
    6664 * '''Redirect URI''' — must match exactly the redirect URI registered with the application. JOSM listens on `http://127.0.0.1:8111/oauth_authorization`, which needs remote control enabled.
    67  * '''Authorize URL / Access Token URL''' — taken from the server's RFC 8414 metadata when it publishes any; on openstreetmap-website these are `<site>/oauth2/authorize` and `<site>/oauth2/token`. Note `<site>`, not the API URL.
     65 * '''Authorize URL / Access Token URL''' — taken from the server's RFC 8414 metadata when it publishes any; on openstreetmap-website these are `<site>/oauth2/authorize` and `<site>/oauth2/token`. Note `<site>`, not the API URL. When discovery fails they are pre-filled with exactly those, rather than today's `<api url>/authorize`, and stay editable.
    6866 * '''Access Token''' — paste a token issued outside JOSM instead of pressing "Authorize now".
    6967
    … …  
    7472Two smaller things in the same method: `obtainOAuth20Token()` saves the token under `OsmApi.getOsmApi().getServerUrl()` while the caller reads it back with the request URL — harmless today only because the holder reduces both to the host, and another reason to settle (d) — and the `while (done.getCount() >= 0 && counter < 5)` loop condition is always true, so it should just be a bounded `await`.
    7573
    76 == 3. What we would like feedback on ==
     74== 3. Feedback ==
    7775
    78 1. '''Is dropping basic authentication acceptable?''' openstreetmap.org, openhistoricalmap.org and OpenGeofiction no longer need it, and the one other instance we know of can publish the RFC 8414 metadata and use OAuth 2 instead. We cannot survey private deployments, though, and `osm-server.username` / `osm-server.password` may be read by plugins. If it goes, what migration do you want for a profile that still has `osm-server.auth-method=basic` — switch it silently to OAuth 2, or warn once on startup?
    79 2. '''Is deleting the wizard and the manual window acceptable?''' Two of the three procedures are already dead or expert-only, but these are public classes and a plugin may reference them. Is the usual deprecation cycle wanted here, or is removal fine given `@since` churn in this area?
    80 3. '''Host or API URL as the key''' for tokens and parameters — which would you prefer?
    81 4. Should `oauth.settings.use-default` become '''per API URL'''? Today one global flag decides it for every server.
    82 5. '''What should happen when RFC 8414 discovery fails?''' This matters more once basic authentication is gone, because discovery becomes the main way a third-party instance works without a client id built into JOSM. Keep guessing `<api url>/authorize`, which is wrong for every openstreetmap-website instance? Guess `<site>/oauth2/authorize` instead? Or leave the fields empty and tell the user the endpoints must be entered by hand?
    83 6. Would you accept a short '''wiki page for server operators''' saying what an openstreetmap-website instance has to do to work with JOSM: publish `/.well-known/oauth-authorization-server`, register a public client with redirect URI `http://127.0.0.1:8111/oauth_authorization`, and grant the scopes JOSM asks for? We can write it up as part of this work.
     761. '''Is dropping basic authentication acceptable?''' openstreetmap.org, openhistoricalmap.org and OpenGeofiction no longer need it, and the one other instance we know of can publish the RFC 8414 metadata and use OAuth 2 instead. We cannot survey private deployments, though, and `osm-server.username` / `osm-server.password` may be read by plugins. If it goes, what migration do you want for a profile that still has `osm-server.auth-method=basic` — switch it silently to OAuth 2, or warn once on startup? — '''No''': it stays, for experts; see (a).
     772. '''Is deleting the wizard and the manual window acceptable?''' Two of the three procedures are already dead or expert-only, but these are public classes and a plugin may reference them. Is the usual deprecation cycle wanted here, or is removal fine given `@since` churn in this area? — '''A manual path must stay''': it does, as the access token field; see (b)/(c) and (d). Deprecation cycle or removal: '''still open'''.
     783. '''Host or API URL as the key''' for tokens and parameters — which would you prefer? — '''Host'''; see (d).
     794. Should `oauth.settings.use-default` become '''per API URL'''? Today one global flag decides it for every server. — '''Yes''', it falls out of (d).
     805. '''What should happen when RFC 8414 discovery fails?''' This matters most for third-party servers, because discovery is the main way a third-party instance works without a client id built into JOSM. Keep guessing `<api url>/authorize`, which is wrong for every openstreetmap-website instance? Guess `<site>/oauth2/authorize` instead? Or leave the fields empty and tell the user the endpoints must be entered by hand? — '''`<site>/oauth2/…`, editable''', which is the manual fallback of question 2; see (e).
     816. Would you accept a short '''wiki page for server operators''' saying what an openstreetmap-website instance has to do to work with JOSM: publish `/.well-known/oauth-authorization-server`, register a public client with redirect URI `http://127.0.0.1:8111/oauth_authorization`, and grant the scopes JOSM asks for? We can write it up as part of this work. — '''Yes'''.
    8482
    8583== 4. Out of scope ==