[gnome-maps/wip/mlundblad/osm-oauth2] WIP: Migrate to OAuth2 for OSM editing
- From: Marcus Lundblad <mlundblad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-maps/wip/mlundblad/osm-oauth2] WIP: Migrate to OAuth2 for OSM editing
- Date: Sun, 21 Aug 2022 19:42:10 +0000 (UTC)
commit 2ae381b66824c6d5c7429a4e3e8fd16edfc8150f
Author: Marcus Lundblad <ml dfupdate se>
Date: Sun Aug 21 00:57:33 2022 +0200
WIP: Migrate to OAuth2 for OSM editing
data/org.gnome.Maps.gschema.xml | 4 +-
data/ui/osm-account-dialog.ui | 17 +------
lib/maps-osm-oauth-proxy-call.c | 6 +--
lib/maps-osm-oauth-proxy-call.h | 10 ++--
org.gnome.Maps.json | 6 +--
src/osmAccountDialog.js | 21 ++------
src/osmConnection.js | 110 +++++++++++++++++-----------------------
src/osmEdit.js | 16 ++----
8 files changed, 70 insertions(+), 120 deletions(-)
---
diff --git a/data/org.gnome.Maps.gschema.xml b/data/org.gnome.Maps.gschema.xml
index 2ed4ad61..91b7f24e 100644
--- a/data/org.gnome.Maps.gschema.xml
+++ b/data/org.gnome.Maps.gschema.xml
@@ -51,10 +51,10 @@
<summary>Number of recent routes to store</summary>
<description>Number of recently visited routes to store.</description>
</key>
- <key name="osm-username" type="s">
+ <key name="osm-username-oauth2" type="s">
<default>""</default>
<summary>OpenStreetMap username or e-mail address</summary>
- <description>Indicates if the user has signed in to edit OpenStreetMap data.</description>
+ <description>Indicates if the user has signed in to edit OpenStreetMap data using OAith2.</description>
</key>
<key name="transportation-type" enum="org.gnome.maps.TransportationType">
<default>'pedestrian'</default>
diff --git a/data/ui/osm-account-dialog.ui b/data/ui/osm-account-dialog.ui
index 31d636ee..46ee8787 100644
--- a/data/ui/osm-account-dialog.ui
+++ b/data/ui/osm-account-dialog.ui
@@ -62,19 +62,6 @@ Then fill in the obtained verification code here in the next step.</property>
</layout>
</object>
</child>
- <child>
- <object class="GtkSpinner" id="signInSpinner">
- <property name="height_request">16</property>
- <property name="width_request">16</property>
- <property name="spinning">True</property>
- <property name="halign">end</property>
- <property name="hexpand">1</property>
- <layout>
- <property name="column">0</property>
- <property name="row">3</property>
- </layout>
- </object>
- </child>
<child>
<object class="GtkLinkButton">
<property name="focusable">1</property>
@@ -83,7 +70,7 @@ Then fill in the obtained verification code here in the next step.</property>
<property name="halign">end</property>
<property name="hexpand">1</property>
<layout>
- <property name="column">1</property>
+ <property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
@@ -96,7 +83,7 @@ Then fill in the obtained verification code here in the next step.</property>
<class name="suggested-action"/>
</style>
<layout>
- <property name="column">2</property>
+ <property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
diff --git a/lib/maps-osm-oauth-proxy-call.c b/lib/maps-osm-oauth-proxy-call.c
index 5e9e7544..47359c60 100644
--- a/lib/maps-osm-oauth-proxy-call.c
+++ b/lib/maps-osm-oauth-proxy-call.c
@@ -33,7 +33,7 @@ struct _MapsOSMOAuthProxyCallPrivate
};
G_DEFINE_TYPE_WITH_PRIVATE(MapsOSMOAuthProxyCall, maps_osm_oauth_proxy_call,
- OAUTH_TYPE_PROXY_CALL);
+ REST_TYPE_OAUTH2_PROXY_CALL);
static gboolean
maps_osm_oauth_proxy_call_serialize_params (RestProxyCall *call,
@@ -85,9 +85,9 @@ maps_osm_oauth_proxy_call_init (MapsOSMOAuthProxyCall *call)
}
MapsOSMOAuthProxyCall *
-maps_osm_oauth_proxy_call_new (OAuthProxy *proxy, const char *payload)
+maps_osm_oauth_proxy_call_new (RestOAuth2Proxy *proxy, const char *payload)
{
- g_return_val_if_fail (OAUTH_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (proxy), NULL);
g_return_val_if_fail (payload != NULL, NULL);
MapsOSMOAuthProxyCall *call =
diff --git a/lib/maps-osm-oauth-proxy-call.h b/lib/maps-osm-oauth-proxy-call.h
index e9c240d8..03c6a363 100644
--- a/lib/maps-osm-oauth-proxy-call.h
+++ b/lib/maps-osm-oauth-proxy-call.h
@@ -22,8 +22,8 @@
#include <glib-object.h>
-#include <rest/oauth-proxy-call.h>
-#include <rest/oauth-proxy.h>
+#include <rest/rest-oauth2-proxy-call.h>
+#include <rest/rest-oauth2-proxy.h>
G_BEGIN_DECLS
@@ -40,17 +40,17 @@ typedef struct _MapsOSMOAuthProxyCallClass MapsOSMOAuthProxyCallClass;
struct _MapsOSMOAuthProxyCall
{
- OAuthProxyCall parent;
+ RestOAuth2ProxyCall parent;
MapsOSMOAuthProxyCallPrivate *priv;
};
struct _MapsOSMOAuthProxyCallClass
{
- OAuthProxyCallClass parent_class;
+ RestOAuth2ProxyCallClass parent_class;
};
GType maps_osm_oauth_proxy_call_get_type(void);
-MapsOSMOAuthProxyCall *maps_osm_oauth_proxy_call_new (OAuthProxy *proxy,
+MapsOSMOAuthProxyCall *maps_osm_oauth_proxy_call_new (RestOAuth2Proxy *proxy,
const char *content);
G_END_DECLS
diff --git a/org.gnome.Maps.json b/org.gnome.Maps.json
index 35a27a54..9558cf4e 100644
--- a/org.gnome.Maps.json
+++ b/org.gnome.Maps.json
@@ -90,9 +90,9 @@
],
"sources" : [
{
- "type" : "archive",
- "url" : "https://gitlab.gnome.org/GNOME/librest/-/archive/1.0.0/librest-1.0.0.tar.gz",
- "sha256" : "eeba5ddbf91a29decec01c3ccce64b922bd9bf52d631e307e185227295aea51d"
+ "type" : "git",
+ "url" : "https://gitlab.gnome.org/GNOME/librest.git",
+ "branch": "master"
}
]
},
diff --git a/src/osmAccountDialog.js b/src/osmAccountDialog.js
index 378960b8..035a77d8 100644
--- a/src/osmAccountDialog.js
+++ b/src/osmAccountDialog.js
@@ -76,24 +76,10 @@ export class OSMAccountDialog extends Gtk.Dialog {
}
_performSignIn() {
- // turn on signing in spinner
- this._signInSpinner.visible = true;
- this._signInButton.sensitive = false;
+ // switch to the verification view
+ this._stack.visible_child_name = 'verify';
- Application.osmEdit.performOAuthSignIn(this._onOAuthTokenAuthorized.bind(this));
- }
-
- _onOAuthTokenAuthorized(success) {
- if (success) {
- // switch to the verification view
- this._stack.visible_child_name = 'verify';
- } else {
- this._errorLabel.visible = true;
- this._errorLabel.label = _("Failed to authorize access");
- this._signInButton.label = _("Try again");
- }
-
- this._signInSpinner.visible = false;
+ Application.osmEdit.performOAuthSignIn();
}
_onVerifyButtonClicked() {
@@ -169,7 +155,6 @@ GObject.registerClass({
Template: 'resource:///org/gnome/Maps/ui/osm-account-dialog.ui',
InternalChildren: ['stack',
'signInButton',
- 'signInSpinner',
'verificationEntry',
'verifyButton',
'errorLabel',
diff --git a/src/osmConnection.js b/src/osmConnection.js
index 5a18f350..4ab1f924 100644
--- a/src/osmConnection.js
+++ b/src/osmConnection.js
@@ -38,10 +38,11 @@ const BASE_URL = 'https://api.openstreetmap.org/api';
const API_VERSION = '0.6';
/* OAuth constants */
-const CONSUMER_KEY = '2lbpDoED0ZspGssTBAJ8zOCtrtmUoX4KnmZUIWIK';
-const CONSUMER_SECRET = 'AO9BhDl9sJ33DjaZgQmYcNIuM3ZSml4xtugai6gE';
-const OAUTH_ENDPOINT_URL = 'https://www.openstreetmap.org/oauth';
-const LOGIN_URL = 'https://www.openstreetmap.org/login';
+const CLIENT_KEY = 'ATOMKAKOXQuAJXpFxkm__nDVRlJLYYmP-0P54UfDnZI';
+const CLIENT_SECRET = '9vda-8M_lt0cLJMLJlbTfJVRDGiS2-pPbeSNMRqBQ0k';
+const AUTH_URL = 'https://www.openstreetmap.org/oauth2/authorize';
+const ACCESS_TOKEN_URL = 'https://www.openstreetmap.org/oauth2/token';
+const REDIRECT_URL = 'urn:ietf:wg:oauth:2.0:oob';
const SECRET_SCHEMA = new Secret.Schema("org.gnome.Maps",
Secret.SchemaFlags.NONE,
@@ -55,9 +56,10 @@ export class OSMConnection {
this._session = new Soup.Session({ user_agent : 'gnome-maps/' + pkg.version });
/* OAuth proxy used for making OSM uploads */
- this._callProxy = Rest.OAuthProxy.new(CONSUMER_KEY, CONSUMER_SECRET,
- BASE_URL + '/' + API_VERSION,
- false);
+ this._callProxy = Rest.OAuth2Proxy.new(AUTH_URL, ACCESS_TOKEN_URL,
+ REDIRECT_URL,
+ CLIENT_KEY, CLIENT_SECRET,
+ BASE_URL + '/' + API_VERSION);
GnomeMaps.osm_init();
}
@@ -93,7 +95,7 @@ export class OSMConnection {
OAuth access token enrolled, so, if the currently instantiated
proxy instance doesn't have a token set, we could safely count on
it being present in the keyring */
- if (this._callProxy.get_token() === null) {
+ if (this._callProxy.get_access_token() === null) {
Secret.password_lookup(SECRET_SCHEMA, {}, null, (s, res) => {
this._onPasswordLookedUp(res,
comment,
@@ -108,25 +110,29 @@ export class OSMConnection {
let password = Secret.password_lookup_finish(result);
if (password) {
- let token = password.split(':')[0];
- let secret = password.split(':')[1];
-
- this._callProxy.token = token;
- this._callProxy.token_secret = secret;
+ this._callProxy.access_token = password;
this._doOpenChangeset(comment, callback);
} else {
callback(false, null, null);
}
}
+ _createCallWithPayload(payload, method, func) {
+ let call = GnomeMaps.OSMOAuthProxyCall.new(this._callProxy, payload);
+
+ call.set_method(method);
+ call.set_function(func);
+ call.add_header('Authorization',
+ 'Bearer ' + this._callProxy.access_token);
+
+ return call;
+ }
+
_doOpenChangeset(comment, callback) {
let changeset =
GnomeMaps.OSMChangeset.new(comment, 'gnome-maps ' + pkg.version);
let xml = changeset.serialize();
-
- let call = GnomeMaps.OSMOAuthProxyCall.new(this._callProxy, xml);
- call.set_method('PUT');
- call.set_function('/changeset/create');
+ let call = this._createCallWithPayload(xml, 'PUT', '/changeset/create');
call.invoke_async(null, (call, res, userdata) =>
{ this._onChangesetOpened(call, callback); });
@@ -146,10 +152,10 @@ export class OSMConnection {
object.changeset = changeset;
let xml = object.serialize();
- let call = GnomeMaps.OSMOAuthProxyCall.new(this._callProxy, xml);
-
- call.set_method('PUT');
- call.set_function(this._getCreateOrUpdateFunction(object, type));
+ let call =
+ this._createCallWithPayload(xml, 'PUT',
+ this._getCreateOrUpdateFunction(object,
+ type));
call.invoke_async(null, (call, res, userdata) =>
{ this._onObjectUploaded(call, callback); });
@@ -168,10 +174,9 @@ export class OSMConnection {
object.changeset = changeset;
let xml = object.serialize();
- let call = GnomeMaps.OSMOAuthProxyCall.new(this._callProxy, xml);
-
- call.set_method('DELETE');
- call.set_function(this._getDeleteFunction(object, type));
+ let call =
+ this._createCallWithPayload(xml, 'DELETE',
+ this._getDeleteFunction(object, type));
call.invoke_async(null, (call, res, userdata) =>
{ this._onObjectDeleted(call, callback); });
@@ -219,46 +224,28 @@ export class OSMConnection {
return type + '/' + id;
}
- requestOAuthToken(callback) {
- /* OAuth proxy used for enrolling access tokens */
- this._oauthProxy = Rest.OAuthProxy.new(CONSUMER_KEY, CONSUMER_SECRET,
- OAUTH_ENDPOINT_URL, false);
- this._oauthProxy.request_token_async('request_token', 'oob', (p, error, w, u) => {
- this._onRequestOAuthToken(error, callback);
- }, this._oauthProxy);
- }
-
- _onRequestOAuthToken(error, callback) {
- if (error) {
- Utils.debug(error);
- callback(false);
- return;
- }
-
- this._oauthToken = this._oauthProxy.get_token();
- this._oauthTokenSecret = this._oauthProxy.get_token_secret();
- callback(true);
- }
-
- authorizeOAuthToken(callback) {
- let auth = '/authorize?oauth_token=';
- let authorizeUrl = OAUTH_ENDPOINT_URL + auth + this._oauthToken;
+ authorizeOAuthToken() {
+ this._codeChallenge = Rest.PkceCodeChallenge.new_random();
+ let [authorizeUrl, state] =
+ this._callProxy.build_authorization_url(this._codeChallenge.get_challenge(),
+ 'read_prefs write_api');
Utils.debug('Trying to open: ' + authorizeUrl);
try {
Gio.AppInfo.launch_default_for_uri(authorizeUrl, null);
- callback(true);
} catch (e) {
Utils.debug('error: ' + e.message);
- callback(false);
}
}
requestOAuthAccessToken(code, callback) {
- this._oauthProxy.access_token_async('access_token', code, (p, error, w, data) => {
- this._onAccessOAuthToken(error, callback);
- }, this._oauthProxy);
+ this._callProxy.fetch_access_token_async(code,
+ this._codeChallenge.get_verifier(),
+ null,
+ (source, res) => {
+ this._onAccessOAuthToken(res, callback);
+ });
}
fetchLoggedInUser(callback) {
@@ -292,21 +279,18 @@ export class OSMConnection {
}
}
- _onAccessOAuthToken(error, callback) {
- if (error) {
+ _onAccessOAuthToken(res, callback) {
+ let success = this._callProxy.fetch_access_token_finish(res);
+ if (!success) {
callback(false);
return;
}
- let token = this._oauthProxy.token;
- let secret = this._oauthProxy.token_secret;
+ let token = this._callProxy.access_token;
- this._callProxy.token = token;
- this._callProxy.token_secret = secret;
Secret.password_store(SECRET_SCHEMA, {}, Secret.COLLECTION_DEFAULT,
- "OSM OAuth access token and secret",
- this._oauthProxy.token + ":" +
- this._oauthProxy.token_secret, null,
+ "OSM OAuth access token",
+ token, null,
(source, result, userData) => {
this._onPasswordStored(result, callback);
});
diff --git a/src/osmEdit.js b/src/osmEdit.js
index 16f41741..e4fa02d6 100644
--- a/src/osmEdit.js
+++ b/src/osmEdit.js
@@ -34,7 +34,7 @@ export class OSMEdit {
constructor() {
this._osmConnection = new OSMConnection();
this._osmObject = null; // currently edited object
- this._username = Application.settings.get('osm-username');
+ this._username = Application.settings.get('osm-username-oauth2');
this._isSignedIn = this._username !== null && this._username.length > 0;
}
@@ -138,14 +138,8 @@ export class OSMEdit {
this._osmConnection.closeChangeset(changesetId, callback);
}
- performOAuthSignIn(callback) {
- this._osmConnection.requestOAuthToken((success) => {
- if (success) {
- this._osmConnection.authorizeOAuthToken(callback);
- } else {
- callback(false);
- }
- });
+ performOAuthSignIn() {
+ this._osmConnection.authorizeOAuthToken();
}
requestOAuthAccessToken(code, callback) {
@@ -164,7 +158,7 @@ export class OSMEdit {
* username to signify that we are signed in
*/
this._username = username ?? '_unknown_';
- Application.settings.set('osm-username', this._username);
+ Application.settings.set('osm-username-oauth2', this._username);
callback(true);
});
} else {
@@ -176,7 +170,7 @@ export class OSMEdit {
this._username = null;
this._isSignedIn = false;
- Application.settings.set('osm-username', '');
+ Application.settings.set('osm-username-oauth2', '');
this._osmConnection.signOut();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]