summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Catanzaro <mcatanzaro@redhat.com>2022-06-22 07:58:48 -0500
committerMichael Catanzaro <mcatanzaro@redhat.com>2022-06-22 07:58:48 -0500
commitaa960cdb251dd10492ff3a6bde29f2050a4ec5c6 (patch)
tree9972fbedf80fea81a7cf122f5a4cf771f18fee63 /src
parent566e73001ecc45d5b3b5caee42e7f66df8cbf971 (diff)
downloadgnome-online-accounts-aa960cdb251dd10492ff3a6bde29f2050a4ec5c6.tar.gz
Drop goaoauthprovider
OAuth 1 support has been removed from librest. It is now unused since the flickr provider was removed, so we can delete it.
Diffstat (limited to 'src')
-rw-r--r--src/goabackend/goaoauthprovider.c1649
-rw-r--r--src/goabackend/goaoauthprovider.h143
-rw-r--r--src/goabackend/goawebextension.c25
-rw-r--r--src/goabackend/meson.build1
4 files changed, 8 insertions, 1810 deletions
diff --git a/src/goabackend/goaoauthprovider.c b/src/goabackend/goaoauthprovider.c
deleted file mode 100644
index 8c2e0f2..0000000
--- a/src/goabackend/goaoauthprovider.c
+++ /dev/null
@@ -1,1649 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * Copyright © 2011 – 2017 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
-
-#include <rest/rest.h>
-#include <libsoup/soup.h>
-#include <json-glib/json-glib.h>
-#include <webkit2/webkit2.h>
-
-#include "goaprovider.h"
-#include "goautils.h"
-#include "goawebview.h"
-#include "goaoauthprovider.h"
-#include "goasouplogger.h"
-
-/**
- * SECTION:goaoauthprovider
- * @title: GoaOAuthProvider
- * @short_description: Abstract base class for OAuth 1.0a providers
- *
- * #GoaOAuthProvider is an abstract base class for OAuth 1.0a
- * compliant implementations as defined by <ulink
- * url="http://tools.ietf.org/html/rfc5849">RFC
- * 5849</ulink>. Additionally, the code works with providers
- * implementing <ulink
- * url="http://oauth.googlecode.com/svn/spec/ext/session/1.0/drafts/1/spec.html">OAuth
- * Session 1.0 Draft 1</ulink> for refreshing access tokens.
- *
- * Subclasses must implement
- * #GoaOAuthProviderClass.get_consumer_key,
- * #GoaOAuthProviderClass.get_consumer_secret,
- * #GoaOAuthProviderClass.get_request_uri,
- * #GoaOAuthProviderClass.get_authorization_uri,
- * #GoaOAuthProviderClass.get_token_uri,
- * #GoaOAuthProviderClass.get_callback_uri and
- * #GoaOAuthProviderClass.get_identity_sync methods.
- *
- * Additionally, the
- * #GoaProviderClass.get_provider_type,
- * #GoaProviderClass.get_provider_name,
- * #GoaProviderClass.build_object (this should chain up to its
- * parent class) methods must be implemented.
- *
- * Note that the #GoaProviderClass.add_account,
- * #GoaProviderClass.refresh_account and
- * #GoaProviderClass.ensure_credentials_sync methods do not
- * need to be implemented - this type implements these methods.
- */
-
-G_LOCK_DEFINE_STATIC (provider_lock);
-
-G_DEFINE_ABSTRACT_TYPE (GoaOAuthProvider, goa_oauth_provider, GOA_TYPE_PROVIDER);
-
-static gboolean
-is_authorization_error (GError *error)
-{
- gboolean ret;
-
- g_return_val_if_fail (error != NULL, FALSE);
-
- ret = FALSE;
- if (error->domain == REST_PROXY_ERROR)
- {
- if (SOUP_STATUS_IS_CLIENT_ERROR (error->code))
- ret = TRUE;
- }
- else if (g_error_matches (error, GOA_ERROR, GOA_ERROR_NOT_AUTHORIZED))
- {
- ret = TRUE;
- }
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-goa_oauth_provider_get_use_mobile_browser_default (GoaOAuthProvider *provider)
-{
- return FALSE;
-}
-
-/**
- * goa_oauth_provider_get_use_mobile_browser:
- * @provider: A #GoaOAuthProvider.
- *
- * Returns whether there is a need for the embedded browser to identify
- * itself as running on a mobile phone in order to get a more compact
- * version of the approval page.
- *
- * This is a virtual method where the default implementation returns
- * %FALSE.
- *
- * Returns: %TRUE if the embedded browser should identify itself as
- * running on a mobile platform, %FALSE otherwise.
- */
-gboolean
-goa_oauth_provider_get_use_mobile_browser (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_use_mobile_browser (provider);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-goa_oauth_provider_is_deny_node_default (GoaOAuthProvider *provider, WebKitDOMNode *node)
-{
- return FALSE;
-}
-
-/**
- * goa_oauth_provider_is_deny_node:
- * @provider: A #GoaOAuthProvider.
- * @node: A WebKitDOMNode.
- *
- * Checks whether @node is the HTML UI element that the user can use
- * to deny permission to access his account. Usually they are either a
- * WebKitDOMHTMLButtonElement or a WebKitDOMHTMLInputElement.
- *
- * Please note that providers may have multiple such elements in their
- * UI and this method should catch all of them.
- *
- * This is a virtual method where the default implementation returns
- * %FALSE.
- *
- * Returns: %TRUE if the @node can be used to deny permission.
- */
-gboolean
-goa_oauth_provider_is_deny_node (GoaOAuthProvider *provider, WebKitDOMNode *node)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->is_deny_node (provider, node);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-goa_oauth_provider_is_password_node_default (GoaOAuthProvider *provider, WebKitDOMHTMLInputElement *element)
-{
- return FALSE;
-}
-
-/**
- * goa_oauth_provider_is_password_node:
- * @provider: A #GoaOAuthProvider.
- * @element: A WebKitDOMHTMLInputElement
- *
- * Checks whether @element is the HTML UI element that the user can
- * use to enter her password. This can be used to offer a
- * #GoaPasswordBased interface by saving the user's
- * password. Providers usually frown upon doing this, so this is not
- * recommended.
- *
- * This is a virtual method where the default implementation returns
- * %FALSE.
- *
- * Returns: %TRUE if @element can be used to enter the password.
- */
-gboolean
-goa_oauth_provider_is_password_node (GoaOAuthProvider *provider, WebKitDOMHTMLInputElement *element)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- g_return_val_if_fail (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element), FALSE);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->is_password_node (provider, element);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-goa_oauth_provider_add_account_key_values_default (GoaOAuthProvider *provider,
- GVariantBuilder *builder)
-{
- /* do nothing */
-}
-
-/**
- * goa_oauth_provider_add_account_key_values:
- * @provider: A #GoaProvider.
- * @builder: A #GVariantBuilder for a <literal>a{ss}</literal> variant.
- *
- * Hook for implementations to add key/value pairs to the key-file
- * when creating an account.
- *
- * This is a virtual method where the default implementation does nothing.
- */
-void
-goa_oauth_provider_add_account_key_values (GoaOAuthProvider *provider,
- GVariantBuilder *builder)
-{
- g_return_if_fail (GOA_IS_OAUTH_PROVIDER (provider));
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->add_account_key_values (provider, builder);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gchar *
-goa_oauth_provider_build_authorization_uri_default (GoaOAuthProvider *provider,
- const gchar *authorization_uri,
- const gchar *escaped_oauth_token)
-{
- return g_strdup_printf ("%s"
- "?oauth_token=%s",
- authorization_uri,
- escaped_oauth_token);
-}
-
-/**
- * goa_oauth_provider_build_authorization_uri:
- * @provider: A #GoaOAuthProvider.
- * @authorization_uri: An authorization URI.
- * @escaped_oauth_token: An escaped oauth token.
- *
- * Builds the URI that can be opened in a web browser (or embedded web
- * browser widget) to start authenticating an user.
- *
- * The default implementation just returns the expected URI
- * (e.g. <literal>http://example.com/dialog/oauth?auth_token=1234567890</literal>)
- * - override (and chain up) if you e.g. need to to pass additional
- * parameters.
- *
- * The @authorization_uri parameter originate from the result of the
- * the goa_oauth_provider_get_authorization_uri() method. The
- * @escaped_oauth_token parameter is the temporary credentials identifier
- * escaped using g_uri_escape_string().
- *
- * Returns: (transfer full): An authorization URI that must be freed with g_free().
- */
-gchar *
-goa_oauth_provider_build_authorization_uri (GoaOAuthProvider *provider,
- const gchar *authorization_uri,
- const gchar *escaped_oauth_token)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- g_return_val_if_fail (authorization_uri != NULL, NULL);
- g_return_val_if_fail (escaped_oauth_token != NULL, NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->build_authorization_uri (provider,
- authorization_uri,
- escaped_oauth_token);
-}
-
-/**
- * goa_oauth_provider_get_consumer_key:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the consumer key identifying the client.
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_consumer_key (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_consumer_key (provider);
-}
-
-/**
- * goa_oauth_provider_get_consumer_secret:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the consumer secret identifying the client.
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_consumer_secret (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_consumer_secret (provider);
-}
-
-/**
- * goa_oauth_provider_get_request_uri:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the request uri.
- *
- * http://tools.ietf.org/html/rfc5849#section-2.1
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_request_uri (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_request_uri (provider);
-}
-
-/**
- * goa_oauth_provider_get_request_uri_params:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets additional parameters for the request URI.
- *
- * http://tools.ietf.org/html/rfc5849#section-2.1
- *
- * This is a virtual method where the default implementation returns
- * %NULL.
- *
- * Returns: (transfer full): %NULL (for no parameters) or a
- * %NULL-terminated array of (key, value) pairs that will be added to
- * the URI. The caller will free the returned value with g_strfreev().
- */
-gchar **
-goa_oauth_provider_get_request_uri_params (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_request_uri_params (provider);
-}
-
-static gchar **
-goa_oauth_provider_get_request_uri_params_default (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return NULL;
-}
-
-/**
- * goa_oauth_provider_get_authorization_uri:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the authorization uri.
- *
- * http://tools.ietf.org/html/rfc5849#section-2.2
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_authorization_uri (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_authorization_uri (provider);
-}
-
-/**
- * goa_oauth_provider_get_token_uri:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the token uri.
- *
- * http://tools.ietf.org/html/rfc5849#section-2.3
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_token_uri (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_token_uri (provider);
-}
-
-/**
- * goa_oauth_provider_get_callback_uri:
- * @provider: A #GoaOAuthProvider.
- *
- * Gets the callback uri.
- *
- * http://tools.ietf.org/html/rfc5849#section-2.1
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: (transfer none): A string owned by @provider - do not free.
- */
-const gchar *
-goa_oauth_provider_get_callback_uri (GoaOAuthProvider *provider)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_callback_uri (provider);
-}
-
-/**
- * goa_oauth_provider_get_identity_sync:
- * @provider: A #GoaOAuthProvider.
- * @access_token: A valid OAuth 1.0 access token.
- * @access_token_secret: The valid secret for @access_token.
- * @out_presentation_identity: (out): Return location for presentation identity or %NULL.
- * @cancellable: (allow-none): A #GCancellable or %NULL.
- * @error: Return location for error or %NULL.
- *
- * Method that returns the identity corresponding to @access_token and
- * @access_token_secret.
- *
- * The identity is needed because all authentication happens out of
- * band. In addition to the identity, an implementation also returns a
- * <emphasis>presentation identity</emphasis> that is more suitable
- * for presentation (the identity could be a GUID for example).
- *
- * The calling thread is blocked while the identity is obtained.
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: The identity or %NULL if error is set. The returned string
- * must be freed with g_free().
- */
-gchar *
-goa_oauth_provider_get_identity_sync (GoaOAuthProvider *provider,
- const gchar *access_token,
- const gchar *access_token_secret,
- gchar **out_presentation_identity,
- GCancellable *cancellable,
- GError **error)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- g_return_val_if_fail (access_token != NULL, NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->get_identity_sync (provider,
- access_token,
- access_token_secret,
- out_presentation_identity,
- cancellable,
- error);
-}
-
-/**
- * goa_oauth_provider_is_identity_node:
- * @provider: A #GoaOAuthProvider.
- * @element: A WebKitDOMHTMLInputElement.
- *
- * Checks whether @element is the HTML UI element that the user can
- * use to identify herself at the provider.
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: %TRUE if the @element can be used to deny permission.
- */
-gboolean
-goa_oauth_provider_is_identity_node (GoaOAuthProvider *provider, WebKitDOMHTMLInputElement *element)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->is_identity_node (provider, element);
-}
-
-/**
- * goa_oauth_provider_parse_request_token_error:
- * @provider: A #GoaOAuthProvider.
- * @call: The #RestProxyCall that was used to fetch the request token.
- *
- * Tries to parse the headers and payload within @call to provide a
- * human readable error message in case the request token could not
- * be fetched.
- *
- * This is a pure virtual method - a subclass must provide an
- * implementation.
- *
- * Returns: A human readable error message or %NULL if the cause of the
- * error could not be determined. The returned string must be freed with
- * g_free().
- */
-gchar *
-goa_oauth_provider_parse_request_token_error (GoaOAuthProvider *provider, RestProxyCall *call)
-{
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- return GOA_OAUTH_PROVIDER_GET_CLASS (provider)->parse_request_token_error (provider, call);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gchar *
-get_tokens_sync (GoaOAuthProvider *provider,
- const gchar *token,
- const gchar *token_secret,
- const gchar *session_handle, /* may be NULL */
- const gchar *verifier, /* may be NULL */
- gchar **out_access_token_secret,
- gint *out_access_token_expires_in,
- gchar **out_session_handle,
- gint *out_session_handle_expires_in,
- GCancellable *cancellable,
- GError **error)
-{
- RestProxy *proxy;
- RestProxyCall *call;
- SoupLogger *logger = NULL;
- gchar *ret = NULL;
- guint status_code;
- GHashTable *f;
- const gchar *expires_in_str;
- gchar *ret_access_token = NULL;
- gchar *ret_access_token_secret = NULL;
- gint ret_access_token_expires_in = 0;
- gchar *ret_session_handle = NULL;
- gint ret_session_handle_expires_in = 0;
-
- proxy = oauth_proxy_new (goa_oauth_provider_get_consumer_key (provider),
- goa_oauth_provider_get_consumer_secret (provider),
- goa_oauth_provider_get_token_uri (provider),
- FALSE);
- logger = goa_soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
- rest_proxy_add_soup_feature (proxy, SOUP_SESSION_FEATURE (logger));
- oauth_proxy_set_token (OAUTH_PROXY (proxy), token);
- oauth_proxy_set_token_secret (OAUTH_PROXY (proxy), token_secret);
- call = rest_proxy_new_call (proxy);
- rest_proxy_call_set_method (call, "POST");
- if (verifier != NULL)
- rest_proxy_call_add_param (call, "oauth_verifier", verifier);
- if (session_handle != NULL)
- rest_proxy_call_add_param (call, "oauth_session_handle", session_handle);
- /* TODO: cancellable support? */
- if (!rest_proxy_call_sync (call, error))
- goto out;
-
- status_code = rest_proxy_call_get_status_code (call);
- if (status_code != 200)
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- /* Translators: the %d is a HTTP status code and the %s is a textual description of it */
- _("Expected status 200 when requesting access token, instead got status %d (%s)"),
- status_code,
- rest_proxy_call_get_status_message (call));
- goto out;
- }
-
- f = soup_form_decode (rest_proxy_call_get_payload (call));
- ret_access_token = g_strdup (g_hash_table_lookup (f, "oauth_token"));
- ret_access_token_secret = g_strdup (g_hash_table_lookup (f, "oauth_token_secret"));
- ret_session_handle = g_strdup (g_hash_table_lookup (f, "oauth_session_handle"));
- expires_in_str = g_hash_table_lookup (f, "oauth_expires_in");
- if (expires_in_str != NULL)
- ret_access_token_expires_in = atoi (expires_in_str);
- expires_in_str = g_hash_table_lookup (f, "oauth_authorization_expires_in");
- if (expires_in_str != NULL)
- ret_session_handle_expires_in = atoi (expires_in_str);
- g_hash_table_unref (f);
-
- if (ret_access_token == NULL || ret_access_token_secret == NULL)
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- _("Missing access_token or access_token_secret headers in response"));
- goto out;
- }
-
- ret = ret_access_token; ret_access_token = NULL;
- if (out_access_token_secret != NULL)
- {
- *out_access_token_secret = ret_access_token_secret;
- ret_access_token_secret = NULL;
- }
- if (out_access_token_expires_in != NULL)
- *out_access_token_expires_in = ret_access_token_expires_in;
- if (out_session_handle != NULL)
- {
- *out_session_handle = ret_session_handle;
- ret_session_handle = NULL;
- }
- if (out_session_handle_expires_in != NULL)
- *out_session_handle_expires_in = ret_session_handle_expires_in;
-
- out:
- g_free (ret_access_token);
- g_free (ret_access_token_secret);
- g_free (ret_session_handle);
- g_clear_object (&call);
- g_clear_object (&proxy);
- g_clear_object (&logger);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
- GoaOAuthProvider *provider;
- GtkDialog *dialog;
- GError *error;
- GMainLoop *loop;
-
- gchar *password;
-
- gchar *oauth_verifier;
-
- const gchar *existing_identity;
-
- gchar *identity;
- gchar *presentation_identity;
-
- gchar *request_token;
- gchar *request_token_secret;
- gchar *access_token;
- gchar *access_token_secret;
- gint access_token_expires_in;
- gchar *session_handle;
- gint session_handle_expires_in;
-} IdentifyData;
-
-static void
-on_web_view_deny_click (GoaWebView *web_view, gpointer user_data)
-{
- IdentifyData *data = user_data;
- gtk_dialog_response (data->dialog, GTK_RESPONSE_CANCEL);
-}
-
-static void
-on_web_view_password_submit (GoaWebView *web_view, const gchar *password, gpointer user_data)
-{
- IdentifyData *data = user_data;
-
- g_free (data->password);
- data->password = g_strdup (password);
-}
-
-static gboolean
-on_web_view_decide_policy (WebKitWebView *web_view,
- WebKitPolicyDecision *decision,
- WebKitPolicyDecisionType decision_type,
- gpointer user_data)
-{
- GHashTable *key_value_pairs;
- IdentifyData *data = user_data;
- GUri *uri;
- WebKitNavigationAction *action;
- WebKitURIRequest *request;
- const gchar *query;
- const gchar *redirect_uri;
- const gchar *requested_uri;
- gint response_id = GTK_RESPONSE_NONE;
-
- if (decision_type != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION)
- return FALSE;
-
- /* TODO: use oauth_proxy_extract_access_token() */
-
- action = webkit_navigation_policy_decision_get_navigation_action (WEBKIT_NAVIGATION_POLICY_DECISION (decision));
- request = webkit_navigation_action_get_request (action);
- requested_uri = webkit_uri_request_get_uri (request);
- redirect_uri = goa_oauth_provider_get_callback_uri (data->provider);
-
- if (!g_str_has_prefix (requested_uri, redirect_uri))
- goto default_behaviour;
-
- uri = g_uri_parse (requested_uri, G_URI_FLAGS_ENCODED, NULL);
- query = g_uri_get_query (uri);
-
- if (query != NULL)
- {
- key_value_pairs = soup_form_decode (query);
-
- data->oauth_verifier = g_strdup (g_hash_table_lookup (key_value_pairs, "oauth_verifier"));
- if (data->oauth_verifier != NULL)
- response_id = GTK_RESPONSE_OK;
-
- g_hash_table_unref (key_value_pairs);
- }
-
- g_uri_unref (uri);
-
- if (data->oauth_verifier != NULL)
- goto ignore_request;
-
- /* TODO: The only OAuth1 provider is Flickr. It doesn't send any
- * error code and only redirects to the URI specified in the Flickr
- * App Garden. Re-evaluate when the situation changes.
- */
- response_id = GTK_RESPONSE_CANCEL;
- goto ignore_request;
-
- ignore_request:
- g_assert (response_id != GTK_RESPONSE_NONE);
- gtk_dialog_response (data->dialog, response_id);
- webkit_policy_decision_ignore (decision);
- return TRUE;
-
- default_behaviour:
- return FALSE;
-}
-
-static void
-rest_proxy_call_cb (GObject *source, GAsyncResult *result, gpointer user_data)
-{
- RestProxyCall *call = REST_PROXY_CALL (source);
- IdentifyData *data = user_data;
-
- if (!rest_proxy_call_invoke_finish (call, result, &data->error))
- {
- g_prefix_error (&data->error, _("Error getting a Request Token: "));
- }
- g_main_loop_quit (data->loop);
-}
-
-static gboolean
-get_tokens_and_identity (GoaOAuthProvider *provider,
- gboolean add_account,
- const gchar *existing_identity,
- GtkDialog *dialog,
- GtkBox *vbox,
- gchar **out_access_token,
- gchar **out_access_token_secret,
- gint *out_access_token_expires_in,
- gchar **out_session_handle,
- gint *out_session_handle_expires_in,
- gchar **out_identity,
- gchar **out_presentation_identity,
- gchar **out_password,
- GError **error)
-{
- gboolean ret = FALSE;
- gchar *url = NULL;
- IdentifyData data;
- gchar *escaped_request_token = NULL;
- RestProxy *proxy = NULL;
- RestProxyCall *call = NULL;
- SoupLogger *logger = NULL;
- GHashTable *f;
- GtkWidget *embed;
- GtkWidget *grid;
- GtkWidget *spinner;
- GtkWidget *web_view;
- gchar **request_params = NULL;
- guint n;
-
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- g_return_val_if_fail ((!add_account && existing_identity != NULL && existing_identity[0] != '\0')
- || (add_account && existing_identity == NULL), FALSE);
- g_return_val_if_fail (GTK_IS_DIALOG (dialog), FALSE);
- g_return_val_if_fail (GTK_IS_BOX (vbox), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* TODO: check with NM whether we're online, if not - return error */
-
- memset (&data, '\0', sizeof (IdentifyData));
- data.provider = provider;
- data.dialog = dialog;
- data.loop = g_main_loop_new (NULL, FALSE);
- data.existing_identity = existing_identity;
-
- proxy = oauth_proxy_new (goa_oauth_provider_get_consumer_key (provider),
- goa_oauth_provider_get_consumer_secret (provider),
- goa_oauth_provider_get_request_uri (provider), FALSE);
- logger = goa_soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
- rest_proxy_add_soup_feature (proxy, SOUP_SESSION_FEATURE (logger));
-
- call = rest_proxy_new_call (proxy);
- rest_proxy_call_set_method (call, "POST");
- rest_proxy_call_add_param (call, "oauth_callback", goa_oauth_provider_get_callback_uri (provider));
-
- request_params = goa_oauth_provider_get_request_uri_params (provider);
- if (request_params != NULL)
- {
- g_assert (g_strv_length (request_params) % 2 == 0);
- for (n = 0; request_params[n] != NULL; n += 2)
- rest_proxy_call_add_param (call, request_params[n], request_params[n+1]);
- }
- rest_proxy_call_invoke_async (call, NULL, rest_proxy_call_cb, &data);
-
- goa_utils_set_dialog_title (GOA_PROVIDER (provider), dialog, add_account);
-
- grid = gtk_grid_new ();
- gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL);
- gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
- gtk_container_add (GTK_CONTAINER (vbox), grid);
-
- spinner = gtk_spinner_new ();
- gtk_widget_set_hexpand (spinner, TRUE);
- gtk_widget_set_halign (spinner, GTK_ALIGN_CENTER);
- gtk_widget_set_vexpand (spinner, TRUE);
- gtk_widget_set_valign (spinner, GTK_ALIGN_CENTER);
- gtk_widget_set_size_request (GTK_WIDGET (spinner), 24, 24);
- gtk_spinner_start (GTK_SPINNER (spinner));
- gtk_container_add (GTK_CONTAINER (grid), spinner);
- gtk_widget_show_all (GTK_WIDGET (vbox));
-
- g_main_loop_run (data.loop);
- gtk_container_remove (GTK_CONTAINER (grid), spinner);
-
- if (data.error)
- goto out;
-
- if (rest_proxy_call_get_status_code (call) != 200)
- {
- gchar *msg;
-
- msg = goa_oauth_provider_parse_request_token_error (provider, call);
- if (msg == NULL)
- /* Translators: the %d is a HTTP status code and the %s is a textual description of it */
- msg = g_strdup_printf (_("Expected status 200 for getting a Request Token, instead got status %d (%s)"),
- rest_proxy_call_get_status_code (call),
- rest_proxy_call_get_status_message (call));
-
- g_set_error_literal (&data.error, GOA_ERROR, GOA_ERROR_FAILED, msg);
- g_free (msg);
- goto out;
- }
- f = soup_form_decode (rest_proxy_call_get_payload (call));
- data.request_token = g_strdup (g_hash_table_lookup (f, "oauth_token"));
- data.request_token_secret = g_strdup (g_hash_table_lookup (f, "oauth_token_secret"));
- g_hash_table_unref (f);
- if (data.request_token == NULL || data.request_token_secret == NULL)
- {
- g_set_error (&data.error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- _("Missing request_token or request_token_secret headers in response"));
- goto out;
- }
-
- escaped_request_token = g_uri_escape_string (data.request_token, NULL, TRUE);
- url = goa_oauth_provider_build_authorization_uri (provider,
- goa_oauth_provider_get_authorization_uri (provider),
- escaped_request_token);
-
- web_view = goa_web_view_new (GOA_PROVIDER (provider), existing_identity);
- gtk_widget_set_hexpand (web_view, TRUE);
- gtk_widget_set_vexpand (web_view, TRUE);
- embed = goa_web_view_get_view (GOA_WEB_VIEW (web_view));
-
- if (goa_oauth_provider_get_use_mobile_browser (provider))
- goa_web_view_fake_mobile (GOA_WEB_VIEW (web_view));
-
- webkit_web_view_load_uri (WEBKIT_WEB_VIEW (embed), url);
- g_signal_connect (embed,
- "decide-policy",
- G_CALLBACK (on_web_view_decide_policy),
- &data);
- g_signal_connect (web_view, "deny-click", G_CALLBACK (on_web_view_deny_click), &data);
- g_signal_connect (web_view, "password-submit", G_CALLBACK (on_web_view_password_submit), &data);
-
- gtk_container_add (GTK_CONTAINER (grid), web_view);
- gtk_window_set_default_size (GTK_WINDOW (dialog), -1, -1);
-
- gtk_widget_show_all (GTK_WIDGET (vbox));
- gtk_dialog_run (GTK_DIALOG (dialog));
-
- if (data.oauth_verifier == NULL)
- {
- if (data.error == NULL)
- {
- g_set_error (&data.error,
- GOA_ERROR,
- GOA_ERROR_DIALOG_DISMISSED,
- _("Dialog was dismissed"));
- }
- goto out;
- }
- g_assert (data.error == NULL);
-
- /* OK, we are done interacting with the user ... but before we can
- * make up our mind, there are two more RPC calls to make and these
- * call may take some time. So hide the dialog immediately.
- */
- gtk_widget_hide (GTK_WIDGET (dialog));
-
- /* OK, we now have the request token... we can exchange that for a
- * (short-lived) access token and session_handle (used to refresh the
- * access token)..
- */
-
- /* TODO: run in worker thread */
- data.access_token = get_tokens_sync (provider,
- data.request_token,
- data.request_token_secret,
- NULL, /* session_handle */
- data.oauth_verifier,
- &data.access_token_secret,
- &data.access_token_expires_in,
- &data.session_handle,
- &data.session_handle_expires_in,
- NULL, /* GCancellable */
- &data.error);
- if (data.access_token == NULL)
- {
- g_prefix_error (&data.error, _("Error getting an Access Token: "));
- goto out;
- }
-
- /* TODO: run in worker thread */
- data.identity = goa_oauth_provider_get_identity_sync (provider,
- data.access_token,
- data.access_token_secret,
- &data.presentation_identity,
- NULL, /* TODO: GCancellable */
- &data.error);
- if (data.identity == NULL)
- {
- g_prefix_error (&data.error, _("Error getting identity: "));
- goto out;
- }
-
- ret = TRUE;
-
- out:
- g_clear_object (&call);
-
- if (ret)
- {
- g_warn_if_fail (data.error == NULL);
- if (out_access_token != NULL)
- *out_access_token = g_strdup (data.access_token);
- if (out_access_token_secret != NULL)
- *out_access_token_secret = g_strdup (data.access_token_secret);
- if (out_access_token_expires_in != NULL)
- *out_access_token_expires_in = data.access_token_expires_in;
- if (out_session_handle != NULL)
- *out_session_handle = g_strdup (data.session_handle);
- if (out_session_handle_expires_in != NULL)
- *out_session_handle_expires_in = data.session_handle_expires_in;
- if (out_identity != NULL)
- *out_identity = g_strdup (data.identity);
- if (out_presentation_identity != NULL)
- *out_presentation_identity = g_strdup (data.presentation_identity);
- if (out_password != NULL)
- *out_password = g_strdup (data.password);
- }
- else
- {
- g_warn_if_fail (data.error != NULL);
- g_propagate_error (error, data.error);
- }
-
- g_free (data.password);
- g_free (data.presentation_identity);
- g_free (data.identity);
- g_free (url);
-
- g_free (data.oauth_verifier);
- g_clear_pointer (&data.loop, g_main_loop_unref);
- g_free (data.access_token);
- g_free (data.access_token_secret);
- g_free (escaped_request_token);
-
- g_free (data.request_token);
- g_free (data.request_token_secret);
-
- g_strfreev (request_params);
- g_clear_object (&proxy);
- g_clear_object (&logger);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
- GError *error;
- GMainLoop *loop;
- gchar *account_object_path;
-} AddData;
-
-static void
-add_account_cb (GoaManager *manager,
- GAsyncResult *res,
- gpointer user_data)
-{
- AddData *data = user_data;
- goa_manager_call_add_account_finish (manager,
- &data->account_object_path,
- res,
- &data->error);
- g_main_loop_quit (data->loop);
-}
-
-static GoaObject *
-goa_oauth_provider_add_account (GoaProvider *_provider,
- GoaClient *client,
- GtkDialog *dialog,
- GtkBox *vbox,
- GError **error)
-{
- GoaOAuthProvider *provider = GOA_OAUTH_PROVIDER (_provider);
- GoaObject *ret = NULL;
- gchar *access_token = NULL;
- gchar *access_token_secret = NULL;
- gint access_token_expires_in;
- gchar *session_handle = NULL;
- gint session_handle_expires_in;
- gchar *identity = NULL;
- gchar *presentation_identity = NULL;
- gchar *password = NULL;
- AddData data;
- GVariantBuilder credentials;
- GVariantBuilder details;
-
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- g_return_val_if_fail (GOA_IS_CLIENT (client), NULL);
- g_return_val_if_fail (GTK_IS_DIALOG (dialog), NULL);
- g_return_val_if_fail (GTK_IS_BOX (vbox), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- memset (&data, '\0', sizeof (AddData));
- data.loop = g_main_loop_new (NULL, FALSE);
-
- if (!get_tokens_and_identity (provider,
- TRUE,
- NULL,
- dialog,
- vbox,
- &access_token,
- &access_token_secret,
- &access_token_expires_in,
- &session_handle,
- &session_handle_expires_in,
- &identity,
- &presentation_identity,
- &password,
- &data.error))
- goto out;
-
- /* OK, got the identity... see if there's already an account
- * of this type with the given identity
- */
- if (!goa_utils_check_duplicate (client,
- identity,
- presentation_identity,
- goa_provider_get_provider_type (GOA_PROVIDER (provider)),
- (GoaPeekInterfaceFunc) goa_object_peek_oauth_based,
- &data.error))
- goto out;
-
- g_variant_builder_init (&credentials, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&credentials, "{sv}", "access_token", g_variant_new_string (access_token));
- g_variant_builder_add (&credentials, "{sv}", "access_token_secret", g_variant_new_string (access_token_secret));
- if (access_token_expires_in > 0)
- g_variant_builder_add (&credentials, "{sv}", "access_token_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (access_token_expires_in)));
- if (session_handle != NULL)
- g_variant_builder_add (&credentials, "{sv}", "session_handle", g_variant_new_string (session_handle));
- if (session_handle_expires_in > 0)
- g_variant_builder_add (&credentials, "{sv}", "session_handle_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (session_handle_expires_in)));
- if (password != NULL)
- g_variant_builder_add (&credentials, "{sv}", "password", g_variant_new_string (password));
-
- g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
- goa_oauth_provider_add_account_key_values (provider, &details);
-
- /* we want the GoaClient to update before this method returns (so it
- * can create a proxy for the new object) so run the mainloop while
- * waiting for this to complete
- */
- goa_manager_call_add_account (goa_client_get_manager (client),
- goa_provider_get_provider_type (GOA_PROVIDER (provider)),
- identity,
- presentation_identity,
- g_variant_builder_end (&credentials),
- g_variant_builder_end (&details),
- NULL, /* GCancellable* */
- (GAsyncReadyCallback) add_account_cb,
- &data);
- g_main_loop_run (data.loop);
- if (data.error != NULL)
- goto out;
-
- ret = GOA_OBJECT (g_dbus_object_manager_get_object (goa_client_get_object_manager (client),
- data.account_object_path));
-
- out:
- /* We might have an object even when data.error is set.
- * eg., if we failed to store the credentials in the keyring.
- */
- if (data.error != NULL)
- g_propagate_error (error, data.error);
- else
- g_assert (ret != NULL);
-
- g_free (identity);
- g_free (presentation_identity);
- g_free (password);
- g_free (access_token);
- g_free (access_token_secret);
- g_free (session_handle);
- g_free (data.account_object_path);
- g_clear_pointer (&data.loop, g_main_loop_unref);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-goa_oauth_provider_refresh_account (GoaProvider *_provider,
- GoaClient *client,
- GoaObject *object,
- GtkWindow *parent,
- GError **error)
-{
- GoaOAuthProvider *provider = GOA_OAUTH_PROVIDER (_provider);
- GoaAccount *account;
- GtkWidget *dialog;
- gchar *access_token = NULL;
- gchar *access_token_secret = NULL;
- gchar *password = NULL;
- gint access_token_expires_in;
- gchar *session_handle = NULL;
- gint session_handle_expires_in;
- gchar *identity = NULL;
- const gchar *existing_identity;
- const gchar *existing_presentation_identity;
- GVariantBuilder builder;
- gboolean ret = FALSE;
-
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), FALSE);
- g_return_val_if_fail (GOA_IS_CLIENT (client), FALSE);
- g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
- g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- dialog = gtk_dialog_new_with_buttons (NULL,
- parent,
- GTK_DIALOG_MODAL
- | GTK_DIALOG_DESTROY_WITH_PARENT
- | GTK_DIALOG_USE_HEADER_BAR,
- NULL,
- NULL);
- gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
- gtk_widget_show_all (dialog);
-
- account = goa_object_peek_account (object);
-
- /* We abuse presentation identity here because for some providers
- * identity can be a machine readable ID, which can not be used to
- * log in via the provider's web interface.
- */
- existing_presentation_identity = goa_account_get_presentation_identity (account);
- if (!get_tokens_and_identity (provider,
- FALSE,
- existing_presentation_identity,
- GTK_DIALOG (dialog),
- GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
- &access_token,
- &access_token_secret,
- &access_token_expires_in,
- &session_handle,
- &session_handle_expires_in,
- &identity,
- NULL, /* out_presentation_identity */
- &password,
- error))
- goto out;
-
- /* Changes made to the web interface by the providers can break our
- * DOM parsing. So we should still query and check the identity
- * afterwards.
- */
- existing_identity = goa_account_get_identity (account);
- if (g_strcmp0 (identity, existing_identity) != 0)
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_FAILED,
- _("Was asked to log in as %s, but logged in as %s"),
- existing_identity,
- identity);
- goto out;
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&builder, "{sv}", "access_token", g_variant_new_string (access_token));
- g_variant_builder_add (&builder, "{sv}", "access_token_secret", g_variant_new_string (access_token_secret));
- if (access_token_expires_in > 0)
- g_variant_builder_add (&builder, "{sv}", "access_token_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (access_token_expires_in)));
- if (session_handle != NULL)
- g_variant_builder_add (&builder, "{sv}", "session_handle", g_variant_new_string (session_handle));
- if (session_handle_expires_in > 0)
- g_variant_builder_add (&builder, "{sv}", "session_handle_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (session_handle_expires_in)));
- if (password != NULL)
- g_variant_builder_add (&builder, "{sv}", "password", g_variant_new_string (password));
- /* TODO: run in worker thread */
- if (!goa_utils_store_credentials_for_object_sync (GOA_PROVIDER (provider),
- object,
- g_variant_builder_end (&builder),
- NULL, /* GCancellable */
- error))
- goto out;
-
- goa_account_call_ensure_credentials (goa_object_peek_account (object),
- NULL, /* GCancellable */
- NULL, NULL); /* callback, user_data */
-
- ret = TRUE;
-
- out:
- gtk_widget_destroy (dialog);
-
- g_free (identity);
- g_free (access_token);
- g_free (access_token_secret);
- g_free (password);
- g_free (session_handle);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-free_mutex (GMutex *mutex)
-{
- g_mutex_clear (mutex);
- g_slice_free (GMutex, mutex);
-}
-
-/**
- * goa_oauth_provider_get_access_token_sync:
- * @provider: A #GoaOAuthProvider.
- * @object: A #GoaObject.
- * @force_refresh: If set to %TRUE, forces a refresh of the access token, if possible.
- * @out_access_token_secret: (out): The secret for the return access token.
- * @out_access_token_expires_in: (out): Return location for how many seconds the returned token is valid for (0 if unknown) or %NULL.
- * @cancellable: (allow-none): A #GCancellable or %NULL.
- * @error: Return location for error or %NULL.
- *
- * Synchronously gets an access token for @object. The calling thread
- * is blocked while the operation is pending.
- *
- * The resulting token is typically read from the local cache so most
- * of the time only a local roundtrip to the storage for the token
- * cache (e.g. <command>gnome-keyring-daemon</command>) is
- * needed. However, the operation may involve refreshing the token
- * with the service provider so a full network round-trip may be
- * needed.
- *
- * Note that multiple calls are serialized to avoid multiple
- * outstanding requests to the service provider.
- *
- * This operation may fail if e.g. unable to refresh the credentials
- * or if network connectivity is not available. Note that even if a
- * token is returned, the returned token isn't guaranteed to work -
- * use goa_provider_ensure_credentials_sync() if you need
- * stronger guarantees.
- *
- * Returns: The access token or %NULL if error is set. The returned
- * string must be freed with g_free().
- */
-gchar *
-goa_oauth_provider_get_access_token_sync (GoaOAuthProvider *provider,
- GoaObject *object,
- gboolean force_refresh,
- gchar **out_access_token_secret,
- gint *out_access_token_expires_in,
- GCancellable *cancellable,
- GError **error)
-{
- GVariant *credentials = NULL;
- GVariantIter iter;
- const gchar *key;
- GVariant *value;
- gchar *access_token = NULL;
- gchar *access_token_secret = NULL;
- gchar *session_handle = NULL;
- gchar *access_token_for_refresh = NULL;
- gchar *access_token_secret_for_refresh = NULL;
- gchar *session_handle_for_refresh = NULL;
- gchar *password = NULL;
- gint access_token_expires_in = 0;
- gint session_handle_expires_in = 0;
- gboolean success = FALSE;
- GVariantBuilder builder;
- gchar *ret = NULL;
- GMutex *lock;
-
- g_return_val_if_fail (GOA_IS_OAUTH_PROVIDER (provider), NULL);
- g_return_val_if_fail (GOA_IS_OBJECT (object), NULL);
- g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- /* provider_lock is too coarse, use a per-object lock instead */
- G_LOCK (provider_lock);
- lock = g_object_get_data (G_OBJECT (object), "-goa-oauth-provider-get-access-token-lock");
- if (lock == NULL)
- {
- lock = g_slice_new0 (GMutex);
- g_mutex_init (lock);
- g_object_set_data_full (G_OBJECT (object),
- "-goa-oauth-provider-get-access-token-lock",
- lock,
- (GDestroyNotify) free_mutex);
- }
- G_UNLOCK (provider_lock);
-
- g_mutex_lock (lock);
-
- /* First, get the credentials from the keyring */
- credentials = goa_utils_lookup_credentials_sync (GOA_PROVIDER (provider),
- object,
- cancellable,
- error);
- if (credentials == NULL)
- {
- if (error != NULL)
- {
- (*error)->domain = GOA_ERROR;
- (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
- }
- goto out;
- }
-
- g_variant_iter_init (&iter, credentials);
- while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
- {
- if (g_strcmp0 (key, "access_token") == 0)
- access_token = g_variant_dup_string (value, NULL);
- else if (g_strcmp0 (key, "access_token_secret") == 0)
- access_token_secret = g_variant_dup_string (value, NULL);
- else if (g_strcmp0 (key, "access_token_expires_at") == 0)
- access_token_expires_in = goa_utils_convert_abs_usec_to_duration_sec (g_variant_get_int64 (value));
- else if (g_strcmp0 (key, "session_handle") == 0)
- session_handle = g_variant_dup_string (value, NULL);
- else if (g_strcmp0 (key, "session_handle_expires_at") == 0)
- session_handle_expires_in = goa_utils_convert_abs_usec_to_duration_sec (g_variant_get_int64 (value));
- else if (g_strcmp0 (key, "password") == 0)
- password = g_variant_dup_string (value, NULL);
- g_variant_unref (value);
- }
-
- if (access_token == NULL || access_token_secret == NULL)
- {
- g_set_error (error,
- GOA_ERROR,
- GOA_ERROR_NOT_AUTHORIZED,
- _("Credentials do not contain access_token or access_token_secret"));
- goto out;
- }
-
- /* if we can't refresh the token, just return it no matter what */
- if (session_handle == NULL)
- {
- g_debug ("Returning locally cached credentials that cannot be refreshed");
- success = TRUE;
- goto out;
- }
-
- /* If access_token is still "fresh enough" (e.g. more than ten
- * minutes of life left in it), just return it unless we've been
- * asked to forcibly refresh it
- */
- if (!force_refresh && access_token_expires_in > 10*60)
- {
- g_debug ("Returning locally cached credentials (expires in %d seconds)", access_token_expires_in);
- success = TRUE;
- goto out;
- }
-
- g_debug ("Refreshing locally cached credentials (expires in %d seconds, force_refresh=%d)", access_token_expires_in, force_refresh);
-
- /* Otherwise, refresh it */
- access_token_for_refresh = access_token; access_token = NULL;
- access_token_secret_for_refresh = access_token_secret; access_token_secret = NULL;
- session_handle_for_refresh = session_handle; session_handle = NULL;
- access_token = get_tokens_sync (provider,
- access_token_for_refresh,
- access_token_secret_for_refresh,
- session_handle_for_refresh,
- NULL, /* verifier */
- &access_token_secret,
- &access_token_expires_in,
- &session_handle,
- &session_handle_expires_in,
- cancellable,
- error);
- if (access_token == NULL)
- {
- if (error != NULL)
- {
- g_prefix_error (error, _("Failed to refresh access token (%s, %d): "),
- g_quark_to_string ((*error)->domain), (*error)->code);
- (*error)->code = is_authorization_error (*error) ? GOA_ERROR_NOT_AUTHORIZED : GOA_ERROR_FAILED;
- (*error)->domain = GOA_ERROR;
- }
- goto out;
- }
-
- /* Good. Now update the keyring with the refreshed credentials */
- g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add (&builder, "{sv}", "access_token", g_variant_new_string (access_token));
- g_variant_builder_add (&builder, "{sv}", "access_token_secret", g_variant_new_string (access_token_secret));
- if (access_token_expires_in > 0)
- g_variant_builder_add (&builder, "{sv}", "access_token_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (access_token_expires_in)));
- if (session_handle != NULL)
- g_variant_builder_add (&builder, "{sv}", "session_handle", g_variant_new_string (session_handle));
- if (session_handle_expires_in > 0)
- g_variant_builder_add (&builder, "{sv}", "session_handle_expires_at",
- g_variant_new_int64 (goa_utils_convert_duration_sec_to_abs_usec (session_handle_expires_in)));
- if (password != NULL)
- g_variant_builder_add (&builder, "{sv}", "password", g_variant_new_string (password));
-
- /* TODO: run in worker thread */
- if (!goa_utils_store_credentials_for_object_sync (GOA_PROVIDER (provider),
- object,
- g_variant_builder_end (&builder),
- cancellable,
- error))
- {
- if (error != NULL)
- {
- (*error)->domain = GOA_ERROR;
- (*error)->code = GOA_ERROR_NOT_AUTHORIZED;
- }
- goto out;
- }
-
- success = TRUE;
-
- out:
- if (success)
- {
- ret = access_token; access_token = NULL;
- g_assert (ret != NULL);
- if (out_access_token_secret != NULL)
- {
- *out_access_token_secret = access_token_secret; access_token_secret = NULL;
- }
- if (out_access_token_expires_in != NULL)
- *out_access_token_expires_in = access_token_expires_in;
- }
- g_free (access_token);
- g_free (access_token_secret);
- g_free (session_handle);
- g_free (access_token_for_refresh);
- g_free (access_token_secret_for_refresh);
- g_free (session_handle_for_refresh);
- g_free (password);
- g_clear_pointer (&credentials, g_variant_unref);
-
- g_mutex_unlock (lock);
-
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean on_handle_get_access_token (GoaOAuthBased *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data);
-
-static gboolean
-goa_oauth_provider_build_object (GoaProvider *provider,
- GoaObjectSkeleton *object,
- GKeyFile *key_file,
- const gchar *group,
- GDBusConnection *connection,
- gboolean just_added,
- GError **error)
-{
- GoaOAuthBased *oauth_based;
- gchar *identity;
-
- identity = NULL;
-
- oauth_based = goa_object_get_oauth_based (GOA_OBJECT (object));
- if (oauth_based != NULL)
- goto out;
-
- oauth_based = goa_oauth_based_skeleton_new ();
- goa_oauth_based_set_consumer_key (oauth_based,
- goa_oauth_provider_get_consumer_key (GOA_OAUTH_PROVIDER (provider)));
- goa_oauth_based_set_consumer_secret (oauth_based,
- goa_oauth_provider_get_consumer_secret (GOA_OAUTH_PROVIDER (provider)));
- /* Ensure D-Bus method invocations run in their own thread */
- g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (oauth_based),
- G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
- goa_object_skeleton_set_oauth_based (object, oauth_based);
- g_signal_connect (oauth_based,
- "handle-get-access-token",
- G_CALLBACK (on_handle_get_access_token),
- NULL);
-
- out:
- g_object_unref (oauth_based);
- g_free (identity);
- return TRUE;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-goa_oauth_provider_ensure_credentials_sync (GoaProvider *_provider,
- GoaObject *object,
- gint *out_expires_in,
- GCancellable *cancellable,
- GError **error)
-{
- GoaOAuthProvider *provider = GOA_OAUTH_PROVIDER (_provider);
- gboolean ret = FALSE;
- gchar *access_token = NULL;
- gchar *access_token_secret = NULL;
- gint access_token_expires_in;
- gchar *identity = NULL;
- gboolean force_refresh = FALSE;
-
- again:
- access_token = goa_oauth_provider_get_access_token_sync (provider,
- object,
- force_refresh,
- &access_token_secret,
- &access_token_expires_in,
- cancellable,
- error);
- if (access_token == NULL)
- goto out;
-
- identity = goa_oauth_provider_get_identity_sync (provider,
- access_token,
- access_token_secret,
- NULL, /* out_presentation_identity */
- cancellable,
- error);
- if (identity == NULL)
- {
- /* OK, try again, with forcing the locally cached credentials to be refreshed */
- if (!force_refresh)
- {
- force_refresh = TRUE;
- g_free (access_token); access_token = NULL;
- g_free (access_token_secret); access_token_secret = NULL;
- g_clear_error (error);
- goto again;
- }
- else
- {
- goto out;
- }
- }
-
- /* TODO: maybe check with the identity we have */
- ret = TRUE;
- if (out_expires_in != NULL)
- *out_expires_in = access_token_expires_in;
-
- out:
- g_free (identity);
- g_free (access_token);
- g_free (access_token_secret);
- return ret;
-}
-
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-goa_oauth_provider_init (GoaOAuthProvider *client)
-{
-}
-
-static void
-goa_oauth_provider_class_init (GoaOAuthProviderClass *klass)
-{
- GoaProviderClass *provider_class;
-
- provider_class = GOA_PROVIDER_CLASS (klass);
- provider_class->add_account = goa_oauth_provider_add_account;
- provider_class->refresh_account = goa_oauth_provider_refresh_account;
- provider_class->build_object = goa_oauth_provider_build_object;
- provider_class->ensure_credentials_sync = goa_oauth_provider_ensure_credentials_sync;
-
- klass->build_authorization_uri = goa_oauth_provider_build_authorization_uri_default;
- klass->get_use_mobile_browser = goa_oauth_provider_get_use_mobile_browser_default;
- klass->is_deny_node = goa_oauth_provider_is_deny_node_default;
- klass->is_password_node = goa_oauth_provider_is_password_node_default;
- klass->get_request_uri_params = goa_oauth_provider_get_request_uri_params_default;
- klass->add_account_key_values = goa_oauth_provider_add_account_key_values_default;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/* runs in a thread dedicated to handling @invocation */
-static gboolean
-on_handle_get_access_token (GoaOAuthBased *interface,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- GoaObject *object;
- GoaAccount *account;
- GoaProvider *provider;
- GError *error;
- const gchar *id;
- const gchar *method_name;
- const gchar *provider_type;
- gchar *access_token = NULL;
- gchar *access_token_secret = NULL;
- gint access_token_expires_in;
-
- /* TODO: maybe log what app is requesting access */
-
- object = GOA_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (interface)));
- account = goa_object_peek_account (object);
-
- id = goa_account_get_id (account);
- provider_type = goa_account_get_provider_type (account);
- method_name = g_dbus_method_invocation_get_method_name (invocation);
- g_debug ("Handling %s for account (%s, %s)", method_name, provider_type, id);
-
- provider = goa_provider_get_for_provider_type (provider_type);
-
- error = NULL;
- access_token = goa_oauth_provider_get_access_token_sync (GOA_OAUTH_PROVIDER (provider),
- object,
- FALSE, /* force_refresh */
- &access_token_secret,
- &access_token_expires_in,
- NULL, /* GCancellable* */
- &error);
- if (access_token == NULL)
- {
- g_dbus_method_invocation_take_error (invocation, error);
- }
- else
- {
- goa_oauth_based_complete_get_access_token (interface,
- invocation,
- access_token,
- access_token_secret,
- access_token_expires_in);
- }
- g_free (access_token);
- g_free (access_token_secret);
- g_object_unref (provider);
- return TRUE; /* invocation was handled */
-}
diff --git a/src/goabackend/goaoauthprovider.h b/src/goabackend/goaoauthprovider.h
deleted file mode 100644
index e42f7a5..0000000
--- a/src/goabackend/goaoauthprovider.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * Copyright © 2011 – 2017 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#if !defined (__GOA_BACKEND_INSIDE_GOA_BACKEND_H__) && !defined (GOA_BACKEND_COMPILATION)
-#error "Only <goabackend/goabackend.h> can be included directly."
-#endif
-
-#ifndef __GOA_OAUTH_PROVIDER_H__
-#define __GOA_OAUTH_PROVIDER_H__
-
-#include <goabackend/goaprovider.h>
-#include <goabackend/goaprovider-priv.h>
-#include <rest/rest.h>
-#include <webkitdom/webkitdom.h>
-
-G_BEGIN_DECLS
-
-#define GOA_TYPE_OAUTH_PROVIDER (goa_oauth_provider_get_type ())
-G_DECLARE_DERIVABLE_TYPE (GoaOAuthProvider, goa_oauth_provider, GOA, OAUTH_PROVIDER, GoaProvider);
-
-/**
- * GoaOAuthProvider:
- *
- * The #GoaOAuthProvider structure contains only private data and should
- * only be accessed using the provided API.
- */
-
-/**
- * GoaOAuthProviderClass:
- * @parent_class: The parent class.
- * @get_consumer_key: Virtual function for goa_oauth_provider_get_consumer_key().
- * @get_consumer_secret: Virtual function for goa_oauth_provider_get_consumer_secret().
- * @get_request_uri: Virtual function for goa_oauth_provider_get_request_uri().
- * @get_authorization_uri: Virtual function for goa_oauth_provider_get_authorization_uri().
- * @get_token_uri: Virtual function for goa_oauth_provider_get_token_uri().
- * @get_callback_uri: Virtual function for goa_oauth_provider_get_callback_uri().
- * @get_identity_sync: Virtual function for goa_oauth_provider_get_identity_sync().
- * @parse_request_token_error: Virtual function for goa_oauth_provider_parse_request_token_error().
- * @build_authorization_uri: Virtual function for goa_oauth_provider_build_authorization_uri().
- * @get_use_mobile_browser: Virtual function for goa_oauth_provider_get_use_mobile_browser().
- * @get_request_uri_params: Virtual function for goa_oauth_provider_get_request_uri_params().
- * @add_account_key_values: Virtual function for goa_oauth_provider_add_account_key_values().
- * @is_deny_node: Virtual function for goa_oauth_provider_is_deny_node().
- * @is_identity_node: Virtual function for goa_oauth_provider_is_identity_node().
- * @is_password_node: Virtual function for goa_oauth_provider_is_password_node().
- *
- * Class structure for #GoaOAuthProvider.
- */
-struct _GoaOAuthProviderClass
-{
- GoaProviderClass parent_class;
-
- /* pure virtual */
- const gchar *(*get_consumer_key) (GoaOAuthProvider *provider);
- const gchar *(*get_consumer_secret) (GoaOAuthProvider *provider);
- const gchar *(*get_request_uri) (GoaOAuthProvider *provider);
- const gchar *(*get_authorization_uri) (GoaOAuthProvider *provider);
- const gchar *(*get_token_uri) (GoaOAuthProvider *provider);
- const gchar *(*get_callback_uri) (GoaOAuthProvider *provider);
-
- gchar *(*get_identity_sync) (GoaOAuthProvider *provider,
- const gchar *access_token,
- const gchar *access_token_secret,
- gchar **out_presentation_identity,
- GCancellable *cancellable,
- GError **error);
-
- gchar *(*parse_request_token_error) (GoaOAuthProvider *provider,
- RestProxyCall *call);
-
- /* virtual but with default implementation */
- gchar *(*build_authorization_uri) (GoaOAuthProvider *provider,
- const gchar *authorization_uri,
- const gchar *escaped_oauth_token);
- gboolean (*get_use_mobile_browser) (GoaOAuthProvider *provider);
- gchar **(*get_request_uri_params) (GoaOAuthProvider *provider);
- void (*add_account_key_values) (GoaOAuthProvider *provider,
- GVariantBuilder *builder);
-
- /* pure virtual */
- gboolean (*is_identity_node) (GoaOAuthProvider *provider,
- WebKitDOMHTMLInputElement *element);
-
- /* virtual but with default implementation */
- gboolean (*is_deny_node) (GoaOAuthProvider *provider,
- WebKitDOMNode *node);
- gboolean (*is_password_node) (GoaOAuthProvider *provider,
- WebKitDOMHTMLInputElement *element);
-};
-
-const gchar *goa_oauth_provider_get_consumer_key (GoaOAuthProvider *provider);
-const gchar *goa_oauth_provider_get_consumer_secret (GoaOAuthProvider *provider);
-const gchar *goa_oauth_provider_get_request_uri (GoaOAuthProvider *provider);
-gchar **goa_oauth_provider_get_request_uri_params (GoaOAuthProvider *provider);
-const gchar *goa_oauth_provider_get_authorization_uri (GoaOAuthProvider *provider);
-const gchar *goa_oauth_provider_get_token_uri (GoaOAuthProvider *provider);
-const gchar *goa_oauth_provider_get_callback_uri (GoaOAuthProvider *provider);
-gchar *goa_oauth_provider_get_identity_sync (GoaOAuthProvider *provider,
- const gchar *access_token,
- const gchar *access_token_secret,
- gchar **out_presentation_identity,
- GCancellable *cancellable,
- GError **error);
-gboolean goa_oauth_provider_is_deny_node (GoaOAuthProvider *provider,
- WebKitDOMNode *node);
-gboolean goa_oauth_provider_is_identity_node (GoaOAuthProvider *provider,
- WebKitDOMHTMLInputElement *element);
-gboolean goa_oauth_provider_is_password_node (GoaOAuthProvider *provider,
- WebKitDOMHTMLInputElement *element);
-gchar *goa_oauth_provider_parse_request_token_error (GoaOAuthProvider *provider,
- RestProxyCall *call);
-gchar *goa_oauth_provider_get_access_token_sync (GoaOAuthProvider *provider,
- GoaObject *object,
- gboolean force_refresh,
- gchar **out_access_token_secret,
- gint *out_access_token_expires_in,
- GCancellable *cancellable,
- GError **error);
-gchar *goa_oauth_provider_build_authorization_uri (GoaOAuthProvider *provider,
- const gchar *authorization_uri,
- const gchar *escaped_oauth_token);
-gboolean goa_oauth_provider_get_use_mobile_browser (GoaOAuthProvider *provider);
-void goa_oauth_provider_add_account_key_values (GoaOAuthProvider *provider,
- GVariantBuilder *builder);
-
-G_END_DECLS
-
-#endif /* __GOA_OAUTH_PROVIDER_H__ */
diff --git a/src/goabackend/goawebextension.c b/src/goabackend/goawebextension.c
index a17edf2..a5e6620 100644
--- a/src/goabackend/goawebextension.c
+++ b/src/goabackend/goawebextension.c
@@ -21,7 +21,6 @@
#include <webkitdom/webkitdom.h>
-#include "goaoauthprovider.h"
#include "goaoauth2provider.h"
#include "goaoauth2provider-web-extension.h"
#include "goaprovider.h"
@@ -86,10 +85,8 @@ web_extension_document_loaded_cb (WebKitWebPage *web_page, gpointer user_data)
{
WebKitDOMNode *element = webkit_dom_html_collection_item (elements, i);
- if ((GOA_IS_OAUTH_PROVIDER (self->provider)
- && goa_oauth_provider_is_deny_node (GOA_OAUTH_PROVIDER (self->provider), element))
- || (GOA_IS_OAUTH2_PROVIDER (self->provider)
- && goa_oauth2_provider_is_deny_node (GOA_OAUTH2_PROVIDER (self->provider), element)))
+ if (GOA_IS_OAUTH2_PROVIDER (self->provider)
+ && goa_oauth2_provider_is_deny_node (GOA_OAUTH2_PROVIDER (self->provider), element))
{
webkit_dom_event_target_add_event_listener (WEBKIT_DOM_EVENT_TARGET (element),
"click",
@@ -100,24 +97,18 @@ web_extension_document_loaded_cb (WebKitWebPage *web_page, gpointer user_data)
else if (self->existing_identity != NULL
&& self->existing_identity[0] != '\0'
&& WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element)
- && ((GOA_IS_OAUTH_PROVIDER (self->provider)
- && goa_oauth_provider_is_identity_node (GOA_OAUTH_PROVIDER (self->provider),
- WEBKIT_DOM_HTML_INPUT_ELEMENT (element)))
- || (GOA_IS_OAUTH2_PROVIDER (self->provider)
- && goa_oauth2_provider_is_identity_node (GOA_OAUTH2_PROVIDER (self->provider),
- WEBKIT_DOM_HTML_INPUT_ELEMENT (element)))))
+ && ((GOA_IS_OAUTH2_PROVIDER (self->provider)
+ && goa_oauth2_provider_is_identity_node (GOA_OAUTH2_PROVIDER (self->provider),
+ WEBKIT_DOM_HTML_INPUT_ELEMENT (element)))))
{
webkit_dom_html_input_element_set_value (WEBKIT_DOM_HTML_INPUT_ELEMENT (element),
self->existing_identity);
webkit_dom_html_input_element_set_read_only (WEBKIT_DOM_HTML_INPUT_ELEMENT (element), TRUE);
}
else if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element)
- && ((GOA_IS_OAUTH_PROVIDER (self->provider)
- && goa_oauth_provider_is_password_node (GOA_OAUTH_PROVIDER (self->provider),
- WEBKIT_DOM_HTML_INPUT_ELEMENT (element)))
- || (GOA_IS_OAUTH2_PROVIDER (self->provider)
- && goa_oauth2_provider_is_password_node (GOA_OAUTH2_PROVIDER (self->provider),
- WEBKIT_DOM_HTML_INPUT_ELEMENT (element)))))
+ && (GOA_IS_OAUTH2_PROVIDER (self->provider)
+ && goa_oauth2_provider_is_password_node (GOA_OAUTH2_PROVIDER (self->provider),
+ WEBKIT_DOM_HTML_INPUT_ELEMENT (element))))
{
WebKitDOMHTMLFormElement *form;
diff --git a/src/goabackend/meson.build b/src/goabackend/meson.build
index 3706d5b..f5382b3 100644
--- a/src/goabackend/meson.build
+++ b/src/goabackend/meson.build
@@ -3,7 +3,6 @@ libgoa_backend_headers_built = []
libgoa_backend_sources = files(
'goaoauth2provider.c',
- 'goaoauthprovider.c',
'goabackendinit.c',
'goadlnaservermanager.c',
'goaewsclient.c',