From 6058f89460166a76a7eec246c896221ef523fc0f Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 27 Apr 2022 14:32:20 -0400 Subject: [PATCH 1/6] Upgrade to osm-auth v2 which uses OAuth2 to connect to OSM API --- dist/index.html | 12 +++--- index.html | 12 +++--- modules/services/osm.js | 35 +++++++++-------- package.json | 6 +-- test/spec/services/osm.js | 81 +++++++++++++++++++-------------------- 5 files changed, 74 insertions(+), 72 deletions(-) diff --git a/dist/index.html b/dist/index.html index d206b8a3c..3a5813340 100644 --- a/dist/index.html +++ b/dist/index.html @@ -45,13 +45,13 @@ .assetPath('') .apiConnections([ { - 'urlroot': 'https://www.openstreetmap.org', - 'oauth_consumer_key': '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', - 'oauth_secret': 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL' + url: 'https://www.openstreetmap.org', + client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', + client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE' }, { - 'urlroot': 'https://api06.dev.openstreetmap.org', - 'oauth_consumer_key': 'zwQZFivccHkLs3a8Rq5CoS412fE5aPCXDw9DZj7R', - 'oauth_secret': 'aMnOOCwExO2XYtRVWJ1bI9QOdqh1cay2UgpbhA6p' + url: 'https://api06.dev.openstreetmap.org', + client_id: 'zod4KxHLYtOOvr8LTdUIhZqeAtDxzHRoEsaNkMt2pBc', + client_secret: 'wnDUzUidx8CM948E5fgdk89_-IeOOyjfvDhtn0-mX6k' } ]) .containerNode(container); diff --git a/index.html b/index.html index 6b394ede8..b3bf5be7d 100644 --- a/index.html +++ b/index.html @@ -45,13 +45,13 @@ .assetPath('dist/') .apiConnections([ { - 'urlroot': 'https://www.openstreetmap.org', - 'oauth_consumer_key': '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', - 'oauth_secret': 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL' + url: 'https://www.openstreetmap.org', + client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', + client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE' }, { - 'urlroot': 'https://api06.dev.openstreetmap.org', - 'oauth_consumer_key': 'zwQZFivccHkLs3a8Rq5CoS412fE5aPCXDw9DZj7R', - 'oauth_secret': 'aMnOOCwExO2XYtRVWJ1bI9QOdqh1cay2UgpbhA6p' + url: 'https://api06.dev.openstreetmap.org', + client_id: 'zod4KxHLYtOOvr8LTdUIhZqeAtDxzHRoEsaNkMt2pBc', + client_secret: 'wnDUzUidx8CM948E5fgdk89_-IeOOyjfvDhtn0-mX6k' } ]) .containerNode(container); diff --git a/modules/services/osm.js b/modules/services/osm.js index 6a1f80abc..ef221fe90 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -2,26 +2,30 @@ import _throttle from 'lodash-es/throttle'; import { dispatch as d3_dispatch } from 'd3-dispatch'; import { json as d3_json, xml as d3_xml } from 'd3-fetch'; - -import osmAuth from 'osm-auth'; +import { osmAuth } from 'osm-auth'; import RBush from 'rbush'; import { JXON } from '../util/jxon'; import { geoExtent, geoRawMercator, geoVecAdd, geoZoomToScale } from '../geo'; import { osmEntity, osmNode, osmNote, osmRelation, osmWay } from '../osm'; -import { utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilRebind, utilTiler, utilQsString } from '../util'; +import { utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilObjectOmit, utilRebind, utilTiler, utilQsString } from '../util'; var tiler = utilTiler(); var dispatch = d3_dispatch('apiStatusChange', 'authLoading', 'authDone', 'change', 'loading', 'loaded', 'loadedNotes'); + var urlroot = 'https://www.openstreetmap.org'; +var redirectPath = window.location.origin + window.location.pathname; var oauth = osmAuth({ url: urlroot, - oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', - oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL', + client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', + client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE', + scope: 'read_prefs write_prefs write_api read_gpx write_notes', + redirect_uri: redirectPath + 'land.html', loading: authLoading, done: authDone }); + // hardcode default block of Google Maps var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/]; var _tileCache = { toLoad: {}, loaded: {}, inflight: {}, seen: {}, rtree: new RBush() }; @@ -785,7 +789,7 @@ export default { var options = { method: 'PUT', path: '/api/0.6/changeset/create', - options: { header: { 'Content-Type': 'text/xml' } }, + headers: { 'Content-Type': 'text/xml' }, content: JXON.stringify(changeset.asJXON()) }; _changeset.inflight = oauth.xhr( @@ -806,7 +810,7 @@ export default { var options = { method: 'POST', path: '/api/0.6/changeset/' + changesetID + '/upload', - options: { header: { 'Content-Type': 'text/xml' } }, + headers: { 'Content-Type': 'text/xml' }, content: JXON.stringify(changeset.osmChangeJXON(changes)) }; _changeset.inflight = oauth.xhr( @@ -832,7 +836,7 @@ export default { oauth.xhr({ method: 'PUT', path: '/api/0.6/changeset/' + changeset.id + '/close', - options: { header: { 'Content-Type': 'text/xml' } } + headers: { 'Content-Type': 'text/xml' } }, function() { return true; }); } } @@ -1267,14 +1271,13 @@ export default { }, - switch: function(options) { - urlroot = options.urlroot; + switch: function(newOptions) { + urlroot = newOptions.url; - oauth.options(Object.assign({ - url: urlroot, - loading: authLoading, - done: authDone - }, options)); + // Copy the existing options, but omit 'access_token'. + // (if we did preauth, access_token won't work on a different server) + var oldOptions = utilObjectOmit(oauth.options(), 'access_token'); + oauth.options(Object.assign(oldOptions, newOptions)); this.reset(); this.userChangesets(function() {}); // eagerly load user details/changesets @@ -1384,7 +1387,7 @@ export default { that.userChangesets(function() {}); // eagerly load user details/changesets } - return oauth.authenticate(done); + oauth.authenticate(done); }, diff --git a/package.json b/package.json index 03d8e1de5..01d5f5072 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,8 @@ "fast-json-stable-stringify": "2.1.0", "lodash-es": "~4.17.15", "marked": "~4.0.12", - "node-diff3": "3.1.0", - "osm-auth": "1.1.1", + "node-diff3": "~3.1.0", + "osm-auth": "~2.0.0", "pannellum": "2.5.6", "pbf": "^3.2.1", "polygon-clipping": "~0.15.1", @@ -122,4 +122,4 @@ "browserslist": [ "> 0.2%, last 6 major versions, Firefox ESR, maintained node versions" ] -} +} \ No newline at end of file diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index 8299f825e..65675d8a6 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -4,11 +4,10 @@ describe('iD.serviceOsm', function () { function login() { connection.switch({ - urlroot: 'http://www.openstreetmap.org', - oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT', - oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL', - oauth_token: 'foo', - oauth_token_secret: 'foo' + url: 'https://www.openstreetmap.org', + client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', + client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE', + access_token: 'foo' // preauth }); } @@ -28,7 +27,7 @@ describe('iD.serviceOsm', function () { serverXHR = sinon.fakeServer.create(); // authenticated calls use XHR via osm-auth context = iD.coreContext().assetPath('../dist/').init(); connection = context.connection(); - connection.switch({ urlroot: 'http://www.openstreetmap.org' }); + connection.switch({ url: 'https://www.openstreetmap.org' }); connection.reset(); spy = sinon.spy(); }); @@ -54,7 +53,7 @@ describe('iD.serviceOsm', function () { it('changes the connection id every time connection is switched', function () { var cid1 = connection.getConnectionId(); - connection.switch({ urlroot: 'https://api06.dev.openstreetmap.org' }); + connection.switch({ url: 'https://api06.dev.openstreetmap.org' }); var cid2 = connection.getConnectionId(); expect(cid2).to.be.above(cid1); }); @@ -62,11 +61,11 @@ describe('iD.serviceOsm', function () { describe('#changesetURL', function() { it('provides a changeset url', function() { - expect(connection.changesetURL(2)).to.eql('http://www.openstreetmap.org/changeset/2'); + expect(connection.changesetURL(2)).to.eql('https://www.openstreetmap.org/changeset/2'); }); it('allows secure connections', function() { - connection.switch({ urlroot: 'https://www.openstreetmap.org' }); + connection.switch({ url: 'https://www.openstreetmap.org' }); expect(connection.changesetURL(2)).to.eql('https://www.openstreetmap.org/changeset/2'); }); }); @@ -75,47 +74,47 @@ describe('iD.serviceOsm', function () { it('provides a local changesets url', function() { var center = [-74.65, 40.65]; var zoom = 17; - expect(connection.changesetsURL(center, zoom)).to.eql('http://www.openstreetmap.org/history#map=17/40.65000/-74.65000'); + expect(connection.changesetsURL(center, zoom)).to.eql('https://www.openstreetmap.org/history#map=17/40.65000/-74.65000'); }); }); describe('#entityURL', function() { it('provides an entity url for a node', function() { var e = iD.osmNode({id: 'n1'}); - expect(connection.entityURL(e)).to.eql('http://www.openstreetmap.org/node/1'); + expect(connection.entityURL(e)).to.eql('https://www.openstreetmap.org/node/1'); }); it('provides an entity url for a way', function() { var e = iD.osmWay({id: 'w1'}); - expect(connection.entityURL(e)).to.eql('http://www.openstreetmap.org/way/1'); + expect(connection.entityURL(e)).to.eql('https://www.openstreetmap.org/way/1'); }); it('provides an entity url for a relation', function() { var e = iD.osmRelation({id: 'r1'}); - expect(connection.entityURL(e)).to.eql('http://www.openstreetmap.org/relation/1'); + expect(connection.entityURL(e)).to.eql('https://www.openstreetmap.org/relation/1'); }); }); describe('#historyURL', function() { it('provides a history url for a node', function() { var e = iD.osmNode({id: 'n1'}); - expect(connection.historyURL(e)).to.eql('http://www.openstreetmap.org/node/1/history'); + expect(connection.historyURL(e)).to.eql('https://www.openstreetmap.org/node/1/history'); }); it('provides a history url for a way', function() { var e = iD.osmWay({id: 'w1'}); - expect(connection.historyURL(e)).to.eql('http://www.openstreetmap.org/way/1/history'); + expect(connection.historyURL(e)).to.eql('https://www.openstreetmap.org/way/1/history'); }); it('provides a history url for a relation', function() { var e = iD.osmRelation({id: 'r1'}); - expect(connection.historyURL(e)).to.eql('http://www.openstreetmap.org/relation/1/history'); + expect(connection.historyURL(e)).to.eql('https://www.openstreetmap.org/relation/1/history'); }); }); describe('#userURL', function() { it('provides a user url', function() { - expect(connection.userURL('bob')).to.eql('http://www.openstreetmap.org/user/bob'); + expect(connection.userURL('bob')).to.eql('https://www.openstreetmap.org/user/bob'); }); }); @@ -127,13 +126,13 @@ describe('iD.serviceOsm', function () { describe('#switch', function() { it('changes the URL', function() { - connection.switch({ urlroot: 'http://example.com' }); - expect(connection.changesetURL(1)).to.equal('http://example.com/changeset/1'); + connection.switch({ url: 'https://example.com' }); + expect(connection.changesetURL(1)).to.equal('https://example.com/changeset/1'); }); it('emits a change event', function() { connection.on('change', spy); - connection.switch({ urlroot: 'http://example.com' }); + connection.switch({ url: 'https://example.com' }); expect(spy).to.have.been.calledOnce; }); }); @@ -152,7 +151,7 @@ describe('iD.serviceOsm', function () { '}'; it('returns an object', function(done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: response, status: 200, headers: { 'Content-Type': 'application/json' } @@ -166,12 +165,12 @@ describe('iD.serviceOsm', function () { }); it('retries an authenticated call unauthenticated if 400 Bad Request', function (done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: response, status: 200, headers: { 'Content-Type': 'application/json' } }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org' + path, + serverXHR.respondWith('GET', 'https://www.openstreetmap.org' + path, [400, { 'Content-Type': 'text/plain' }, 'Bad Request']); login(); @@ -189,12 +188,12 @@ describe('iD.serviceOsm', function () { }); it('retries an authenticated call unauthenticated if 401 Unauthorized', function (done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: response, status: 200, headers: { 'Content-Type': 'application/json' } }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org' + path, + serverXHR.respondWith('GET', 'https://www.openstreetmap.org' + path, [401, { 'Content-Type': 'text/plain' }, 'Unauthorized']); login(); @@ -211,12 +210,12 @@ describe('iD.serviceOsm', function () { }); it('retries an authenticated call unauthenticated if 403 Forbidden', function (done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: response, status: 200, headers: { 'Content-Type': 'application/json' } }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org' + path, + serverXHR.respondWith('GET', 'https://www.openstreetmap.org' + path, [403, { 'Content-Type': 'text/plain' }, 'Forbidden']); login(); @@ -234,7 +233,7 @@ describe('iD.serviceOsm', function () { it('dispatches change event if 509 Bandwidth Limit Exceeded', function (done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: 'Bandwidth Limit Exceeded', status: 509, headers: { 'Content-Type': 'text/plain' } @@ -250,7 +249,7 @@ describe('iD.serviceOsm', function () { }); it('dispatches change event if 429 Too Many Requests', function (done) { - fetchMock.mock('http://www.openstreetmap.org' + path, { + fetchMock.mock('https://www.openstreetmap.org' + path, { body: '429 Too Many Requests', status: 429, headers: { 'Content-Type': 'text/plain' } @@ -347,7 +346,7 @@ describe('iD.serviceOsm', function () { '}'; it('loads a node', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/node/1.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1.json', { body: nodeResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -362,7 +361,7 @@ describe('iD.serviceOsm', function () { }); it('loads a way', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/way/1/full.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/way/1/full.json', { body: wayResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -377,7 +376,7 @@ describe('iD.serviceOsm', function () { }); it('does not ignore repeat requests', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/node/1.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1.json', { body: wayResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -416,7 +415,7 @@ describe('iD.serviceOsm', function () { '}'; it('loads a node', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/node/1/1.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1/1.json', { body: nodeResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -431,7 +430,7 @@ describe('iD.serviceOsm', function () { }); it('loads a way', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/way/1/1.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/way/1/1.json', { body: wayResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -446,7 +445,7 @@ describe('iD.serviceOsm', function () { }); it('does not ignore repeat requests', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/0.6/node/1/1.json', { + fetchMock.mock('https://www.openstreetmap.org/api/0.6/node/1/1.json', { body: nodeResponse, status: 200, headers: { 'Content-Type': 'application/json' } @@ -510,7 +509,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); @@ -539,7 +538,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); @@ -569,7 +568,7 @@ describe('iD.serviceOsm', function () { done(); }); - serverXHR.respondWith('GET', 'http://www.openstreetmap.org/api/0.6/changesets?user=1', + serverXHR.respondWith('GET', 'https://www.openstreetmap.org/api/0.6/changesets?user=1', [200, { 'Content-Type': 'text/xml' }, changesetsXML]); serverXHR.respond(); }); @@ -768,7 +767,7 @@ describe('iD.serviceOsm', function () { describe('#status', function() { it('gets API status', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/capabilities', { + fetchMock.mock('https://www.openstreetmap.org/api/capabilities', { body: capabilitiesXML, status: 200, headers: { 'Content-Type': 'text/xml' } @@ -785,7 +784,7 @@ describe('iD.serviceOsm', function () { describe('#imageryBlocklists', function() { it('updates imagery blocklists', function(done) { - fetchMock.mock('http://www.openstreetmap.org/api/capabilities', { + fetchMock.mock('https://www.openstreetmap.org/api/capabilities', { body: capabilitiesXML, status: 200, headers: { 'Content-Type': 'text/xml' } @@ -802,4 +801,4 @@ describe('iD.serviceOsm', function () { }); }); -}); \ No newline at end of file +}); From 43fe6e9579cbaad6f17b3cbf9425d47395d7980e Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 28 Apr 2022 11:18:29 -0400 Subject: [PATCH 2/6] Update account component - Add ability to both login and logout --- modules/ui/account.js | 124 ++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 53 deletions(-) diff --git a/modules/ui/account.js b/modules/ui/account.js index 64b879dea..4931961cb 100644 --- a/modules/ui/account.js +++ b/modules/ui/account.js @@ -1,76 +1,94 @@ import { t } from '../core/localizer'; import { svgIcon } from '../svg/icon'; + export function uiAccount(context) { - var osm = context.connection(); + const osm = context.connection(); - function update(selection) { - if (!osm) return; + function updateUserDetails(selection) { + if (!osm) return; - if (!osm.authenticated()) { - selection.selectAll('.userLink, .logoutLink') - .classed('hide', true); - return; - } + if (!osm.authenticated()) { // logged out + render(selection, null); + } else { + osm.userDetails((err, user) => render(selection, user)); + } + } - osm.userDetails(function(err, details) { - var userLink = selection.select('.userLink'), - logoutLink = selection.select('.logoutLink'); - userLink.html(''); - logoutLink.html(''); + function render(selection, user) { + let userInfo = selection.select('.userInfo'); + let loginLogout = selection.select('.loginLogout'); - if (err || !details) return; + if (user) { + userInfo + .html('') + .classed('hide', false); - selection.selectAll('.userLink, .logoutLink') - .classed('hide', false); + let userLink = userInfo + .append('a') + .attr('href', osm.userURL(user.display_name)) + .attr('target', '_blank'); - // Link - var userLinkA = userLink.append('a') - .attr('href', osm.userURL(details.display_name)) - .attr('target', '_blank'); + // Add user's image or placeholder + if (user.image_url) { + userLink.append('img') + .attr('class', 'icon pre-text user-icon') + .attr('src', user.image_url); + } else { + userLink + .call(svgIcon('#iD-icon-avatar', 'pre-text light')); + } - // Add thumbnail or dont - if (details.image_url) { - userLinkA.append('img') - .attr('class', 'icon pre-text user-icon') - .attr('src', details.image_url); - } else { - userLinkA - .call(svgIcon('#iD-icon-avatar', 'pre-text light')); - } + // Add user name + userLink.append('span') + .attr('class', 'label') + .html(user.display_name); - // Add user name - userLinkA.append('span') - .attr('class', 'label') - .text(details.display_name); + // show "Log Out" + loginLogout + .classed('hide', false) + .select('a') + .text(t('logout')) + .on('click', e => { + e.preventDefault(); + osm.logout(); + }); - logoutLink.append('a') - .attr('class', 'logout') - .attr('href', '#') - .call(t.append('logout')) - .on('click.logout', function(d3_event) { - d3_event.preventDefault(); - osm.logout(); - }); + } else { // no user + userInfo + .html('') + .classed('hide', true); + + // show "Log In" + loginLogout + .classed('hide', false) + .select('a') + .text(t('login')) + .on('click', e => { + e.preventDefault(); + osm.authenticate(); }); } + } - return function(selection) { + return function(selection) { + if (!osm) return; - selection.append('li') - .attr('class', 'userLink') - .classed('hide', true); + selection.append('li') + .attr('class', 'userInfo') + .classed('hide', true); - selection.append('li') - .attr('class', 'logoutLink') - .classed('hide', true); + selection.append('li') + .attr('class', 'loginLogout') + .classed('hide', true) + .append('a') + .attr('href', '#'); + + osm.on('change.account', () => updateUserDetails(selection)); + updateUserDetails(selection); + }; - if (osm) { - osm.on('change.account', function() { update(selection); }); - update(selection); - } - }; } From 34a2af0330aa211a81d148580a0a7ce819078cf7 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 28 Apr 2022 13:13:07 -0400 Subject: [PATCH 3/6] Give user the opportunity to switch users when logging out OAuth2's idea of "logout" is just to get rid of the bearer token. If we try to "login" again, it will just grab the token again. What a user probably _really_ expects is to logout of OSM so that they can switch users. --- modules/services/osm.js | 5 +++++ modules/ui/account.js | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/services/osm.js b/modules/services/osm.js index ef221fe90..ed30a3bbb 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -568,6 +568,11 @@ export default { }, + getUrlRoot: function() { + return urlroot; + }, + + changesetURL: function(changesetID) { return urlroot + '/changeset/' + changesetID; }, diff --git a/modules/ui/account.js b/modules/ui/account.js index 4931961cb..2d6203d70 100644 --- a/modules/ui/account.js +++ b/modules/ui/account.js @@ -54,6 +54,7 @@ export function uiAccount(context) { .on('click', e => { e.preventDefault(); osm.logout(); + tryLogout(); }); } else { // no user @@ -74,6 +75,29 @@ export function uiAccount(context) { } + // OAuth2's idea of "logout" is just to get rid of the bearer token. + // If we try to "login" again, it will just grab the token again. + // What a user probably _really_ expects is to logout of OSM so that they can switch users. + function tryLogout() { + if (!osm) return; + + const url = osm.getUrlRoot() + '/logout?referer=%2Flogin'; + // Create a 600x550 popup window in the center of the screen + const w = 600; + const h = 550; + const settings = [ + ['width', w], + ['height', h], + ['left', window.screen.width / 2 - w / 2], + ['top', window.screen.height / 2 - h / 2], + ] + .map(x => x.join('=')) + .join(','); + + window.open(url, '_blank', settings); + } + + return function(selection) { if (!osm) return; From 280acfa661bd45ab01beded1c401f759559ae211 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 2 Jun 2022 14:46:11 +0200 Subject: [PATCH 4/6] Replace RapiD credentials with iD credentials --- dist/index.html | 8 ++++---- index.html | 10 +++++----- modules/services/osm.js | 4 ++-- test/spec/services/osm.js | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dist/index.html b/dist/index.html index 3a5813340..673dcc29f 100644 --- a/dist/index.html +++ b/dist/index.html @@ -46,12 +46,12 @@ .apiConnections([ { url: 'https://www.openstreetmap.org', - client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', - client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE' + client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', + client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q' }, { url: 'https://api06.dev.openstreetmap.org', - client_id: 'zod4KxHLYtOOvr8LTdUIhZqeAtDxzHRoEsaNkMt2pBc', - client_secret: 'wnDUzUidx8CM948E5fgdk89_-IeOOyjfvDhtn0-mX6k' + client_id: 'Ee1wWJ6UlpERbF6BfTNOpwn0R8k_06mvMXdDUkeHMgw', + client_secret: 'OnfWFC-JkZNHyYdr_viNn_h_RTZXRslKcUxllOXqf5g' } ]) .containerNode(container); diff --git a/index.html b/index.html index b3bf5be7d..dae23ef65 100644 --- a/index.html +++ b/index.html @@ -46,12 +46,12 @@ .apiConnections([ { url: 'https://www.openstreetmap.org', - client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', - client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE' + client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', + client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q' }, { url: 'https://api06.dev.openstreetmap.org', - client_id: 'zod4KxHLYtOOvr8LTdUIhZqeAtDxzHRoEsaNkMt2pBc', - client_secret: 'wnDUzUidx8CM948E5fgdk89_-IeOOyjfvDhtn0-mX6k' + client_id: 'Ee1wWJ6UlpERbF6BfTNOpwn0R8k_06mvMXdDUkeHMgw', + client_secret: 'OnfWFC-JkZNHyYdr_viNn_h_RTZXRslKcUxllOXqf5g' } ]) .containerNode(container); @@ -67,4 +67,4 @@ } - + \ No newline at end of file diff --git a/modules/services/osm.js b/modules/services/osm.js index ed30a3bbb..aa47d180b 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -18,8 +18,8 @@ var urlroot = 'https://www.openstreetmap.org'; var redirectPath = window.location.origin + window.location.pathname; var oauth = osmAuth({ url: urlroot, - client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', - client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE', + client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', + client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q', scope: 'read_prefs write_prefs write_api read_gpx write_notes', redirect_uri: redirectPath + 'land.html', loading: authLoading, diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index 65675d8a6..bad227032 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -5,8 +5,8 @@ describe('iD.serviceOsm', function () { function login() { connection.switch({ url: 'https://www.openstreetmap.org', - client_id: 'O3g0mOUuA2WY5Fs826j5tP260qR3DDX7cIIE2R2WWSc', - client_secret: 'b4aeHD1cNeapPPQTrvpPoExqQRjybit6JBlNnxh62uE', + client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', + client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q', access_token: 'foo' // preauth }); } From ae8013c7cb2c88956bba3f3c2926f33e14da9da4 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 2 Jun 2022 14:53:43 +0200 Subject: [PATCH 5/6] use 127.0.0.1 instead of localhost for dev usage as oauth2 does only allow 127.0.0.1 for non https connections see https://wiki.openstreetmap.org/wiki/OAuth#OAuth_2.0_2 --- CONTRIBUTING.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9695a3885..fe95e28ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -394,7 +394,7 @@ In your local copy, make a branch for this change using a descriptive branch nam Make your changes to source files under `modules/`. The `iD.js` and `iD.min.js` files in this project are autogenerated - don't edit them. -1. Try your change locally. Run `npm start` and visit `localhost:8080` in a browser. +1. Try your change locally. Run `npm start` and visit `http://127.0.0.1:8080` in a browser. 2. Run lint and tests with `npm test`. 3. If you feel like it, append a line describing your changes to the project's [changelog](https://github.com/openstreetmap/iD/blob/develop/CHANGELOG.md). 4. Commit your changes with an informative commit message. diff --git a/README.md b/README.md index 55ff0e433..66bf34e00 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ If you want to add in the full history later on, perhaps to run `git blame` or ` 2. Run `npm install` 3. Run `npm run all` 3. Run `npm start` -4. Open `http://localhost:8080/` in a web browser +4. Open `http://127.0.0.1:8080/` in a web browser For guidance on building a packaged version, running tests, and contributing to development, see [CONTRIBUTING.md](CONTRIBUTING.md). From eb1e1c47fdfa2b7064e9e8cf69772ec626b52209 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 2 Jun 2022 15:12:20 +0200 Subject: [PATCH 6/6] update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a10b998c0..f3f046d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ _Breaking developer changes, which may affect downstream projects or sites that #### :newspaper: News * Drop legacy support for Internet Explorer 11 ([#8811]) +* Use OAuth2 for authentication with OSM API ([#9134], thanks [@bhousel] and [@dakotabenjamin]) #### :white_check_mark: Validation * Handle indoor features like buildings when checking for crossing ways ([#8944]) #### :bug: Bugfixes @@ -66,6 +67,7 @@ _Breaking developer changes, which may affect downstream projects or sites that #### Other * Redact more API tokens from custom imagery sources in changeset metadata tags ([#8976], thanks [@k-yle]) * New Bing imagery API key and limit tiles vintage API requests ([#9133], thanks [@mbrzakovic]) +* Change authentication #### :hammer: Development * Switch build system to [esbuild](https://esbuild.github.io/) for much faster builds ([#8774], thanks [@mbrzakovic] and [@bhousel]) * Upgrade dependencies: maki to `v7.1`, `fontawesome` to `v6.1`, `d3` to `v7.4`, `node-diff` to `v3.1`, `mocha` to `v9.2`, `svg-sprite` to `v1.5.4`, `marked` to `v4.0`, `temaki` to `v5.1`, `mapillary-js` to `v4.1` @@ -88,8 +90,9 @@ _Breaking developer changes, which may affect downstream projects or sites that [#9118]: https://github.com/openstreetmap/iD/issues/9118 [#9124]: https://github.com/openstreetmap/iD/pull/9124 [#9133]: https://github.com/openstreetmap/iD/pull/9133 +[#9134]: https://github.com/openstreetmap/iD/pull/9134 [@wcedmisten]: https://github.com/wcedmisten - +[@dakotabenjamin]: https://github.com/dakotabenjamin # 2.20.4 ##### 2022-Feb-03