[libgdata] core: Add GDataOAuth2Authorizer:refresh-token API



commit b80f8883dd7c15a62ae9756f34c8f3155d557a32
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Sun Jun 14 15:51:48 2015 +0100

    core: Add GDataOAuth2Authorizer:refresh-token API
    
    Add new API to allow the refresh token from an OAuth 2 authorizer to be
    stored by an application and restored into a new GDataOAuth2Authorizer
    instance (a cold start). This adds the following new API:
     • GDataOAuth2Authorizer:refresh-token
     • gdata_oauth2_authorizer_dup_refresh_token()
     • gdata_oauth2_authorizer_set_refresh_token()
    
    It does not add any new tests.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=750746

 docs/reference/gdata-sections.txt |    2 +
 gdata/gdata-oauth2-authorizer.c   |  119 +++++++++++++++++++++++++++++++++++-
 gdata/gdata-oauth2-authorizer.h   |    5 +-
 gdata/gdata.symbols               |    2 +
 4 files changed, 123 insertions(+), 5 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index d841848..fba50b3 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -2776,6 +2776,8 @@ gdata_oauth2_authorizer_request_authorization_finish
 gdata_oauth2_authorizer_get_client_id
 gdata_oauth2_authorizer_get_redirect_uri
 gdata_oauth2_authorizer_get_client_secret
+gdata_oauth2_authorizer_dup_refresh_token
+gdata_oauth2_authorizer_set_refresh_token
 gdata_oauth2_authorizer_get_locale
 gdata_oauth2_authorizer_set_locale
 gdata_oauth2_authorizer_get_timeout
diff --git a/gdata/gdata-oauth2-authorizer.c b/gdata/gdata-oauth2-authorizer.c
index 994c115..4062817 100644
--- a/gdata/gdata-oauth2-authorizer.c
+++ b/gdata/gdata-oauth2-authorizer.c
@@ -1,7 +1,7 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
  * GData Client
- * Copyright (C) Philip Withnall 2011, 2014 <philip tecnocode co uk>
+ * Copyright (C) Philip Withnall 2011, 2014, 2015 <philip tecnocode co uk>
  *
  * GData Client is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,6 +49,13 @@
  * token can be used in future (with gdata_authorizer_refresh_authorization())
  * to refresh authorization after the access token expires.
  *
+ * The refresh token may also be accessed as
+ * #GDataOAuth2Authorizer:refresh-token and saved by the application. It may
+ * later be set on a new instance of #GDataOAuth2Authorizer, and
+ * gdata_authorizer_refresh_authorization_async() called to establish a new
+ * access token without requiring the user to re-authenticate unless they have
+ * explicitly revoked the refresh token.
+ *
  * For an overview of the standard OAuth 2.0 flow, see
  * <ulink type="http" url="http://tools.ietf.org/html/rfc6749#section-1.2";>RFC 6749</ulink>.
  *
