From 44e3703f05dc4e26c9426236ca8829d0066340d2 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 26 Apr 2024 16:03:24 -0400 Subject: [PATCH] Remove any extra quotes that were stored with legacy tokens (closes #129) --- CHANGELOG.md | 11 +++++++++++ dist/osm-auth.cjs | 18 +++++++++++++----- dist/osm-auth.cjs.map | 4 ++-- dist/osm-auth.iife.js | 2 +- dist/osm-auth.iife.js.map | 6 +++--- src/osm-auth.mjs | 17 ++++++++++++++--- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 289174f..04ea8f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,17 @@ _Breaking changes, which may affect downstream projects, are marked with a_ ⚠ [#xxx]: https://github.com/osmlab/osm-auth/issues/xxx --> +## 2.5.0 +##### 2024-Apr-26 +* Remove any extra quotes that were stored with legacy tokens ([#129]) +* Allow locale to be passed to login page ([#23], [#130], thanks [@k-yle]) + +[#23]: https://github.com/osmlab/osm-auth/issues/23 +[#129]: https://github.com/osmlab/osm-auth/issues/129 +[#130]: https://github.com/osmlab/osm-auth/issues/130 +[@k-yle]: https://github.com/k-yle + + ## 2.4.0 ##### 2024-Jan-04 * Remove `store` dependency ([#126]) diff --git a/dist/osm-auth.cjs b/dist/osm-auth.cjs index df0bedd..1822ada 100644 --- a/dist/osm-auth.cjs +++ b/dist/osm-auth.cjs @@ -37,10 +37,17 @@ function osmAuth(o) { }; } function token(k, v) { - if (arguments.length === 1) - return _store.getItem(o.url + k); - else if (arguments.length === 2) - return _store.setItem(o.url + k, v); + var key = o.url + k; + if (arguments.length === 1) { + var val = _store.getItem(key) || ""; + return val.replace(/"/g, ""); + } else if (arguments.length === 2) { + if (v) { + return _store.setItem(key, v); + } else { + return _store.removeItem(key); + } + } } oauth.authenticated = function() { return !!token("oauth2_access_token"); @@ -123,7 +130,8 @@ function osmAuth(o) { scope: o.scope, state, code_challenge: pkce.code_challenge, - code_challenge_method: pkce.code_challenge_method + code_challenge_method: pkce.code_challenge_method, + locale: o.locale || "" }); if (o.singlepage) { if (_store.isMocked) { diff --git a/dist/osm-auth.cjs.map b/dist/osm-auth.cjs.map index bc6e70f..9370a2d 100644 --- a/dist/osm-auth.cjs.map +++ b/dist/osm-auth.cjs.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/osm-auth.mjs"], - "sourcesContent": ["\n/**\n * osmAuth\n * Easy authentication with OpenStreetMap over OAuth 2.0.\n * @module\n *\n * @param o `Object` containing options:\n * @param o.scope OAuth2 scopes requested (e.g. \"read_prefs write_api\")\n * @param o.client_id OAuth2 client ID\n * @param o.redirect_uri OAuth2 redirect URI (e.g. \"http://127.0.0.1:8080/land.html\")\n * @param o.access_token Can pre-authorize with an OAuth2 bearer token if you have one\n * @param o.apiUrl A base url for the OSM API (default: \"https://api.openstreetmap.org\")\n * @param o.url A base url for the OAuth2 handshake (default: \"https://www.openstreetmap.org\")\n * @param o.auto If `true`, attempt to authenticate automatically when calling `.xhr()` or `.fetch()` (default: `false`)\n * @param o.singlepage If `true`, use page redirection instead of a popup (default: `false`)\n * @param o.loading Function called when auth-related xhr calls start\n * @param o.done Function called when auth-related xhr calls end\n * @return `self`\n */\nexport function osmAuth(o) {\n var oauth = {};\n\n // Mock localStorage if needed.\n // Note that accessing localStorage may throw a `SecurityError`, so wrap in a try/catch.\n var _store = null;\n try {\n _store = window.localStorage;\n } catch (e) {\n var _mock = new Map();\n _store = {\n isMocked: true,\n hasItem: (k) => _mock.has(k),\n getItem: (k) => _mock.get(k),\n setItem: (k, v) => _mock.set(k, v),\n removeItem: (k) => _mock.delete(k),\n clear: () => _mock.clear()\n };\n }\n\n /**\n * token\n * Get/Set tokens. These are prefixed with the base URL so that `osm-auth`\n * can be used with multiple APIs and the keys in `localStorage` will not clash\n * @param {string} k key\n * @param {string?} v value\n * @return {string?} If getting, returns the stored value or `null`. If setting, returns `undefined`.\n */\n function token(k, v) {\n if (arguments.length === 1) return _store.getItem(o.url + k);\n else if (arguments.length === 2) return _store.setItem(o.url + k, v);\n }\n\n\n /**\n * authenticated\n * Test whether the user is currently authenticated\n *\n * @return {boolean} `true` if authenticated, `false` if not\n */\n oauth.authenticated = function() {\n return !!token('oauth2_access_token');\n };\n\n\n /**\n * logout\n * Removes any stored authentication tokens (legacy OAuth1 tokens too)\n *\n * @return `self`\n */\n oauth.logout = function () {\n token('oauth2_access_token', ''); // OAuth2\n token('oauth_token', ''); // OAuth1\n token('oauth_token_secret', ''); // OAuth1\n token('oauth_request_token_secret', ''); // OAuth1\n return oauth;\n };\n\n\n /**\n * authenticate\n * First logs out, then runs the authentiation flow, finally calls the callback.\n * TODO: detect lack of click event (probably can settimeout it)\n *\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.authenticate = function(callback) {\n if (oauth.authenticated()) {\n callback(null, oauth);\n return;\n }\n\n oauth.logout();\n\n _preopenPopup(function(error, popup) {\n if (error) {\n callback(error);\n } else {\n _generatePkceChallenge(function(pkce) {\n _authenticate(pkce, popup, callback);\n });\n }\n });\n };\n\n\n /**\n * authenticateAsync\n * Promisified version of `authenticate`\n * @return {Promise} Promise settled with whatever `_authenticate` did\n */\n oauth.authenticateAsync = function() {\n if (oauth.authenticated()) {\n return Promise.resolve(oauth);\n }\n\n oauth.logout();\n\n return new Promise((resolve, reject) => {\n var errback = (err, result) => {\n if (err) {\n reject(err);\n } else {\n resolve(result);\n }\n };\n\n _preopenPopup((error, popup) => {\n if (error) {\n errback(error);\n } else {\n _generatePkceChallenge(pkce => _authenticate(pkce, popup, errback));\n }\n });\n });\n };\n\n\n /**\n * opens an empty popup to be later used for the authentication page\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n function _preopenPopup(callback) {\n if (o.singlepage) {\n callback(null, undefined);\n return;\n }\n\n // Create a 550x610 popup window in the center of the screen\n var w = 550;\n var h = 610;\n var settings = [\n ['width', w],\n ['height', h],\n ['left', window.screen.width / 2 - w / 2],\n ['top', window.screen.height / 2 - h / 2],\n ]\n .map(function (x) { return x.join('='); })\n .join(',');\n var popup = window.open('about:blank', 'oauth_window', settings);\n if (popup) {\n callback(null, popup);\n } else {\n var error = new Error('Popup was blocked');\n error.status = 'popup-blocked';\n callback(error);\n }\n }\n\n\n /**\n * _authenticate\n * internal authenticate\n *\n * @param {Object} pkce Object containing PKCE code challenge properties\n * @param {Window} popup Popup Window to use for the authentication page, should be undefined when using singlepage mode\n * @param {function} callback Errback-style callback that accepts `(err, result)`\n */\n function _authenticate(pkce, popup, callback) {\n var state = generateState();\n\n // ## Request authorization to access resources from the user\n // and receive authorization code\n var url =\n o.url +\n '/oauth2/authorize?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n response_type: 'code',\n scope: o.scope,\n state: state,\n code_challenge: pkce.code_challenge,\n code_challenge_method: pkce.code_challenge_method,\n });\n\n if (o.singlepage) {\n if (_store.isMocked) {\n // in singlepage mode, PKCE requires working non-volatile storage\n var error = new Error('localStorage unavailable, but required in singlepage mode');\n error.status = 'pkce-localstorage-unavailable';\n callback(error);\n return;\n }\n var params = utilStringQs(window.location.search.slice(1));\n if (params.code) {\n oauth.bootstrapToken(params.code, callback);\n } else {\n // save OAuth2 state and PKCE challenge in local storage, for later use\n // in the `/oauth/token` request\n token('oauth2_state', state);\n token('oauth2_pkce_code_verifier', pkce.code_verifier);\n window.location = url;\n }\n } else {\n oauth.popupWindow = popup;\n popup.location = url;\n }\n\n // Called by a function in the redirect URL page, in the popup window. The\n // window closes itself.\n window.authComplete = function (url) {\n var params = utilStringQs(url.split('?')[1]);\n if (params.state !== state) {\n error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n _getAccessToken(params.code, pkce.code_verifier, accessTokenDone);\n delete window.authComplete;\n };\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n }\n\n\n /**\n * _getAccessToken\n * The client requests an access token by authenticating with the\n * authorization server and presenting the `auth_code`, brought\n * in from a function call on a landing page popup.\n * @param {string} auth_code\n * @param {string} code_verifier\n * @param {function} accessTokenDone Errback-style callback `(err, result)`, called when complete\n */\n function _getAccessToken(auth_code, code_verifier, accessTokenDone) {\n var url =\n o.url +\n '/oauth2/token?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n grant_type: 'authorization_code',\n code: auth_code,\n code_verifier: code_verifier\n });\n\n // The authorization server authenticates the client and validates\n // the authorization grant, and if valid, issues an access token.\n oauth.rawxhr('POST', url, null, null, null, accessTokenDone);\n o.loading();\n }\n\n\n /**\n * bringPopupWindowToFront\n * Tries to bring an existing authentication popup to the front.\n *\n * @return {boolean} `true` if it succeeded, `false` if not\n */\n oauth.bringPopupWindowToFront = function() {\n var broughtPopupToFront = false;\n try {\n // This may cause a cross-origin error:\n // `DOMException: Blocked a frame with origin \"...\" from accessing a cross-origin frame.`\n if (oauth.popupWindow && !oauth.popupWindow.closed) {\n oauth.popupWindow.focus();\n broughtPopupToFront = true;\n }\n } catch (err) {\n // Bringing popup window to front failed (probably because of the cross-origin error mentioned above)\n }\n return broughtPopupToFront;\n };\n\n\n /**\n * bootstrapToken\n * The authorization code is a temporary code that a client can exchange for an access token.\n * If using this library in single-page mode, you'll need to call this once your application\n * has an `auth_code` and wants to get an access_token.\n *\n * @param {string} auth_code The OAuth2 `auth_code`\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.bootstrapToken = function(auth_code, callback) {\n var state = token('oauth2_state');\n token('oauth2_state', '');\n var params = utilStringQs(window.location.search.slice(1));\n if (params.state !== state) {\n var error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n var code_verifier = token('oauth2_pkce_code_verifier');\n token('oauth2_pkce_code_verifier', '');\n _getAccessToken(auth_code, code_verifier, accessTokenDone);\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n };\n\n\n /**\n * fetch\n * A `fetch` wrapper that includes the Authorization header if the user is authenticated.\n * https://developer.mozilla.org/en-US/docs/Web/API/fetch\n *\n * @param {string} resource Resource passed to `fetch`\n * @param {Object} options Options passed to `fetch`\n * @return {Promise} Promise that wraps `authenticateAsync` then `fetch`\n */\n oauth.fetch = function(resource, options) {\n if (oauth.authenticated()) {\n return _doFetch();\n } else {\n if (o.auto) {\n return oauth.authenticateAsync().then(_doFetch);\n } else {\n return Promise.reject(new Error('not authenticated'));\n }\n }\n\n function _doFetch() {\n options = options || {};\n if (!options.headers) {\n options.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n }\n options.headers.Authorization = 'Bearer ' + token('oauth2_access_token');\n return fetch(resource, options);\n }\n };\n\n\n /**\n * xhr\n * A `XMLHttpRequest` wrapper that does authenticated calls if the user has logged in.\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param {Object} options\n * @param options.method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param options.prefix If `true` path contains a path, if `false` path contains the full url\n * @param options.path The URL path (e.g. \"/api/0.6/user/details\") (or full url, if `prefix`=`false`)\n * @param options.content Passed to `xhr.send`\n * @param options.headers `Object` containing request headers\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return {XMLHttpRequest} `XMLHttpRequest` if authenticated, otherwise `null`\n */\n oauth.xhr = function (options, callback) {\n if (oauth.authenticated()) {\n return _doXHR();\n } else {\n if (o.auto) {\n oauth.authenticate(_doXHR);\n return;\n } else {\n callback('not authenticated', null);\n return;\n }\n }\n\n function _doXHR() {\n var url = options.prefix !== false ? (o.apiUrl + options.path) : options.path;\n return oauth.rawxhr(\n options.method,\n url,\n token('oauth2_access_token'),\n options.content,\n options.headers,\n done\n );\n }\n\n function done(err, xhr) {\n if (err) {\n callback(err);\n } else if (xhr.responseXML) {\n callback(err, xhr.responseXML);\n } else {\n callback(err, xhr.response);\n }\n }\n };\n\n\n /**\n * rawxhr\n * Creates the XMLHttpRequest set up with a header and response handling\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param url Passed to `xhr.open`\n * @param access_token OAuth2 bearer token\n * @param data Passed to `xhr.send`\n * @param headers `Object` containing request headers\n * @param callback An \"errback\"-style callback (`err`, `result`), called when complete\n * @return `XMLHttpRequest`\n */\n oauth.rawxhr = function(method, url, access_token, data, headers, callback) {\n headers = headers || { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (access_token) {\n headers.Authorization = 'Bearer ' + access_token;\n }\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (4 === xhr.readyState && 0 !== xhr.status) {\n if (/^20\\d$/.test(xhr.status)) { // a 20x status code - OK\n callback(null, xhr);\n } else {\n callback(xhr, null);\n }\n }\n };\n xhr.onerror = function (e) {\n callback(e, null);\n };\n\n xhr.open(method, url, true);\n for (var h in headers) xhr.setRequestHeader(h, headers[h]);\n\n xhr.send(data);\n return xhr;\n };\n\n\n /**\n * preauth\n * Pre-authorize this object, if we already have access token from the start\n *\n * @param {Object} val Object containing `access_token` property\n * @return `self`\n */\n oauth.preauth = function(val) {\n if (val && val.access_token) {\n token('oauth2_access_token', val.access_token);\n }\n return oauth;\n };\n\n\n /**\n * options (getter / setter)\n * If passed with no arguments, just return the options\n * If passed an Object, set the options then attempt to pre-authorize\n *\n * @param val? Object containing options\n * @return current `options` (if getting), or `self` (if setting)\n */\n oauth.options = function(val) {\n if (!arguments.length) return o;\n\n o = val;\n o.apiUrl = o.apiUrl || 'https://api.openstreetmap.org';\n o.url = o.url || 'https://www.openstreetmap.org';\n o.auto = o.auto || false;\n o.singlepage = o.singlepage || false;\n\n // Optional loading and loading-done functions for nice UI feedback.\n // by default, no-ops\n o.loading = o.loading || function () {};\n o.done = o.done || function () {};\n return oauth.preauth(o);\n };\n\n\n // Everything below here is initialization/setup code\n // Handle options and attempt to pre-authorize\n oauth.options(o);\n\n return oauth;\n}\n\n\n/**\n * utilQsString\n * Transforms object of `key=value` pairs into query string\n * @param {Object} Object of `key=value` pairs\n * @returns {string} query string\n */\nfunction utilQsString(obj) {\n return Object.keys(obj)\n .filter(function(key) {\n return obj[key] !== undefined;\n })\n .sort()\n .map(function(key) {\n return (encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));\n })\n .join('&');\n}\n\n/**\n * utilStringQs\n * Transforms query string into object of `key=value` pairs\n * @param {string} query string\n * @returns {Object} Object of `key=value` pairs\n */\nfunction utilStringQs(str) {\n var i = 0; // advance past any leading '?' or '#' characters\n while (i < str.length && (str[i] === '?' || str[i] === '#')) i++;\n str = str.slice(i);\n\n return str.split('&').reduce(function(obj, pair) {\n var parts = pair.split('=');\n if (parts.length === 2) {\n obj[parts[0]] = decodeURIComponent(parts[1]);\n }\n return obj;\n }, {});\n}\n\n\n/**\n * supportsWebCryptoAPI\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n * @returns {boolean} `true` if WebCryptoAPI is available\n */\nfunction supportsWebCryptoAPI() {\n return window && window.crypto\n && window.crypto.getRandomValues\n && window.crypto.subtle\n && window.crypto.subtle.digest;\n}\n\n\n/**\n * Generates a challenge/verifier pair for PKCE.\n * If the browser does not support the WebCryptoAPI, the \"plain\" method is\n * used as a fallback instead of a SHA-256 hash.\n * @param {callback} callback called with the result of the generated PKCE challenge\n */\nfunction _generatePkceChallenge(callback) {\n var code_verifier;\n if (supportsWebCryptoAPI()) {\n // generate a random code_verifier\n // https://datatracker.ietf.org/doc/html/rfc7636#section-7.1\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n code_verifier = base64(random.buffer);\n var verifier = Uint8Array.from(Array.from(code_verifier).map(function(char) {\n return char.charCodeAt(0);\n }));\n\n // generate challenge for code verifier\n window.crypto.subtle.digest('SHA-256', verifier).then(function(hash) {\n var code_challenge = base64(hash);\n\n callback({\n code_challenge: code_challenge,\n code_verifier: code_verifier,\n code_challenge_method: 'S256'\n });\n });\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n code_verifier = '';\n for (var i=0; i<64; i++) {\n code_verifier += chars[Math.floor(Math.random() * chars.length)];\n }\n callback({\n code_verifier: code_verifier,\n code_challenge: code_verifier,\n code_challenge_method: 'plain',\n });\n }\n}\n\n\n/**\n * Returns a random state to be used as the \"state\" of the OAuth2 authentication\n * See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12\n */\nfunction generateState() {\n var state;\n if (supportsWebCryptoAPI()) {\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n state = base64(random.buffer);\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n state = '';\n for (var i=0; i<64; i++) {\n state += chars[Math.floor(Math.random() * chars.length)];\n }\n }\n return state;\n}\n\n\n/**\n * base64\n * Converts binary buffer to base64 encoded string, as used in rfc7636\n * @param {ArrayBuffer} buffer\n * @returns {string} base64 encoded\n */\nfunction base64(buffer) {\n return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))\n .replace(/\\//g, '_')\n .replace(/\\+/g, '-')\n .replace(/[=]/g, '');\n}\n"], - "mappings": "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", + "sourcesContent": ["\n/**\n * osmAuth\n * Easy authentication with OpenStreetMap over OAuth 2.0.\n * @module\n *\n * @param o `Object` containing options:\n * @param o.scope OAuth2 scopes requested (e.g. \"read_prefs write_api\")\n * @param o.client_id OAuth2 client ID\n * @param o.redirect_uri OAuth2 redirect URI (e.g. \"http://127.0.0.1:8080/land.html\")\n * @param o.access_token Can pre-authorize with an OAuth2 bearer token if you have one\n * @param o.apiUrl A base url for the OSM API (default: \"https://api.openstreetmap.org\")\n * @param o.url A base url for the OAuth2 handshake (default: \"https://www.openstreetmap.org\")\n * @param o.auto If `true`, attempt to authenticate automatically when calling `.xhr()` or `.fetch()` (default: `false`)\n * @param o.singlepage If `true`, use page redirection instead of a popup (default: `false`)\n * @param o.loading Function called when auth-related xhr calls start\n * @param o.done Function called when auth-related xhr calls end\n * @param o.locale The locale to use on the OAuth2 authentication page. Optional.\n * @return `self`\n */\nexport function osmAuth(o) {\n var oauth = {};\n\n // Mock localStorage if needed.\n // Note that accessing localStorage may throw a `SecurityError`, so wrap in a try/catch.\n var _store = null;\n try {\n _store = window.localStorage;\n } catch (e) {\n var _mock = new Map();\n _store = {\n isMocked: true,\n hasItem: (k) => _mock.has(k),\n getItem: (k) => _mock.get(k),\n setItem: (k, v) => _mock.set(k, v),\n removeItem: (k) => _mock.delete(k),\n clear: () => _mock.clear()\n };\n }\n\n /**\n * token\n * Get/Set tokens. These are prefixed with the base URL so that `osm-auth`\n * can be used with multiple APIs and the keys in `localStorage` will not clash\n * @param {string} k key\n * @param {string?} v value\n * @return {string?} If getting, returns the stored value or `null`. If setting, returns `undefined`.\n */\n function token(k, v) {\n var key = o.url + k;\n if (arguments.length === 1) {\n var val = _store.getItem(key) || '';\n // Note: legacy tokens might be wrapped in double quotes - remove them, see #129\n return val.replace(/\"/g, '');\n\n } else if (arguments.length === 2) {\n if (v) {\n return _store.setItem(key, v);\n } else {\n return _store.removeItem(key);\n }\n }\n }\n\n\n /**\n * authenticated\n * Test whether the user is currently authenticated\n *\n * @return {boolean} `true` if authenticated, `false` if not\n */\n oauth.authenticated = function() {\n return !!token('oauth2_access_token');\n };\n\n\n /**\n * logout\n * Removes any stored authentication tokens (legacy OAuth1 tokens too)\n *\n * @return `self`\n */\n oauth.logout = function () {\n token('oauth2_access_token', ''); // OAuth2\n token('oauth_token', ''); // OAuth1\n token('oauth_token_secret', ''); // OAuth1\n token('oauth_request_token_secret', ''); // OAuth1\n return oauth;\n };\n\n\n /**\n * authenticate\n * First logs out, then runs the authentiation flow, finally calls the callback.\n * TODO: detect lack of click event (probably can settimeout it)\n *\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.authenticate = function(callback) {\n if (oauth.authenticated()) {\n callback(null, oauth);\n return;\n }\n\n oauth.logout();\n\n _preopenPopup(function(error, popup) {\n if (error) {\n callback(error);\n } else {\n _generatePkceChallenge(function(pkce) {\n _authenticate(pkce, popup, callback);\n });\n }\n });\n };\n\n\n /**\n * authenticateAsync\n * Promisified version of `authenticate`\n * @return {Promise} Promise settled with whatever `_authenticate` did\n */\n oauth.authenticateAsync = function() {\n if (oauth.authenticated()) {\n return Promise.resolve(oauth);\n }\n\n oauth.logout();\n\n return new Promise((resolve, reject) => {\n var errback = (err, result) => {\n if (err) {\n reject(err);\n } else {\n resolve(result);\n }\n };\n\n _preopenPopup((error, popup) => {\n if (error) {\n errback(error);\n } else {\n _generatePkceChallenge(pkce => _authenticate(pkce, popup, errback));\n }\n });\n });\n };\n\n\n /**\n * opens an empty popup to be later used for the authentication page\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n function _preopenPopup(callback) {\n if (o.singlepage) {\n callback(null, undefined);\n return;\n }\n\n // Create a 550x610 popup window in the center of the screen\n var w = 550;\n var h = 610;\n var settings = [\n ['width', w],\n ['height', h],\n ['left', window.screen.width / 2 - w / 2],\n ['top', window.screen.height / 2 - h / 2],\n ]\n .map(function (x) { return x.join('='); })\n .join(',');\n var popup = window.open('about:blank', 'oauth_window', settings);\n if (popup) {\n callback(null, popup);\n } else {\n var error = new Error('Popup was blocked');\n error.status = 'popup-blocked';\n callback(error);\n }\n }\n\n\n /**\n * _authenticate\n * internal authenticate\n *\n * @param {Object} pkce Object containing PKCE code challenge properties\n * @param {Window} popup Popup Window to use for the authentication page, should be undefined when using singlepage mode\n * @param {function} callback Errback-style callback that accepts `(err, result)`\n */\n function _authenticate(pkce, popup, callback) {\n var state = generateState();\n\n // ## Request authorization to access resources from the user\n // and receive authorization code\n var url =\n o.url +\n '/oauth2/authorize?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n response_type: 'code',\n scope: o.scope,\n state: state,\n code_challenge: pkce.code_challenge,\n code_challenge_method: pkce.code_challenge_method,\n locale: o.locale || '',\n });\n\n if (o.singlepage) {\n if (_store.isMocked) {\n // in singlepage mode, PKCE requires working non-volatile storage\n var error = new Error('localStorage unavailable, but required in singlepage mode');\n error.status = 'pkce-localstorage-unavailable';\n callback(error);\n return;\n }\n var params = utilStringQs(window.location.search.slice(1));\n if (params.code) {\n oauth.bootstrapToken(params.code, callback);\n } else {\n // save OAuth2 state and PKCE challenge in local storage, for later use\n // in the `/oauth/token` request\n token('oauth2_state', state);\n token('oauth2_pkce_code_verifier', pkce.code_verifier);\n window.location = url;\n }\n } else {\n oauth.popupWindow = popup;\n popup.location = url;\n }\n\n // Called by a function in the redirect URL page, in the popup window. The\n // window closes itself.\n window.authComplete = function (url) {\n var params = utilStringQs(url.split('?')[1]);\n if (params.state !== state) {\n error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n _getAccessToken(params.code, pkce.code_verifier, accessTokenDone);\n delete window.authComplete;\n };\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n }\n\n\n /**\n * _getAccessToken\n * The client requests an access token by authenticating with the\n * authorization server and presenting the `auth_code`, brought\n * in from a function call on a landing page popup.\n * @param {string} auth_code\n * @param {string} code_verifier\n * @param {function} accessTokenDone Errback-style callback `(err, result)`, called when complete\n */\n function _getAccessToken(auth_code, code_verifier, accessTokenDone) {\n var url =\n o.url +\n '/oauth2/token?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n grant_type: 'authorization_code',\n code: auth_code,\n code_verifier: code_verifier\n });\n\n // The authorization server authenticates the client and validates\n // the authorization grant, and if valid, issues an access token.\n oauth.rawxhr('POST', url, null, null, null, accessTokenDone);\n o.loading();\n }\n\n\n /**\n * bringPopupWindowToFront\n * Tries to bring an existing authentication popup to the front.\n *\n * @return {boolean} `true` if it succeeded, `false` if not\n */\n oauth.bringPopupWindowToFront = function() {\n var broughtPopupToFront = false;\n try {\n // This may cause a cross-origin error:\n // `DOMException: Blocked a frame with origin \"...\" from accessing a cross-origin frame.`\n if (oauth.popupWindow && !oauth.popupWindow.closed) {\n oauth.popupWindow.focus();\n broughtPopupToFront = true;\n }\n } catch (err) {\n // Bringing popup window to front failed (probably because of the cross-origin error mentioned above)\n }\n return broughtPopupToFront;\n };\n\n\n /**\n * bootstrapToken\n * The authorization code is a temporary code that a client can exchange for an access token.\n * If using this library in single-page mode, you'll need to call this once your application\n * has an `auth_code` and wants to get an access_token.\n *\n * @param {string} auth_code The OAuth2 `auth_code`\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.bootstrapToken = function(auth_code, callback) {\n var state = token('oauth2_state');\n token('oauth2_state', '');\n var params = utilStringQs(window.location.search.slice(1));\n if (params.state !== state) {\n var error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n var code_verifier = token('oauth2_pkce_code_verifier');\n token('oauth2_pkce_code_verifier', '');\n _getAccessToken(auth_code, code_verifier, accessTokenDone);\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n };\n\n\n /**\n * fetch\n * A `fetch` wrapper that includes the Authorization header if the user is authenticated.\n * https://developer.mozilla.org/en-US/docs/Web/API/fetch\n *\n * @param {string} resource Resource passed to `fetch`\n * @param {Object} options Options passed to `fetch`\n * @return {Promise} Promise that wraps `authenticateAsync` then `fetch`\n */\n oauth.fetch = function(resource, options) {\n if (oauth.authenticated()) {\n return _doFetch();\n } else {\n if (o.auto) {\n return oauth.authenticateAsync().then(_doFetch);\n } else {\n return Promise.reject(new Error('not authenticated'));\n }\n }\n\n function _doFetch() {\n options = options || {};\n if (!options.headers) {\n options.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n }\n options.headers.Authorization = 'Bearer ' + token('oauth2_access_token');\n return fetch(resource, options);\n }\n };\n\n\n /**\n * xhr\n * A `XMLHttpRequest` wrapper that does authenticated calls if the user has logged in.\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param {Object} options\n * @param options.method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param options.prefix If `true` path contains a path, if `false` path contains the full url\n * @param options.path The URL path (e.g. \"/api/0.6/user/details\") (or full url, if `prefix`=`false`)\n * @param options.content Passed to `xhr.send`\n * @param options.headers `Object` containing request headers\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return {XMLHttpRequest} `XMLHttpRequest` if authenticated, otherwise `null`\n */\n oauth.xhr = function (options, callback) {\n if (oauth.authenticated()) {\n return _doXHR();\n } else {\n if (o.auto) {\n oauth.authenticate(_doXHR);\n return;\n } else {\n callback('not authenticated', null);\n return;\n }\n }\n\n function _doXHR() {\n var url = options.prefix !== false ? (o.apiUrl + options.path) : options.path;\n return oauth.rawxhr(\n options.method,\n url,\n token('oauth2_access_token'),\n options.content,\n options.headers,\n done\n );\n }\n\n function done(err, xhr) {\n if (err) {\n callback(err);\n } else if (xhr.responseXML) {\n callback(err, xhr.responseXML);\n } else {\n callback(err, xhr.response);\n }\n }\n };\n\n\n /**\n * rawxhr\n * Creates the XMLHttpRequest set up with a header and response handling\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param url Passed to `xhr.open`\n * @param access_token OAuth2 bearer token\n * @param data Passed to `xhr.send`\n * @param headers `Object` containing request headers\n * @param callback An \"errback\"-style callback (`err`, `result`), called when complete\n * @return `XMLHttpRequest`\n */\n oauth.rawxhr = function(method, url, access_token, data, headers, callback) {\n headers = headers || { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (access_token) {\n headers.Authorization = 'Bearer ' + access_token;\n }\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (4 === xhr.readyState && 0 !== xhr.status) {\n if (/^20\\d$/.test(xhr.status)) { // a 20x status code - OK\n callback(null, xhr);\n } else {\n callback(xhr, null);\n }\n }\n };\n xhr.onerror = function (e) {\n callback(e, null);\n };\n\n xhr.open(method, url, true);\n for (var h in headers) xhr.setRequestHeader(h, headers[h]);\n\n xhr.send(data);\n return xhr;\n };\n\n\n /**\n * preauth\n * Pre-authorize this object, if we already have access token from the start\n *\n * @param {Object} val Object containing `access_token` property\n * @return `self`\n */\n oauth.preauth = function(val) {\n if (val && val.access_token) {\n token('oauth2_access_token', val.access_token);\n }\n return oauth;\n };\n\n\n /**\n * options (getter / setter)\n * If passed with no arguments, just return the options\n * If passed an Object, set the options then attempt to pre-authorize\n *\n * @param val? Object containing options\n * @return current `options` (if getting), or `self` (if setting)\n */\n oauth.options = function(val) {\n if (!arguments.length) return o;\n\n o = val;\n o.apiUrl = o.apiUrl || 'https://api.openstreetmap.org';\n o.url = o.url || 'https://www.openstreetmap.org';\n o.auto = o.auto || false;\n o.singlepage = o.singlepage || false;\n\n // Optional loading and loading-done functions for nice UI feedback.\n // by default, no-ops\n o.loading = o.loading || function () {};\n o.done = o.done || function () {};\n return oauth.preauth(o);\n };\n\n\n // Everything below here is initialization/setup code\n // Handle options and attempt to pre-authorize\n oauth.options(o);\n\n return oauth;\n}\n\n\n/**\n * utilQsString\n * Transforms object of `key=value` pairs into query string\n * @param {Object} Object of `key=value` pairs\n * @returns {string} query string\n */\nfunction utilQsString(obj) {\n return Object.keys(obj)\n .filter(function(key) {\n return obj[key] !== undefined;\n })\n .sort()\n .map(function(key) {\n return (encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));\n })\n .join('&');\n}\n\n/**\n * utilStringQs\n * Transforms query string into object of `key=value` pairs\n * @param {string} query string\n * @returns {Object} Object of `key=value` pairs\n */\nfunction utilStringQs(str) {\n var i = 0; // advance past any leading '?' or '#' characters\n while (i < str.length && (str[i] === '?' || str[i] === '#')) i++;\n str = str.slice(i);\n\n return str.split('&').reduce(function(obj, pair) {\n var parts = pair.split('=');\n if (parts.length === 2) {\n obj[parts[0]] = decodeURIComponent(parts[1]);\n }\n return obj;\n }, {});\n}\n\n\n/**\n * supportsWebCryptoAPI\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n * @returns {boolean} `true` if WebCryptoAPI is available\n */\nfunction supportsWebCryptoAPI() {\n return window && window.crypto\n && window.crypto.getRandomValues\n && window.crypto.subtle\n && window.crypto.subtle.digest;\n}\n\n\n/**\n * Generates a challenge/verifier pair for PKCE.\n * If the browser does not support the WebCryptoAPI, the \"plain\" method is\n * used as a fallback instead of a SHA-256 hash.\n * @param {callback} callback called with the result of the generated PKCE challenge\n */\nfunction _generatePkceChallenge(callback) {\n var code_verifier;\n if (supportsWebCryptoAPI()) {\n // generate a random code_verifier\n // https://datatracker.ietf.org/doc/html/rfc7636#section-7.1\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n code_verifier = base64(random.buffer);\n var verifier = Uint8Array.from(Array.from(code_verifier).map(function(char) {\n return char.charCodeAt(0);\n }));\n\n // generate challenge for code verifier\n window.crypto.subtle.digest('SHA-256', verifier).then(function(hash) {\n var code_challenge = base64(hash);\n\n callback({\n code_challenge: code_challenge,\n code_verifier: code_verifier,\n code_challenge_method: 'S256'\n });\n });\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n code_verifier = '';\n for (var i=0; i<64; i++) {\n code_verifier += chars[Math.floor(Math.random() * chars.length)];\n }\n callback({\n code_verifier: code_verifier,\n code_challenge: code_verifier,\n code_challenge_method: 'plain',\n });\n }\n}\n\n\n/**\n * Returns a random state to be used as the \"state\" of the OAuth2 authentication\n * See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12\n */\nfunction generateState() {\n var state;\n if (supportsWebCryptoAPI()) {\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n state = base64(random.buffer);\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n state = '';\n for (var i=0; i<64; i++) {\n state += chars[Math.floor(Math.random() * chars.length)];\n }\n }\n return state;\n}\n\n\n/**\n * base64\n * Converts binary buffer to base64 encoded string, as used in rfc7636\n * @param {ArrayBuffer} buffer\n * @returns {string} base64 encoded\n */\nfunction base64(buffer) {\n return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))\n .replace(/\\//g, '_')\n .replace(/\\+/g, '-')\n .replace(/[=]/g, '');\n}\n"], + "mappings": "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", "names": ["url", "params"] } diff --git a/dist/osm-auth.iife.js b/dist/osm-auth.iife.js index 06e2e0f..23b75ce 100644 --- a/dist/osm-auth.iife.js +++ b/dist/osm-auth.iife.js @@ -1,2 +1,2 @@ -var osmAuth=(function(){var v=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var U=function(t,e){for(var s in e)v(t,s,{get:e[s],enumerable:!0})},k=function(t,e,s,d){if(e&&typeof e=="object"||typeof e=="function")for(var a=P(e),h=0,p=a.length,f;h _mock.has(k),\n getItem: (k) => _mock.get(k),\n setItem: (k, v) => _mock.set(k, v),\n removeItem: (k) => _mock.delete(k),\n clear: () => _mock.clear()\n };\n }\n\n /**\n * token\n * Get/Set tokens. These are prefixed with the base URL so that `osm-auth`\n * can be used with multiple APIs and the keys in `localStorage` will not clash\n * @param {string} k key\n * @param {string?} v value\n * @return {string?} If getting, returns the stored value or `null`. If setting, returns `undefined`.\n */\n function token(k, v) {\n if (arguments.length === 1) return _store.getItem(o.url + k);\n else if (arguments.length === 2) return _store.setItem(o.url + k, v);\n }\n\n\n /**\n * authenticated\n * Test whether the user is currently authenticated\n *\n * @return {boolean} `true` if authenticated, `false` if not\n */\n oauth.authenticated = function() {\n return !!token('oauth2_access_token');\n };\n\n\n /**\n * logout\n * Removes any stored authentication tokens (legacy OAuth1 tokens too)\n *\n * @return `self`\n */\n oauth.logout = function () {\n token('oauth2_access_token', ''); // OAuth2\n token('oauth_token', ''); // OAuth1\n token('oauth_token_secret', ''); // OAuth1\n token('oauth_request_token_secret', ''); // OAuth1\n return oauth;\n };\n\n\n /**\n * authenticate\n * First logs out, then runs the authentiation flow, finally calls the callback.\n * TODO: detect lack of click event (probably can settimeout it)\n *\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.authenticate = function(callback) {\n if (oauth.authenticated()) {\n callback(null, oauth);\n return;\n }\n\n oauth.logout();\n\n _preopenPopup(function(error, popup) {\n if (error) {\n callback(error);\n } else {\n _generatePkceChallenge(function(pkce) {\n _authenticate(pkce, popup, callback);\n });\n }\n });\n };\n\n\n /**\n * authenticateAsync\n * Promisified version of `authenticate`\n * @return {Promise} Promise settled with whatever `_authenticate` did\n */\n oauth.authenticateAsync = function() {\n if (oauth.authenticated()) {\n return Promise.resolve(oauth);\n }\n\n oauth.logout();\n\n return new Promise((resolve, reject) => {\n var errback = (err, result) => {\n if (err) {\n reject(err);\n } else {\n resolve(result);\n }\n };\n\n _preopenPopup((error, popup) => {\n if (error) {\n errback(error);\n } else {\n _generatePkceChallenge(pkce => _authenticate(pkce, popup, errback));\n }\n });\n });\n };\n\n\n /**\n * opens an empty popup to be later used for the authentication page\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n function _preopenPopup(callback) {\n if (o.singlepage) {\n callback(null, undefined);\n return;\n }\n\n // Create a 550x610 popup window in the center of the screen\n var w = 550;\n var h = 610;\n var settings = [\n ['width', w],\n ['height', h],\n ['left', window.screen.width / 2 - w / 2],\n ['top', window.screen.height / 2 - h / 2],\n ]\n .map(function (x) { return x.join('='); })\n .join(',');\n var popup = window.open('about:blank', 'oauth_window', settings);\n if (popup) {\n callback(null, popup);\n } else {\n var error = new Error('Popup was blocked');\n error.status = 'popup-blocked';\n callback(error);\n }\n }\n\n\n /**\n * _authenticate\n * internal authenticate\n *\n * @param {Object} pkce Object containing PKCE code challenge properties\n * @param {Window} popup Popup Window to use for the authentication page, should be undefined when using singlepage mode\n * @param {function} callback Errback-style callback that accepts `(err, result)`\n */\n function _authenticate(pkce, popup, callback) {\n var state = generateState();\n\n // ## Request authorization to access resources from the user\n // and receive authorization code\n var url =\n o.url +\n '/oauth2/authorize?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n response_type: 'code',\n scope: o.scope,\n state: state,\n code_challenge: pkce.code_challenge,\n code_challenge_method: pkce.code_challenge_method,\n });\n\n if (o.singlepage) {\n if (_store.isMocked) {\n // in singlepage mode, PKCE requires working non-volatile storage\n var error = new Error('localStorage unavailable, but required in singlepage mode');\n error.status = 'pkce-localstorage-unavailable';\n callback(error);\n return;\n }\n var params = utilStringQs(window.location.search.slice(1));\n if (params.code) {\n oauth.bootstrapToken(params.code, callback);\n } else {\n // save OAuth2 state and PKCE challenge in local storage, for later use\n // in the `/oauth/token` request\n token('oauth2_state', state);\n token('oauth2_pkce_code_verifier', pkce.code_verifier);\n window.location = url;\n }\n } else {\n oauth.popupWindow = popup;\n popup.location = url;\n }\n\n // Called by a function in the redirect URL page, in the popup window. The\n // window closes itself.\n window.authComplete = function (url) {\n var params = utilStringQs(url.split('?')[1]);\n if (params.state !== state) {\n error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n _getAccessToken(params.code, pkce.code_verifier, accessTokenDone);\n delete window.authComplete;\n };\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n }\n\n\n /**\n * _getAccessToken\n * The client requests an access token by authenticating with the\n * authorization server and presenting the `auth_code`, brought\n * in from a function call on a landing page popup.\n * @param {string} auth_code\n * @param {string} code_verifier\n * @param {function} accessTokenDone Errback-style callback `(err, result)`, called when complete\n */\n function _getAccessToken(auth_code, code_verifier, accessTokenDone) {\n var url =\n o.url +\n '/oauth2/token?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n grant_type: 'authorization_code',\n code: auth_code,\n code_verifier: code_verifier\n });\n\n // The authorization server authenticates the client and validates\n // the authorization grant, and if valid, issues an access token.\n oauth.rawxhr('POST', url, null, null, null, accessTokenDone);\n o.loading();\n }\n\n\n /**\n * bringPopupWindowToFront\n * Tries to bring an existing authentication popup to the front.\n *\n * @return {boolean} `true` if it succeeded, `false` if not\n */\n oauth.bringPopupWindowToFront = function() {\n var broughtPopupToFront = false;\n try {\n // This may cause a cross-origin error:\n // `DOMException: Blocked a frame with origin \"...\" from accessing a cross-origin frame.`\n if (oauth.popupWindow && !oauth.popupWindow.closed) {\n oauth.popupWindow.focus();\n broughtPopupToFront = true;\n }\n } catch (err) {\n // Bringing popup window to front failed (probably because of the cross-origin error mentioned above)\n }\n return broughtPopupToFront;\n };\n\n\n /**\n * bootstrapToken\n * The authorization code is a temporary code that a client can exchange for an access token.\n * If using this library in single-page mode, you'll need to call this once your application\n * has an `auth_code` and wants to get an access_token.\n *\n * @param {string} auth_code The OAuth2 `auth_code`\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.bootstrapToken = function(auth_code, callback) {\n var state = token('oauth2_state');\n token('oauth2_state', '');\n var params = utilStringQs(window.location.search.slice(1));\n if (params.state !== state) {\n var error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n var code_verifier = token('oauth2_pkce_code_verifier');\n token('oauth2_pkce_code_verifier', '');\n _getAccessToken(auth_code, code_verifier, accessTokenDone);\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n };\n\n\n /**\n * fetch\n * A `fetch` wrapper that includes the Authorization header if the user is authenticated.\n * https://developer.mozilla.org/en-US/docs/Web/API/fetch\n *\n * @param {string} resource Resource passed to `fetch`\n * @param {Object} options Options passed to `fetch`\n * @return {Promise} Promise that wraps `authenticateAsync` then `fetch`\n */\n oauth.fetch = function(resource, options) {\n if (oauth.authenticated()) {\n return _doFetch();\n } else {\n if (o.auto) {\n return oauth.authenticateAsync().then(_doFetch);\n } else {\n return Promise.reject(new Error('not authenticated'));\n }\n }\n\n function _doFetch() {\n options = options || {};\n if (!options.headers) {\n options.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n }\n options.headers.Authorization = 'Bearer ' + token('oauth2_access_token');\n return fetch(resource, options);\n }\n };\n\n\n /**\n * xhr\n * A `XMLHttpRequest` wrapper that does authenticated calls if the user has logged in.\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param {Object} options\n * @param options.method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param options.prefix If `true` path contains a path, if `false` path contains the full url\n * @param options.path The URL path (e.g. \"/api/0.6/user/details\") (or full url, if `prefix`=`false`)\n * @param options.content Passed to `xhr.send`\n * @param options.headers `Object` containing request headers\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return {XMLHttpRequest} `XMLHttpRequest` if authenticated, otherwise `null`\n */\n oauth.xhr = function (options, callback) {\n if (oauth.authenticated()) {\n return _doXHR();\n } else {\n if (o.auto) {\n oauth.authenticate(_doXHR);\n return;\n } else {\n callback('not authenticated', null);\n return;\n }\n }\n\n function _doXHR() {\n var url = options.prefix !== false ? (o.apiUrl + options.path) : options.path;\n return oauth.rawxhr(\n options.method,\n url,\n token('oauth2_access_token'),\n options.content,\n options.headers,\n done\n );\n }\n\n function done(err, xhr) {\n if (err) {\n callback(err);\n } else if (xhr.responseXML) {\n callback(err, xhr.responseXML);\n } else {\n callback(err, xhr.response);\n }\n }\n };\n\n\n /**\n * rawxhr\n * Creates the XMLHttpRequest set up with a header and response handling\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param url Passed to `xhr.open`\n * @param access_token OAuth2 bearer token\n * @param data Passed to `xhr.send`\n * @param headers `Object` containing request headers\n * @param callback An \"errback\"-style callback (`err`, `result`), called when complete\n * @return `XMLHttpRequest`\n */\n oauth.rawxhr = function(method, url, access_token, data, headers, callback) {\n headers = headers || { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (access_token) {\n headers.Authorization = 'Bearer ' + access_token;\n }\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (4 === xhr.readyState && 0 !== xhr.status) {\n if (/^20\\d$/.test(xhr.status)) { // a 20x status code - OK\n callback(null, xhr);\n } else {\n callback(xhr, null);\n }\n }\n };\n xhr.onerror = function (e) {\n callback(e, null);\n };\n\n xhr.open(method, url, true);\n for (var h in headers) xhr.setRequestHeader(h, headers[h]);\n\n xhr.send(data);\n return xhr;\n };\n\n\n /**\n * preauth\n * Pre-authorize this object, if we already have access token from the start\n *\n * @param {Object} val Object containing `access_token` property\n * @return `self`\n */\n oauth.preauth = function(val) {\n if (val && val.access_token) {\n token('oauth2_access_token', val.access_token);\n }\n return oauth;\n };\n\n\n /**\n * options (getter / setter)\n * If passed with no arguments, just return the options\n * If passed an Object, set the options then attempt to pre-authorize\n *\n * @param val? Object containing options\n * @return current `options` (if getting), or `self` (if setting)\n */\n oauth.options = function(val) {\n if (!arguments.length) return o;\n\n o = val;\n o.apiUrl = o.apiUrl || 'https://api.openstreetmap.org';\n o.url = o.url || 'https://www.openstreetmap.org';\n o.auto = o.auto || false;\n o.singlepage = o.singlepage || false;\n\n // Optional loading and loading-done functions for nice UI feedback.\n // by default, no-ops\n o.loading = o.loading || function () {};\n o.done = o.done || function () {};\n return oauth.preauth(o);\n };\n\n\n // Everything below here is initialization/setup code\n // Handle options and attempt to pre-authorize\n oauth.options(o);\n\n return oauth;\n}\n\n\n/**\n * utilQsString\n * Transforms object of `key=value` pairs into query string\n * @param {Object} Object of `key=value` pairs\n * @returns {string} query string\n */\nfunction utilQsString(obj) {\n return Object.keys(obj)\n .filter(function(key) {\n return obj[key] !== undefined;\n })\n .sort()\n .map(function(key) {\n return (encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));\n })\n .join('&');\n}\n\n/**\n * utilStringQs\n * Transforms query string into object of `key=value` pairs\n * @param {string} query string\n * @returns {Object} Object of `key=value` pairs\n */\nfunction utilStringQs(str) {\n var i = 0; // advance past any leading '?' or '#' characters\n while (i < str.length && (str[i] === '?' || str[i] === '#')) i++;\n str = str.slice(i);\n\n return str.split('&').reduce(function(obj, pair) {\n var parts = pair.split('=');\n if (parts.length === 2) {\n obj[parts[0]] = decodeURIComponent(parts[1]);\n }\n return obj;\n }, {});\n}\n\n\n/**\n * supportsWebCryptoAPI\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n * @returns {boolean} `true` if WebCryptoAPI is available\n */\nfunction supportsWebCryptoAPI() {\n return window && window.crypto\n && window.crypto.getRandomValues\n && window.crypto.subtle\n && window.crypto.subtle.digest;\n}\n\n\n/**\n * Generates a challenge/verifier pair for PKCE.\n * If the browser does not support the WebCryptoAPI, the \"plain\" method is\n * used as a fallback instead of a SHA-256 hash.\n * @param {callback} callback called with the result of the generated PKCE challenge\n */\nfunction _generatePkceChallenge(callback) {\n var code_verifier;\n if (supportsWebCryptoAPI()) {\n // generate a random code_verifier\n // https://datatracker.ietf.org/doc/html/rfc7636#section-7.1\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n code_verifier = base64(random.buffer);\n var verifier = Uint8Array.from(Array.from(code_verifier).map(function(char) {\n return char.charCodeAt(0);\n }));\n\n // generate challenge for code verifier\n window.crypto.subtle.digest('SHA-256', verifier).then(function(hash) {\n var code_challenge = base64(hash);\n\n callback({\n code_challenge: code_challenge,\n code_verifier: code_verifier,\n code_challenge_method: 'S256'\n });\n });\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n code_verifier = '';\n for (var i=0; i<64; i++) {\n code_verifier += chars[Math.floor(Math.random() * chars.length)];\n }\n callback({\n code_verifier: code_verifier,\n code_challenge: code_verifier,\n code_challenge_method: 'plain',\n });\n }\n}\n\n\n/**\n * Returns a random state to be used as the \"state\" of the OAuth2 authentication\n * See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12\n */\nfunction generateState() {\n var state;\n if (supportsWebCryptoAPI()) {\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n state = base64(random.buffer);\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n state = '';\n for (var i=0; i<64; i++) {\n state += chars[Math.floor(Math.random() * chars.length)];\n }\n }\n return state;\n}\n\n\n/**\n * base64\n * Converts binary buffer to base64 encoded string, as used in rfc7636\n * @param {ArrayBuffer} buffer\n * @returns {string} base64 encoded\n */\nfunction base64(buffer) {\n return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))\n .replace(/\\//g, '_')\n .replace(/\\+/g, '-')\n .replace(/[=]/g, '');\n}\n"], - "mappings": "2gBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,KAmBO,SAASA,EAAQC,EAAG,CACzB,IAAIC,EAAQ,CAAC,EAITC,EAAS,KACb,GAAI,CACFA,EAAS,OAAO,YAClB,OAASC,EAAG,CACV,IAAIC,EAAQ,IAAI,IAChBF,EAAS,CACP,SAAU,GACV,QAAS,SAACG,EAAG,CAAG,OAAAD,EAAM,IAAIC,CAAC,GAC3B,QAAS,SAACA,EAAG,CAAG,OAAAD,EAAM,IAAIC,CAAC,GAC3B,QAAS,SAACA,EAAGC,EAAG,CAAG,OAAAF,EAAM,IAAIC,EAAGC,CAAC,GACjC,WAAY,SAACD,EAAG,CAAG,OAAAD,EAAM,OAAOC,CAAC,GACjC,MAAO,UAAG,CAAG,OAAAD,EAAM,MAAM,EAC3B,CACF,CAUA,SAASG,EAAMF,EAAGC,EAAG,CACnB,GAAI,UAAU,SAAW,EAAG,OAAOJ,EAAO,QAAQF,EAAE,IAAMK,CAAC,EACtD,GAAI,UAAU,SAAW,EAAG,OAAOH,EAAO,QAAQF,EAAE,IAAMK,EAAGC,CAAC,CACrE,CASAL,EAAM,cAAgB,UAAW,CAC/B,MAAO,CAAC,CAACM,EAAM,qBAAqB,CACtC,EASAN,EAAM,OAAS,UAAY,CACzB,OAAAM,EAAM,sBAAuB,EAAE,EAC/BA,EAAM,cAAe,EAAE,EACvBA,EAAM,qBAAsB,EAAE,EAC9BA,EAAM,6BAA8B,EAAE,EAC/BN,CACT,EAWAA,EAAM,aAAe,SAASO,EAAU,CACtC,GAAIP,EAAM,cAAc,EAAG,CACzBO,EAAS,KAAMP,CAAK,EACpB,MACF,CAEAA,EAAM,OAAO,EAEbQ,EAAc,SAASC,EAAOC,EAAO,CAC/BD,EACFF,EAASE,CAAK,EAEdE,EAAuB,SAASC,EAAM,CACpCC,EAAcD,EAAMF,EAAOH,CAAQ,CACrC,CAAC,CAEL,CAAC,CACH,EAQAP,EAAM,kBAAoB,UAAW,CACnC,OAAIA,EAAM,cAAc,EACf,QAAQ,QAAQA,CAAK,GAG9BA,EAAM,OAAO,EAEN,IAAI,QAAQ,SAACc,EAASC,EAAW,CACtC,IAAIC,EAAU,SAACC,EAAKC,EAAW,CACzBD,EACFF,EAAOE,CAAG,EAEVH,EAAQI,CAAM,CAElB,EAEAV,EAAc,SAACC,EAAOC,EAAU,CAC1BD,EACFO,EAAQP,CAAK,EAEbE,EAAuB,SAAAC,EAAK,CAAG,OAAAC,EAAcD,EAAMF,EAAOM,CAAO,EAAC,CAEtE,CAAC,CACH,CAAC,EACH,EAQA,SAASR,EAAcD,EAAU,CAC/B,GAAIR,EAAE,WAAY,CAChBQ,EAAS,KAAM,MAAS,EACxB,MACF,CAGA,IAAIY,EAAI,IACJC,EAAI,IACJC,EAAW,CACX,CAAC,QAASF,CAAC,EACX,CAAC,SAAUC,CAAC,EACZ,CAAC,OAAQ,OAAO,OAAO,MAAQ,EAAID,EAAI,CAAC,EACxC,CAAC,MAAO,OAAO,OAAO,OAAS,EAAIC,EAAI,CAAC,CAC1C,EACC,IAAI,SAAUE,EAAG,CAAE,OAAOA,EAAE,KAAK,GAAG,CAAG,CAAC,EACxC,KAAK,GAAG,EACPZ,EAAQ,OAAO,KAAK,cAAe,eAAgBW,CAAQ,EAC/D,GAAIX,EACFH,EAAS,KAAMG,CAAK,MACf,CACL,IAAID,EAAQ,IAAI,MAAM,mBAAmB,EACzCA,EAAM,OAAS,gBACfF,EAASE,CAAK,CAChB,CACF,CAWA,SAASI,EAAcD,EAAMF,EAAOH,EAAU,CAC5C,IAAIgB,EAAQC,EAAc,EAItBC,EACF1B,EAAE,IACF,qBACA2B,EAAa,CACX,UAAW3B,EAAE,UACb,aAAcA,EAAE,aAChB,cAAe,OACf,MAAOA,EAAE,MACT,MAAOwB,EACP,eAAgBX,EAAK,eACrB,sBAAuBA,EAAK,qBAC9B,CAAC,EAEH,GAAIb,EAAE,WAAY,CAChB,GAAIE,EAAO,SAAU,CAEnB,IAAIQ,EAAQ,IAAI,MAAM,2DAA2D,EACjFA,EAAM,OAAS,gCACfF,EAASE,CAAK,EACd,MACF,CACA,IAAIkB,EAASC,EAAa,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,EACrDD,EAAO,KACT3B,EAAM,eAAe2B,EAAO,KAAMpB,CAAQ,GAI1CD,EAAM,eAAgBiB,CAAK,EAC3BjB,EAAM,4BAA6BM,EAAK,aAAa,EACrD,OAAO,SAAWa,EAEtB,MACEzB,EAAM,YAAcU,EACpBA,EAAM,SAAWe,EAKnB,OAAO,aAAe,SAAUA,EAAK,CACnC,IAAIE,EAASC,EAAaH,EAAI,MAAM,GAAG,EAAE,CAAC,CAAC,EAC3C,GAAIE,EAAO,QAAUJ,EAAO,CAC1Bd,EAAQ,IAAI,MAAM,eAAe,EACjCA,EAAM,OAAS,gBACfF,EAASE,CAAK,EACd,MACF,CACAoB,EAAgBF,EAAO,KAAMf,EAAK,cAAekB,CAAe,EAChE,OAAO,OAAO,YAChB,EAEA,SAASA,EAAgBb,EAAKc,EAAK,CAEjC,GADAhC,EAAE,KAAK,EACHkB,EAAK,CACPV,EAASU,CAAG,EACZ,MACF,CACA,IAAIe,EAAe,KAAK,MAAMD,EAAI,QAAQ,EAC1CzB,EAAM,sBAAuB0B,EAAa,YAAY,EACtDzB,EAAS,KAAMP,CAAK,CACtB,CACF,CAYA,SAAS6B,EAAgBI,EAAWC,EAAeJ,EAAiB,CAClE,IAAIL,EACF1B,EAAE,IACF,iBACA2B,EAAa,CACX,UAAW3B,EAAE,UACb,aAAcA,EAAE,aAChB,WAAY,qBACZ,KAAMkC,EACN,cAAeC,CACjB,CAAC,EAIHlC,EAAM,OAAO,OAAQyB,EAAK,KAAM,KAAM,KAAMK,CAAe,EAC3D/B,EAAE,QAAQ,CACZ,CASA,OAAAC,EAAM,wBAA0B,UAAW,CACzC,IAAImC,EAAsB,GAC1B,GAAI,CAGEnC,EAAM,aAAe,CAACA,EAAM,YAAY,SAC1CA,EAAM,YAAY,MAAM,EACxBmC,EAAsB,GAE1B,OAASlB,EAAK,CAEd,CACA,OAAOkB,CACT,EAaAnC,EAAM,eAAiB,SAASiC,EAAW1B,EAAU,CACnD,IAAIgB,EAAQjB,EAAM,cAAc,EAChCA,EAAM,eAAgB,EAAE,EACxB,IAAIqB,EAASC,EAAa,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,EACzD,GAAID,EAAO,QAAUJ,EAAO,CAC1B,IAAId,EAAQ,IAAI,MAAM,eAAe,EACrCA,EAAM,OAAS,gBACfF,EAASE,CAAK,EACd,MACF,CACA,IAAIyB,EAAgB5B,EAAM,2BAA2B,EACrDA,EAAM,4BAA6B,EAAE,EACrCuB,EAAgBI,EAAWC,EAAeJ,CAAe,EAEzD,SAASA,EAAgBb,EAAKc,EAAK,CAEjC,GADAhC,EAAE,KAAK,EACHkB,EAAK,CACPV,EAASU,CAAG,EACZ,MACF,CACA,IAAIe,EAAe,KAAK,MAAMD,EAAI,QAAQ,EAC1CzB,EAAM,sBAAuB0B,EAAa,YAAY,EACtDzB,EAAS,KAAMP,CAAK,CACtB,CACF,EAYAA,EAAM,MAAQ,SAASoC,EAAUC,EAAS,CACxC,GAAIrC,EAAM,cAAc,EACtB,OAAOsC,EAAS,EAEhB,OAAIvC,EAAE,KACGC,EAAM,kBAAkB,EAAE,KAAKsC,CAAQ,EAEvC,QAAQ,OAAO,IAAI,MAAM,mBAAmB,CAAC,EAIxD,SAASA,GAAW,CAClB,OAAAD,EAAUA,GAAW,CAAC,EACjBA,EAAQ,UACXA,EAAQ,QAAU,CAAE,eAAgB,mCAAoC,GAE1EA,EAAQ,QAAQ,cAAgB,UAAY/B,EAAM,qBAAqB,EAChE,MAAM8B,EAAUC,CAAO,CAChC,CACF,EAiBArC,EAAM,IAAM,SAAUqC,EAAS9B,EAAU,CACvC,GAAIP,EAAM,cAAc,EACtB,OAAOuC,EAAO,EAEd,GAAIxC,EAAE,KAAM,CACVC,EAAM,aAAauC,CAAM,EACzB,MACF,KAAO,CACLhC,EAAS,oBAAqB,IAAI,EAClC,MACF,CAGF,SAASgC,GAAS,CAChB,IAAId,EAAMY,EAAQ,SAAW,GAAStC,EAAE,OAASsC,EAAQ,KAAQA,EAAQ,KACzE,OAAOrC,EAAM,OACXqC,EAAQ,OACRZ,EACAnB,EAAM,qBAAqB,EAC3B+B,EAAQ,QACRA,EAAQ,QACRG,CACF,CACF,CAEA,SAASA,EAAKvB,EAAKc,EAAK,CAClBd,EACFV,EAASU,CAAG,EACHc,EAAI,YACbxB,EAASU,EAAKc,EAAI,WAAW,EAE7BxB,EAASU,EAAKc,EAAI,QAAQ,CAE9B,CACF,EAgBA/B,EAAM,OAAS,SAASyC,EAAQhB,EAAKO,EAAcU,EAAMC,EAASpC,EAAU,CAC1EoC,EAAUA,GAAW,CAAE,eAAgB,mCAAoC,EAEvEX,IACFW,EAAQ,cAAgB,UAAYX,GAGtC,IAAID,EAAM,IAAI,eAEdA,EAAI,mBAAqB,UAAY,CACzBA,EAAI,aAAV,GAA8BA,EAAI,SAAV,IACtB,SAAS,KAAKA,EAAI,MAAM,EAC1BxB,EAAS,KAAMwB,CAAG,EAElBxB,EAASwB,EAAK,IAAI,EAGxB,EACAA,EAAI,QAAU,SAAU7B,EAAG,CACzBK,EAASL,EAAG,IAAI,CAClB,EAEA6B,EAAI,KAAKU,EAAQhB,EAAK,EAAI,EAC1B,QAASL,KAAKuB,EAASZ,EAAI,iBAAiBX,EAAGuB,EAAQvB,CAAC,CAAC,EAEzD,OAAAW,EAAI,KAAKW,CAAI,EACNX,CACT,EAUA/B,EAAM,QAAU,SAAS4C,EAAK,CAC5B,OAAIA,GAAOA,EAAI,cACbtC,EAAM,sBAAuBsC,EAAI,YAAY,EAExC5C,CACT,EAWAA,EAAM,QAAU,SAAS4C,EAAK,CAC5B,OAAK,UAAU,QAEf7C,EAAI6C,EACJ7C,EAAE,OAASA,EAAE,QAAU,gCACvBA,EAAE,IAAMA,EAAE,KAAO,gCACjBA,EAAE,KAAOA,EAAE,MAAQ,GACnBA,EAAE,WAAaA,EAAE,YAAc,GAI/BA,EAAE,QAAUA,EAAE,SAAW,UAAY,CAAC,EACtCA,EAAE,KAAOA,EAAE,MAAQ,UAAY,CAAC,EACzBC,EAAM,QAAQD,CAAC,GAZQA,CAahC,EAKAC,EAAM,QAAQD,CAAC,EAERC,CACT,CASA,SAAS0B,EAAamB,EAAK,CACzB,OAAO,OAAO,KAAKA,CAAG,EACnB,OAAO,SAASC,EAAK,CACpB,OAAOD,EAAIC,CAAG,IAAM,MACtB,CAAC,EACA,KAAK,EACL,IAAI,SAASA,EAAK,CACjB,OAAQ,mBAAmBA,CAAG,EAAI,IAAM,mBAAmBD,EAAIC,CAAG,CAAC,CACrE,CAAC,EACA,KAAK,GAAG,CACb,CAQA,SAASlB,EAAamB,EAAK,CAEzB,QADIC,EAAI,EACDA,EAAID,EAAI,SAAWA,EAAIC,CAAC,IAAM,KAAOD,EAAIC,CAAC,IAAM,MAAMA,IAC7D,OAAAD,EAAMA,EAAI,MAAMC,CAAC,EAEVD,EAAI,MAAM,GAAG,EAAE,OAAO,SAASF,EAAKI,EAAM,CAC/C,IAAIC,EAAQD,EAAK,MAAM,GAAG,EAC1B,OAAIC,EAAM,SAAW,IACnBL,EAAIK,EAAM,CAAC,CAAC,EAAI,mBAAmBA,EAAM,CAAC,CAAC,GAEtCL,CACT,EAAG,CAAC,CAAC,CACP,CAQA,SAASM,GAAuB,CAC9B,OAAO,QAAU,OAAO,QACnB,OAAO,OAAO,iBACd,OAAO,OAAO,QACd,OAAO,OAAO,OAAO,MAC5B,CASA,SAASxC,EAAuBJ,EAAU,CACxC,IAAI2B,EACJ,GAAIiB,EAAqB,EAAG,CAG1B,IAAIC,EAAS,OAAO,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,EAC7DlB,EAAgBmB,EAAOD,EAAO,MAAM,EACpC,IAAIE,EAAW,WAAW,KAAK,MAAM,KAAKpB,CAAa,EAAE,IAAI,SAASqB,EAAM,CAC1E,OAAOA,EAAK,WAAW,CAAC,CAC1B,CAAC,CAAC,EAGF,OAAO,OAAO,OAAO,OAAO,UAAWD,CAAQ,EAAE,KAAK,SAASE,EAAM,CACnE,IAAIC,EAAiBJ,EAAOG,CAAI,EAEhCjD,EAAS,CACP,eAAgBkD,EAChB,cAAevB,EACf,sBAAuB,MACzB,CAAC,CACH,CAAC,CACH,KAAO,CAEL,IAAIwB,EAAQ,mEACZxB,EAAgB,GAChB,QAASc,EAAE,EAAGA,EAAE,GAAIA,IAClBd,GAAiBwB,EAAM,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAM,MAAM,CAAC,EAEjEnD,EAAS,CACP,cAAe2B,EACf,eAAgBA,EAChB,sBAAuB,OACzB,CAAC,CACH,CACF,CAOA,SAASV,GAAgB,CACvB,IAAID,EACJ,GAAI4B,EAAqB,EAAG,CAC1B,IAAIC,EAAS,OAAO,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,EAC7D7B,EAAQ8B,EAAOD,EAAO,MAAM,CAC9B,KAAO,CAEL,IAAIM,EAAQ,mEACZnC,EAAQ,GACR,QAASyB,EAAE,EAAGA,EAAE,GAAIA,IAClBzB,GAASmC,EAAM,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAM,MAAM,CAAC,CAE3D,CACA,OAAOnC,CACT,CASA,SAAS8B,EAAOM,EAAQ,CACtB,OAAO,KAAK,OAAO,aAAa,MAAM,KAAM,IAAI,WAAWA,CAAM,CAAC,CAAC,EAChE,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,GAAG,EAClB,QAAQ,OAAQ,EAAE,CACvB", - "names": ["osm_auth_exports", "__export", "osmAuth", "o", "oauth", "_store", "e", "_mock", "k", "v", "token", "callback", "_preopenPopup", "error", "popup", "_generatePkceChallenge", "pkce", "_authenticate", "resolve", "reject", "errback", "err", "result", "w", "h", "settings", "x", "state", "generateState", "url", "utilQsString", "params", "utilStringQs", "_getAccessToken", "accessTokenDone", "xhr", "access_token", "auth_code", "code_verifier", "broughtPopupToFront", "resource", "options", "_doFetch", "_doXHR", "done", "method", "data", "headers", "val", "obj", "key", "str", "i", "pair", "parts", "supportsWebCryptoAPI", "random", "base64", "verifier", "char", "hash", "code_challenge", "chars", "buffer"] + "sourcesContent": ["\n/**\n * osmAuth\n * Easy authentication with OpenStreetMap over OAuth 2.0.\n * @module\n *\n * @param o `Object` containing options:\n * @param o.scope OAuth2 scopes requested (e.g. \"read_prefs write_api\")\n * @param o.client_id OAuth2 client ID\n * @param o.redirect_uri OAuth2 redirect URI (e.g. \"http://127.0.0.1:8080/land.html\")\n * @param o.access_token Can pre-authorize with an OAuth2 bearer token if you have one\n * @param o.apiUrl A base url for the OSM API (default: \"https://api.openstreetmap.org\")\n * @param o.url A base url for the OAuth2 handshake (default: \"https://www.openstreetmap.org\")\n * @param o.auto If `true`, attempt to authenticate automatically when calling `.xhr()` or `.fetch()` (default: `false`)\n * @param o.singlepage If `true`, use page redirection instead of a popup (default: `false`)\n * @param o.loading Function called when auth-related xhr calls start\n * @param o.done Function called when auth-related xhr calls end\n * @param o.locale The locale to use on the OAuth2 authentication page. Optional.\n * @return `self`\n */\nexport function osmAuth(o) {\n var oauth = {};\n\n // Mock localStorage if needed.\n // Note that accessing localStorage may throw a `SecurityError`, so wrap in a try/catch.\n var _store = null;\n try {\n _store = window.localStorage;\n } catch (e) {\n var _mock = new Map();\n _store = {\n isMocked: true,\n hasItem: (k) => _mock.has(k),\n getItem: (k) => _mock.get(k),\n setItem: (k, v) => _mock.set(k, v),\n removeItem: (k) => _mock.delete(k),\n clear: () => _mock.clear()\n };\n }\n\n /**\n * token\n * Get/Set tokens. These are prefixed with the base URL so that `osm-auth`\n * can be used with multiple APIs and the keys in `localStorage` will not clash\n * @param {string} k key\n * @param {string?} v value\n * @return {string?} If getting, returns the stored value or `null`. If setting, returns `undefined`.\n */\n function token(k, v) {\n var key = o.url + k;\n if (arguments.length === 1) {\n var val = _store.getItem(key) || '';\n // Note: legacy tokens might be wrapped in double quotes - remove them, see #129\n return val.replace(/\"/g, '');\n\n } else if (arguments.length === 2) {\n if (v) {\n return _store.setItem(key, v);\n } else {\n return _store.removeItem(key);\n }\n }\n }\n\n\n /**\n * authenticated\n * Test whether the user is currently authenticated\n *\n * @return {boolean} `true` if authenticated, `false` if not\n */\n oauth.authenticated = function() {\n return !!token('oauth2_access_token');\n };\n\n\n /**\n * logout\n * Removes any stored authentication tokens (legacy OAuth1 tokens too)\n *\n * @return `self`\n */\n oauth.logout = function () {\n token('oauth2_access_token', ''); // OAuth2\n token('oauth_token', ''); // OAuth1\n token('oauth_token_secret', ''); // OAuth1\n token('oauth_request_token_secret', ''); // OAuth1\n return oauth;\n };\n\n\n /**\n * authenticate\n * First logs out, then runs the authentiation flow, finally calls the callback.\n * TODO: detect lack of click event (probably can settimeout it)\n *\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.authenticate = function(callback) {\n if (oauth.authenticated()) {\n callback(null, oauth);\n return;\n }\n\n oauth.logout();\n\n _preopenPopup(function(error, popup) {\n if (error) {\n callback(error);\n } else {\n _generatePkceChallenge(function(pkce) {\n _authenticate(pkce, popup, callback);\n });\n }\n });\n };\n\n\n /**\n * authenticateAsync\n * Promisified version of `authenticate`\n * @return {Promise} Promise settled with whatever `_authenticate` did\n */\n oauth.authenticateAsync = function() {\n if (oauth.authenticated()) {\n return Promise.resolve(oauth);\n }\n\n oauth.logout();\n\n return new Promise((resolve, reject) => {\n var errback = (err, result) => {\n if (err) {\n reject(err);\n } else {\n resolve(result);\n }\n };\n\n _preopenPopup((error, popup) => {\n if (error) {\n errback(error);\n } else {\n _generatePkceChallenge(pkce => _authenticate(pkce, popup, errback));\n }\n });\n });\n };\n\n\n /**\n * opens an empty popup to be later used for the authentication page\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n function _preopenPopup(callback) {\n if (o.singlepage) {\n callback(null, undefined);\n return;\n }\n\n // Create a 550x610 popup window in the center of the screen\n var w = 550;\n var h = 610;\n var settings = [\n ['width', w],\n ['height', h],\n ['left', window.screen.width / 2 - w / 2],\n ['top', window.screen.height / 2 - h / 2],\n ]\n .map(function (x) { return x.join('='); })\n .join(',');\n var popup = window.open('about:blank', 'oauth_window', settings);\n if (popup) {\n callback(null, popup);\n } else {\n var error = new Error('Popup was blocked');\n error.status = 'popup-blocked';\n callback(error);\n }\n }\n\n\n /**\n * _authenticate\n * internal authenticate\n *\n * @param {Object} pkce Object containing PKCE code challenge properties\n * @param {Window} popup Popup Window to use for the authentication page, should be undefined when using singlepage mode\n * @param {function} callback Errback-style callback that accepts `(err, result)`\n */\n function _authenticate(pkce, popup, callback) {\n var state = generateState();\n\n // ## Request authorization to access resources from the user\n // and receive authorization code\n var url =\n o.url +\n '/oauth2/authorize?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n response_type: 'code',\n scope: o.scope,\n state: state,\n code_challenge: pkce.code_challenge,\n code_challenge_method: pkce.code_challenge_method,\n locale: o.locale || '',\n });\n\n if (o.singlepage) {\n if (_store.isMocked) {\n // in singlepage mode, PKCE requires working non-volatile storage\n var error = new Error('localStorage unavailable, but required in singlepage mode');\n error.status = 'pkce-localstorage-unavailable';\n callback(error);\n return;\n }\n var params = utilStringQs(window.location.search.slice(1));\n if (params.code) {\n oauth.bootstrapToken(params.code, callback);\n } else {\n // save OAuth2 state and PKCE challenge in local storage, for later use\n // in the `/oauth/token` request\n token('oauth2_state', state);\n token('oauth2_pkce_code_verifier', pkce.code_verifier);\n window.location = url;\n }\n } else {\n oauth.popupWindow = popup;\n popup.location = url;\n }\n\n // Called by a function in the redirect URL page, in the popup window. The\n // window closes itself.\n window.authComplete = function (url) {\n var params = utilStringQs(url.split('?')[1]);\n if (params.state !== state) {\n error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n _getAccessToken(params.code, pkce.code_verifier, accessTokenDone);\n delete window.authComplete;\n };\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n }\n\n\n /**\n * _getAccessToken\n * The client requests an access token by authenticating with the\n * authorization server and presenting the `auth_code`, brought\n * in from a function call on a landing page popup.\n * @param {string} auth_code\n * @param {string} code_verifier\n * @param {function} accessTokenDone Errback-style callback `(err, result)`, called when complete\n */\n function _getAccessToken(auth_code, code_verifier, accessTokenDone) {\n var url =\n o.url +\n '/oauth2/token?' +\n utilQsString({\n client_id: o.client_id,\n redirect_uri: o.redirect_uri,\n grant_type: 'authorization_code',\n code: auth_code,\n code_verifier: code_verifier\n });\n\n // The authorization server authenticates the client and validates\n // the authorization grant, and if valid, issues an access token.\n oauth.rawxhr('POST', url, null, null, null, accessTokenDone);\n o.loading();\n }\n\n\n /**\n * bringPopupWindowToFront\n * Tries to bring an existing authentication popup to the front.\n *\n * @return {boolean} `true` if it succeeded, `false` if not\n */\n oauth.bringPopupWindowToFront = function() {\n var broughtPopupToFront = false;\n try {\n // This may cause a cross-origin error:\n // `DOMException: Blocked a frame with origin \"...\" from accessing a cross-origin frame.`\n if (oauth.popupWindow && !oauth.popupWindow.closed) {\n oauth.popupWindow.focus();\n broughtPopupToFront = true;\n }\n } catch (err) {\n // Bringing popup window to front failed (probably because of the cross-origin error mentioned above)\n }\n return broughtPopupToFront;\n };\n\n\n /**\n * bootstrapToken\n * The authorization code is a temporary code that a client can exchange for an access token.\n * If using this library in single-page mode, you'll need to call this once your application\n * has an `auth_code` and wants to get an access_token.\n *\n * @param {string} auth_code The OAuth2 `auth_code`\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return none\n */\n oauth.bootstrapToken = function(auth_code, callback) {\n var state = token('oauth2_state');\n token('oauth2_state', '');\n var params = utilStringQs(window.location.search.slice(1));\n if (params.state !== state) {\n var error = new Error('Invalid state');\n error.status = 'invalid-state';\n callback(error);\n return;\n }\n var code_verifier = token('oauth2_pkce_code_verifier');\n token('oauth2_pkce_code_verifier', '');\n _getAccessToken(auth_code, code_verifier, accessTokenDone);\n\n function accessTokenDone(err, xhr) {\n o.done();\n if (err) {\n callback(err);\n return;\n }\n var access_token = JSON.parse(xhr.response);\n token('oauth2_access_token', access_token.access_token);\n callback(null, oauth);\n }\n };\n\n\n /**\n * fetch\n * A `fetch` wrapper that includes the Authorization header if the user is authenticated.\n * https://developer.mozilla.org/en-US/docs/Web/API/fetch\n *\n * @param {string} resource Resource passed to `fetch`\n * @param {Object} options Options passed to `fetch`\n * @return {Promise} Promise that wraps `authenticateAsync` then `fetch`\n */\n oauth.fetch = function(resource, options) {\n if (oauth.authenticated()) {\n return _doFetch();\n } else {\n if (o.auto) {\n return oauth.authenticateAsync().then(_doFetch);\n } else {\n return Promise.reject(new Error('not authenticated'));\n }\n }\n\n function _doFetch() {\n options = options || {};\n if (!options.headers) {\n options.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n }\n options.headers.Authorization = 'Bearer ' + token('oauth2_access_token');\n return fetch(resource, options);\n }\n };\n\n\n /**\n * xhr\n * A `XMLHttpRequest` wrapper that does authenticated calls if the user has logged in.\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param {Object} options\n * @param options.method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param options.prefix If `true` path contains a path, if `false` path contains the full url\n * @param options.path The URL path (e.g. \"/api/0.6/user/details\") (or full url, if `prefix`=`false`)\n * @param options.content Passed to `xhr.send`\n * @param options.headers `Object` containing request headers\n * @param {function} callback Errback-style callback `(err, result)`, called when complete\n * @return {XMLHttpRequest} `XMLHttpRequest` if authenticated, otherwise `null`\n */\n oauth.xhr = function (options, callback) {\n if (oauth.authenticated()) {\n return _doXHR();\n } else {\n if (o.auto) {\n oauth.authenticate(_doXHR);\n return;\n } else {\n callback('not authenticated', null);\n return;\n }\n }\n\n function _doXHR() {\n var url = options.prefix !== false ? (o.apiUrl + options.path) : options.path;\n return oauth.rawxhr(\n options.method,\n url,\n token('oauth2_access_token'),\n options.content,\n options.headers,\n done\n );\n }\n\n function done(err, xhr) {\n if (err) {\n callback(err);\n } else if (xhr.responseXML) {\n callback(err, xhr.responseXML);\n } else {\n callback(err, xhr.response);\n }\n }\n };\n\n\n /**\n * rawxhr\n * Creates the XMLHttpRequest set up with a header and response handling\n * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest\n *\n * @param method Passed to `xhr.open` (e.g. 'GET', 'POST')\n * @param url Passed to `xhr.open`\n * @param access_token OAuth2 bearer token\n * @param data Passed to `xhr.send`\n * @param headers `Object` containing request headers\n * @param callback An \"errback\"-style callback (`err`, `result`), called when complete\n * @return `XMLHttpRequest`\n */\n oauth.rawxhr = function(method, url, access_token, data, headers, callback) {\n headers = headers || { 'Content-Type': 'application/x-www-form-urlencoded' };\n\n if (access_token) {\n headers.Authorization = 'Bearer ' + access_token;\n }\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (4 === xhr.readyState && 0 !== xhr.status) {\n if (/^20\\d$/.test(xhr.status)) { // a 20x status code - OK\n callback(null, xhr);\n } else {\n callback(xhr, null);\n }\n }\n };\n xhr.onerror = function (e) {\n callback(e, null);\n };\n\n xhr.open(method, url, true);\n for (var h in headers) xhr.setRequestHeader(h, headers[h]);\n\n xhr.send(data);\n return xhr;\n };\n\n\n /**\n * preauth\n * Pre-authorize this object, if we already have access token from the start\n *\n * @param {Object} val Object containing `access_token` property\n * @return `self`\n */\n oauth.preauth = function(val) {\n if (val && val.access_token) {\n token('oauth2_access_token', val.access_token);\n }\n return oauth;\n };\n\n\n /**\n * options (getter / setter)\n * If passed with no arguments, just return the options\n * If passed an Object, set the options then attempt to pre-authorize\n *\n * @param val? Object containing options\n * @return current `options` (if getting), or `self` (if setting)\n */\n oauth.options = function(val) {\n if (!arguments.length) return o;\n\n o = val;\n o.apiUrl = o.apiUrl || 'https://api.openstreetmap.org';\n o.url = o.url || 'https://www.openstreetmap.org';\n o.auto = o.auto || false;\n o.singlepage = o.singlepage || false;\n\n // Optional loading and loading-done functions for nice UI feedback.\n // by default, no-ops\n o.loading = o.loading || function () {};\n o.done = o.done || function () {};\n return oauth.preauth(o);\n };\n\n\n // Everything below here is initialization/setup code\n // Handle options and attempt to pre-authorize\n oauth.options(o);\n\n return oauth;\n}\n\n\n/**\n * utilQsString\n * Transforms object of `key=value` pairs into query string\n * @param {Object} Object of `key=value` pairs\n * @returns {string} query string\n */\nfunction utilQsString(obj) {\n return Object.keys(obj)\n .filter(function(key) {\n return obj[key] !== undefined;\n })\n .sort()\n .map(function(key) {\n return (encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));\n })\n .join('&');\n}\n\n/**\n * utilStringQs\n * Transforms query string into object of `key=value` pairs\n * @param {string} query string\n * @returns {Object} Object of `key=value` pairs\n */\nfunction utilStringQs(str) {\n var i = 0; // advance past any leading '?' or '#' characters\n while (i < str.length && (str[i] === '?' || str[i] === '#')) i++;\n str = str.slice(i);\n\n return str.split('&').reduce(function(obj, pair) {\n var parts = pair.split('=');\n if (parts.length === 2) {\n obj[parts[0]] = decodeURIComponent(parts[1]);\n }\n return obj;\n }, {});\n}\n\n\n/**\n * supportsWebCryptoAPI\n * https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n * @returns {boolean} `true` if WebCryptoAPI is available\n */\nfunction supportsWebCryptoAPI() {\n return window && window.crypto\n && window.crypto.getRandomValues\n && window.crypto.subtle\n && window.crypto.subtle.digest;\n}\n\n\n/**\n * Generates a challenge/verifier pair for PKCE.\n * If the browser does not support the WebCryptoAPI, the \"plain\" method is\n * used as a fallback instead of a SHA-256 hash.\n * @param {callback} callback called with the result of the generated PKCE challenge\n */\nfunction _generatePkceChallenge(callback) {\n var code_verifier;\n if (supportsWebCryptoAPI()) {\n // generate a random code_verifier\n // https://datatracker.ietf.org/doc/html/rfc7636#section-7.1\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n code_verifier = base64(random.buffer);\n var verifier = Uint8Array.from(Array.from(code_verifier).map(function(char) {\n return char.charCodeAt(0);\n }));\n\n // generate challenge for code verifier\n window.crypto.subtle.digest('SHA-256', verifier).then(function(hash) {\n var code_challenge = base64(hash);\n\n callback({\n code_challenge: code_challenge,\n code_verifier: code_verifier,\n code_challenge_method: 'S256'\n });\n });\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n code_verifier = '';\n for (var i=0; i<64; i++) {\n code_verifier += chars[Math.floor(Math.random() * chars.length)];\n }\n callback({\n code_verifier: code_verifier,\n code_challenge: code_verifier,\n code_challenge_method: 'plain',\n });\n }\n}\n\n\n/**\n * Returns a random state to be used as the \"state\" of the OAuth2 authentication\n * See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12\n */\nfunction generateState() {\n var state;\n if (supportsWebCryptoAPI()) {\n var random = window.crypto.getRandomValues(new Uint8Array(32));\n state = base64(random.buffer);\n } else {\n // browser does not support Web Crypto API (e.g. IE11) -> fall back to \"plain\" method\n var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n state = '';\n for (var i=0; i<64; i++) {\n state += chars[Math.floor(Math.random() * chars.length)];\n }\n }\n return state;\n}\n\n\n/**\n * base64\n * Converts binary buffer to base64 encoded string, as used in rfc7636\n * @param {ArrayBuffer} buffer\n * @returns {string} base64 encoded\n */\nfunction base64(buffer) {\n return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))\n .replace(/\\//g, '_')\n .replace(/\\+/g, '-')\n .replace(/[=]/g, '');\n}\n"], + "mappings": "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", + "names": ["osm_auth_exports", "__export", "osmAuth", "o", "oauth", "_store", "e", "_mock", "k", "v", "token", "key", "val", "callback", "_preopenPopup", "error", "popup", "_generatePkceChallenge", "pkce", "_authenticate", "resolve", "reject", "errback", "err", "result", "w", "h", "settings", "x", "state", "generateState", "url", "utilQsString", "params", "utilStringQs", "_getAccessToken", "accessTokenDone", "xhr", "access_token", "auth_code", "code_verifier", "broughtPopupToFront", "resource", "options", "_doFetch", "_doXHR", "done", "method", "data", "headers", "obj", "str", "i", "pair", "parts", "supportsWebCryptoAPI", "random", "base64", "verifier", "char", "hash", "code_challenge", "chars", "buffer"] } diff --git a/src/osm-auth.mjs b/src/osm-auth.mjs index ffa6a0b..b64f2e1 100644 --- a/src/osm-auth.mjs +++ b/src/osm-auth.mjs @@ -47,8 +47,19 @@ export function osmAuth(o) { * @return {string?} If getting, returns the stored value or `null`. If setting, returns `undefined`. */ function token(k, v) { - if (arguments.length === 1) return _store.getItem(o.url + k); - else if (arguments.length === 2) return _store.setItem(o.url + k, v); + var key = o.url + k; + if (arguments.length === 1) { + var val = _store.getItem(key) || ''; + // Note: legacy tokens might be wrapped in double quotes - remove them, see #129 + return val.replace(/"/g, ''); + + } else if (arguments.length === 2) { + if (v) { + return _store.setItem(key, v); + } else { + return _store.removeItem(key); + } + } } @@ -195,7 +206,7 @@ export function osmAuth(o) { state: state, code_challenge: pkce.code_challenge, code_challenge_method: pkce.code_challenge_method, - locale: o.locale || "", + locale: o.locale || '', }); if (o.singlepage) {