@@ -183,7 +190,9 @@ struct _GDataOAuth2AuthorizerPrivate {
        /* Mutex for access_token, refresh_token and authentication_domains. */
        GMutex mutex;
 
-       /* These are both non-NULL when authorised, and both NULL otherwise. */
+       /* These are both non-NULL when authorised. refresh_token may be
+        * non-NULL if access_token is NULL and refresh_authorization() has not
+        * yet been called on this authorizer. They may be both NULL. */
        gchar *access_token;  /* owned */
        gchar *refresh_token;  /* owned */
 
@@ -199,6 +208,7 @@ enum {
        PROP_LOCALE,
        PROP_TIMEOUT,
        PROP_PROXY_RESOLVER,
+       PROP_REFRESH_TOKEN,
 };
 
 G_DEFINE_TYPE_WITH_CODE (GDataOAuth2Authorizer, gdata_oauth2_authorizer,
@@ -354,6 +364,25 @@ gdata_oauth2_authorizer_class_init (GDataOAuth2AuthorizerClass *klass)
                                                              "A GProxyResolver used to determine a proxy 
URI.",
                                                              G_TYPE_PROXY_RESOLVER,
                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+       /**
+        * GDataOAuth2Authorizer:refresh-token:
+        *
+        * The server provided refresh token, which can be stored and passed in
+        * to new #GDataOAuth2Authorizer instances before calling
+        * gdata_authorizer_refresh_authorization_async() to create a new
+        * short-lived access token.
+        *
+        * The refresh token is opaque data and must not be parsed.
+        *
+        * Since: UNRELEASED
+        */
+       g_object_class_install_property (gobject_class, PROP_REFRESH_TOKEN,
+                                        g_param_spec_string ("refresh-token",
+                                                             "Refresh Token",
+                                                             "The server provided refresh token.",
+                                                             NULL,
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -464,6 +493,11 @@ get_property (GObject *object, guint property_id, GValue *value,
                g_value_set_object (value,
                                    gdata_oauth2_authorizer_get_proxy_resolver (self));
                break;
+       case PROP_REFRESH_TOKEN:
+               g_mutex_lock (&priv->mutex);
+               g_value_set_string (value, priv->refresh_token);
+               g_mutex_unlock (&priv->mutex);
+               break;
        default:
                /* We don't have any other property... */
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -505,6 +539,10 @@ set_property (GObject *object, guint property_id, const GValue *value, GParamSpe
                gdata_oauth2_authorizer_set_proxy_resolver (self,
                                                            g_value_get_object (value));
                break;
+       case PROP_REFRESH_TOKEN:
+               gdata_oauth2_authorizer_set_refresh_token (self,
+                                                          g_value_get_string (value));
+               break;
        default:
                /* We don't have any other property... */
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -524,8 +562,8 @@ process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain,
        g_mutex_lock (&priv->mutex);
 
        /* Sanity check */
-       g_assert ((priv->access_token == NULL) ==
-                 (priv->refresh_token == NULL));
+       g_assert ((priv->access_token == NULL) ||
+                 (priv->refresh_token != NULL));
 
        if (priv->access_token != NULL &&
            g_hash_table_lookup (priv->authentication_domains,
@@ -1343,6 +1381,79 @@ gdata_oauth2_authorizer_get_client_secret (GDataOAuth2Authorizer *self)
 }
 
 /**
+ * gdata_oauth2_authorizer_dup_refresh_token:
+ * @self: a #GDataOAuth2Authorizer
+ *
+ * Returns the authorizer's refresh token, #GDataOAuth2Authorizer:refresh-token,
+ * as set by client code previously on the #GDataOAuth2Authorizer, or as
+ * returned by the most recent authentication operation.
+ *
+ * Return value: (transfer full): the authorizer's refresh token
+ *
+ * Since: UNRELEASED
+ */
+gchar *
+gdata_oauth2_authorizer_dup_refresh_token (GDataOAuth2Authorizer *self)
+{
+       GDataOAuth2AuthorizerPrivate *priv;
+       gchar *refresh_token;  /* owned */
+
+       g_return_val_if_fail (GDATA_IS_OAUTH2_AUTHORIZER (self), NULL);
+
+       priv = self->priv;
+
+       g_mutex_lock (&priv->mutex);
+       refresh_token = g_strdup (priv->refresh_token);
+       g_mutex_unlock (&priv->mutex);
+
+       return refresh_token;
+}
+
+/**
+ * gdata_oauth2_authorizer_set_refresh_token:
+ * @self: a #GDataOAuth2Authorizer
+ * @refresh_token: (nullable): the new refresh token, or %NULL to clear
+ *   authorization
+ *
+ * Sets the authorizer's refresh token, #GDataOAuth2Authorizer:refresh-token.
+ * This is used to periodically refresh the access token. Set it to %NULL to
+ * clear the current authentication from the authorizer.
+ *
+ * Since: UNRELEASED
+ */
+void
+gdata_oauth2_authorizer_set_refresh_token (GDataOAuth2Authorizer *self,
+                                           const gchar *refresh_token)
+{
+       GDataOAuth2AuthorizerPrivate *priv;
+
+       g_return_if_fail (GDATA_IS_OAUTH2_AUTHORIZER (self));
+
+       priv = self->priv;
+
+       g_mutex_lock (&priv->mutex);
+
+       if (g_strcmp0 (priv->refresh_token, refresh_token) == 0) {
+               g_mutex_unlock (&priv->mutex);
+               return;
+       }
+
+       /* Clear the access token; if the refresh token has changed, it can
+        * no longer be valid, and we must avoid the situation:
+        *    (access_token != NULL) && (refresh_token == NULL) */
+       g_free (priv->access_token);
+       priv->access_token = NULL;
+
+       /* Update the refresh token. */
+       g_free (priv->refresh_token);
+       priv->refresh_token = g_strdup (refresh_token);
+
+       g_mutex_unlock (&priv->mutex);
+
+       g_object_notify (G_OBJECT (self), "refresh-token");
+}
+
+/**
  * gdata_oauth2_authorizer_get_locale:
  * @self: a #GDataOAuth2Authorizer
  *
diff --git a/gdata/gdata-oauth2-authorizer.h b/gdata/gdata-oauth2-authorizer.h
index 8a1c078..ffba9af 100644
--- a/gdata/gdata-oauth2-authorizer.h
+++ b/gdata/gdata-oauth2-authorizer.h
@@ -1,7 +1,7 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
  * GData Client
- * Copyright (C) Philip Withnall 2011, 2014 <philip tecnocode co uk>
+ * Copyright (C) Philip Withnall 2011, 2014, 2015 <philip tecnocode co uk>
  *
  * GData Client is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -119,6 +119,9 @@ const gchar *gdata_oauth2_authorizer_get_client_id (GDataOAuth2Authorizer *self)
 const gchar *gdata_oauth2_authorizer_get_redirect_uri (GDataOAuth2Authorizer *self) G_GNUC_PURE;
 const gchar *gdata_oauth2_authorizer_get_client_secret (GDataOAuth2Authorizer *self) G_GNUC_PURE;
 
+gchar *gdata_oauth2_authorizer_dup_refresh_token (GDataOAuth2Authorizer *self) G_GNUC_PURE;
+void gdata_oauth2_authorizer_set_refresh_token (GDataOAuth2Authorizer *self, const gchar *refresh_token);
+
 const gchar *gdata_oauth2_authorizer_get_locale (GDataOAuth2Authorizer *self) G_GNUC_PURE;
 void gdata_oauth2_authorizer_set_locale (GDataOAuth2Authorizer *self, const gchar *locale);
 
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index ae4cfb7..e3773ab 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -1110,6 +1110,8 @@ gdata_oauth2_authorizer_request_authorization_finish
 gdata_oauth2_authorizer_get_client_id
 gdata_oauth2_authorizer_get_redirect_uri
 gdata_oauth2_authorizer_get_client_secret
+gdata_oauth2_authorizer_dup_refresh_token
+gdata_oauth2_authorizer_set_refresh_token
 gdata_oauth2_authorizer_get_locale
 gdata_oauth2_authorizer_set_locale
 gdata_oauth2_authorizer_get_timeout


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]