diff options
author | Jonathon Jongsma <jonathon@quotidian.org> | 2010-05-07 17:15:20 -0500 |
---|---|---|
committer | Rob Bradford <rob@linux.intel.com> | 2010-06-17 17:35:02 +0100 |
commit | 1305915bb6a6af6ef661d6076f3f11c25bf5b5cc (patch) | |
tree | db008e9a6f5c8a893c0fdcac15b2de6949234942 | |
parent | 09b651e4da616a83476a6b9f853940fa91938ad1 (diff) |
Add a oauth2 proxylibrest-0.6.4
This new class provides a proxy class for oauth2-based web services, such as the
new facebook graph API. The basic idea is as follows:
- Construct a OAuth2Proxy object
- Build a login url with _build_login_url(_full)()
- Display said url in a browser widget (e.g. webkit) and listen for redirects to
the specified 'redirect_uri'
- Extract the access token from the uri that you are redirected to
- Set the access token for the proxy with _set_access_token()
http://bugs.meego.com/show_bug.cgi?id=2265
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | rest/Makefile.am | 5 | ||||
-rw-r--r-- | rest/oauth2-proxy-call.c | 69 | ||||
-rw-r--r-- | rest/oauth2-proxy-call.h | 68 | ||||
-rw-r--r-- | rest/oauth2-proxy-private.h | 34 | ||||
-rw-r--r-- | rest/oauth2-proxy.c | 399 | ||||
-rw-r--r-- | rest/oauth2-proxy.h | 95 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/oauth2.c | 56 |
9 files changed, 729 insertions, 4 deletions
@@ -52,6 +52,7 @@ rest-extras/RestExtras-0.6.typelib rest-extras/test-runner tests/oauth tests/oauth-async +tests/oauth2 tests/proxy tests/flickr tests/threaded diff --git a/rest/Makefile.am b/rest/Makefile.am index c7bfc27..a5bbf0e 100644 --- a/rest/Makefile.am +++ b/rest/Makefile.am @@ -12,12 +12,17 @@ lib_sources = \ oauth-proxy.c \ oauth-proxy-call.c \ oauth-proxy-private.h \ + oauth2-proxy.c \ + oauth2-proxy-call.c \ + oauth2-proxy-private.h \ sha1.c \ sha1.h lib_headers = rest-proxy.h \ rest-proxy-call.h \ oauth-proxy.h \ oauth-proxy-call.h \ + oauth2-proxy.h \ + oauth2-proxy-call.h \ rest-xml-parser.h lib_LTLIBRARIES = librest-@API_VERSION@.la diff --git a/rest/oauth2-proxy-call.c b/rest/oauth2-proxy-call.c new file mode 100644 index 0000000..f0d441c --- /dev/null +++ b/rest/oauth2-proxy-call.c @@ -0,0 +1,69 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <string.h> +#include <libsoup/soup.h> +#include <rest/rest-proxy-call.h> +#include "oauth2-proxy-call.h" +#include "oauth2-proxy-private.h" +#include "rest-proxy-call-private.h" +#include "sha1.h" + +G_DEFINE_TYPE (OAuth2ProxyCall, oauth2_proxy_call, REST_TYPE_PROXY_CALL) + +static gboolean +_prepare (RestProxyCall *call, GError **error) +{ + OAuth2Proxy *proxy = NULL; + gboolean result = TRUE; + + g_object_get (call, "proxy", &proxy, NULL); + + if (!proxy->priv->access_token) { + g_set_error (error, + REST_PROXY_CALL_ERROR, + REST_PROXY_CALL_FAILED, + "Missing access token, web service not properly authenticated"); + result = FALSE; + } else { + rest_proxy_call_add_param (call, "access_token", proxy->priv->access_token); + } + + g_object_unref (proxy); + + return result; +} + +static void +oauth2_proxy_call_class_init (OAuth2ProxyCallClass *klass) +{ + RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass); + + call_class->prepare = _prepare; +} + +static void +oauth2_proxy_call_init (OAuth2ProxyCall *self) +{ +} + diff --git a/rest/oauth2-proxy-call.h b/rest/oauth2-proxy-call.h new file mode 100644 index 0000000..ebe78a1 --- /dev/null +++ b/rest/oauth2-proxy-call.h @@ -0,0 +1,68 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _OAUTH2_PROXY_CALL +#define _OAUTH2_PROXY_CALL + +#include <rest/rest-proxy-call.h> + +G_BEGIN_DECLS + +#define OAUTH2_TYPE_PROXY_CALL oauth2_proxy_call_get_type() + +#define OAUTH2_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), OAUTH2_TYPE_PROXY_CALL, OAuth2ProxyCall)) + +#define OAUTH2_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), OAUTH2_TYPE_PROXY_CALL, OAuth2ProxyCallClass)) + +#define OAUTH2_IS_PROXY_CALL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OAUTH2_TYPE_PROXY_CALL)) + +#define OAUTH2_IS_PROXY_CALL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), OAUTH2_TYPE_PROXY_CALL)) + +#define OAUTH2_PROXY_CALL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), OAUTH2_TYPE_PROXY_CALL, OAuth2ProxyCallClass)) + +/** + * OAuth2ProxyCall: + * + * #OAuth2ProxyCall has no publicly available members. + */ +typedef struct { + RestProxyCall parent; +} OAuth2ProxyCall; + +typedef struct { + RestProxyCallClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} OAuth2ProxyCallClass; + +GType oauth2_proxy_call_get_type (void); + +G_END_DECLS + +#endif /* _OAUTH2_PROXY_CALL */ diff --git a/rest/oauth2-proxy-private.h b/rest/oauth2-proxy-private.h new file mode 100644 index 0000000..565c1c3 --- /dev/null +++ b/rest/oauth2-proxy-private.h @@ -0,0 +1,34 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, 2010 Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef _OAUTH2_PROXY_PRIVATE +#define _OAUTH2_PROXY_PRIVATE + +#include "oauth2-proxy.h" + +struct _OAuth2ProxyPrivate { + char *client_id; + char *auth_endpoint; + char *access_token; +}; + +#endif /* _OAUTH2_PROXY_PRIVATE */ diff --git a/rest/oauth2-proxy.c b/rest/oauth2-proxy.c new file mode 100644 index 0000000..1a15bb6 --- /dev/null +++ b/rest/oauth2-proxy.c @@ -0,0 +1,399 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, 2010 Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <rest/rest-proxy.h> +#include <libsoup/soup.h> +#include "oauth2-proxy.h" +#include "oauth2-proxy-private.h" +#include "oauth2-proxy-call.h" + +G_DEFINE_TYPE (OAuth2Proxy, oauth2_proxy, REST_TYPE_PROXY) + +#define OAUTH2_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), OAUTH2_TYPE_PROXY, OAuth2ProxyPrivate)) + +GQuark +oauth2_proxy_error_quark (void) +{ + return g_quark_from_static_string ("rest-oauth2-proxy"); +} + +#define EXTRA_CHARS_ENCODE "!$&'()*+,;=@" + +enum { + PROP_0, + PROP_CLIENT_ID, + PROP_AUTH_ENDPOINT, + PROP_ACCESS_TOKEN +}; + +static RestProxyCall * +_new_call (RestProxy *proxy) +{ + RestProxyCall *call; + + call = g_object_new (OAUTH2_TYPE_PROXY_CALL, + "proxy", proxy, + NULL); + + return call; +} + +static void +oauth2_proxy_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv; + + switch (property_id) { + case PROP_CLIENT_ID: + g_value_set_string (value, priv->client_id); + break; + case PROP_AUTH_ENDPOINT: + g_value_set_string (value, priv->auth_endpoint); + break; + case PROP_ACCESS_TOKEN: + g_value_set_string (value, priv->access_token); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +oauth2_proxy_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv; + + switch (property_id) { + case PROP_CLIENT_ID: + if (priv->client_id) + g_free (priv->client_id); + priv->client_id = g_value_dup_string (value); + break; + case PROP_AUTH_ENDPOINT: + if (priv->auth_endpoint) + g_free (priv->auth_endpoint); + priv->auth_endpoint = g_value_dup_string (value); + break; + case PROP_ACCESS_TOKEN: + if (priv->access_token) + g_free (priv->access_token); + priv->access_token = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +oauth2_proxy_finalize (GObject *object) +{ + OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv; + + g_free (priv->client_id); + g_free (priv->auth_endpoint); + g_free (priv->access_token); + + G_OBJECT_CLASS (oauth2_proxy_parent_class)->finalize (object); +} + +static void +oauth2_proxy_class_init (OAuth2ProxyClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + RestProxyClass *proxy_class = REST_PROXY_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (OAuth2ProxyPrivate)); + + object_class->get_property = oauth2_proxy_get_property; + object_class->set_property = oauth2_proxy_set_property; + object_class->finalize = oauth2_proxy_finalize; + + proxy_class->new_call = _new_call; + + pspec = g_param_spec_string ("client-id", "client-id", + "The client (application) id", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CLIENT_ID, + pspec); + + pspec = g_param_spec_string ("auth-endpoint", "auth-endpoint", + "The authentication endpoint url", NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_AUTH_ENDPOINT, + pspec); + + pspec = g_param_spec_string ("access-token", "access-token", + "The request or access token", NULL, + G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_ACCESS_TOKEN, + pspec); +} + +static void +oauth2_proxy_init (OAuth2Proxy *proxy) +{ + proxy->priv = OAUTH2_PROXY_GET_PRIVATE (proxy); +} + +/** + * oauth2_proxy_new: + * @client_id: the client (application) id + * @auth_endpoint: the authentication endpoint URL + * @url_format: the endpoint URL + * @binding_required: whether the URL needs to be bound before calling + * + * Create a new #OAuth2Proxy for the specified endpoint @url_format, using the + * specified API key and secret. + * + * This proxy won't have the Token set so will be unauthorised. If the token is + * unknown then the following steps should be taken to acquire an access token: + * - Get the authentication url with oauth2_proxy_build_login_url() + * - Display this url in an embedded browser widget + * - wait for the browser widget to be redirected to the specified redirect_uri + * - extract the token from the fragment of the redirected uri (using + * convenience function oauth2_proxy_extract_access_token()) + * - set the token with oauth2_proxy_set_access_token() + * + * Set @binding_required to %TRUE if the URL contains string formatting + * operations (for example "http://foo.com/%<!-- -->s". These must be expanded + * using rest_proxy_bind() before invoking the proxy. + * + * Returns: A new #OAuth2Proxy. + */ +RestProxy * +oauth2_proxy_new (const char *client_id, + const char *auth_endpoint, + const gchar *url_format, + gboolean binding_required) +{ + return g_object_new (OAUTH2_TYPE_PROXY, + "client-id", client_id, + "auth-endpoint", auth_endpoint, + "url-format", url_format, + "binding-required", binding_required, + NULL); +} + +/** + * oauth2_proxy_new_with_token: + * @client_id: the client (application) id + * @access_token: the Access Token + * @auth_endpoint: the authentication endpoint URL + * @url_format: the endpoint URL + * @binding_required: whether the URL needs to be bound before calling + * + * Create a new #OAuth2Proxy for the specified endpoint @url_format, using the + * specified client id + * + * @access_token is used for the Access Token, so if they are still valid then + * this proxy is authorised. + * + * Set @binding_required to %TRUE if the URL contains string formatting + * operations (for example "http://foo.com/%<!-- -->s". These must be expanded + * using rest_proxy_bind() before invoking the proxy. + * + * Returns: A new #OAuth2Proxy. + */ +RestProxy * +oauth2_proxy_new_with_token (const char *client_id, + const char *access_token, + const char *auth_endpoint, + const gchar *url_format, + gboolean binding_required) +{ + return g_object_new (OAUTH2_TYPE_PROXY, + "client-id", client_id, + "access-token", access_token, + "auth-endpoint", auth_endpoint, + "url-format", url_format, + "binding-required", binding_required, + NULL); +} + +/* allocates a new string of the form "key=value" */ +static void +append_query_param (gpointer key, gpointer value, gpointer user_data) +{ + GString *params = (GString*) user_data; + char *encoded_val, *encoded_key; + char *param; + + encoded_val = soup_uri_encode (value, EXTRA_CHARS_ENCODE); + encoded_key = soup_uri_encode (key, EXTRA_CHARS_ENCODE); + + param = g_strdup_printf ("%s=%s", encoded_key, encoded_val); + g_free (encoded_key); + g_free (encoded_val); + + // if there's already a parameter in the string, we need to add a '&' + // separator before adding the new param + if (params->len) + g_string_append_c (params, '&'); + g_string_append (params, param); +} + +/** + * oauth2_proxy_build_login_url_full: + * @proxy: a OAuth2Proxy object + * @redirect_uri: the uri to redirect to after the user authenticates + * @extra_params: any extra parameters to add to the login url (e.g. facebook + * uses 'scope=foo,bar' to request extended permissions). + * + * Builds a url at which the user can log in to the specified OAuth2-based web + * service. In general, this url should be displayed in an embedded browser + * widget, and you should then intercept the browser's redirect to @redirect_uri + * and extract the access token from the url fragment. After the access token + * has been retrieved, call oauth2_proxy_set_access_token(). This must be done + * before making any API calls to the service. + * + * See the oauth2 spec for more details about the "user-agent" authentication + * flow. + * + * The @extra_params and @redirect_uri should not be uri-encoded, that will be + * done automatically + * + * Returns: a newly allocated uri string + */ +char * +oauth2_proxy_build_login_url_full (OAuth2Proxy *proxy, + const char* redirect_uri, + GHashTable* extra_params) +{ + char *url; + GString *params = 0; + char *encoded_uri, *encoded_id; + + g_return_val_if_fail (proxy, NULL); + g_return_val_if_fail (redirect_uri, NULL); + + if (extra_params && g_hash_table_size (extra_params) > 0) { + params = g_string_new (NULL); + g_hash_table_foreach (extra_params, append_query_param, params); + } + + encoded_uri = soup_uri_encode (redirect_uri, EXTRA_CHARS_ENCODE); + encoded_id = soup_uri_encode (proxy->priv->client_id, EXTRA_CHARS_ENCODE); + + url = g_strdup_printf ("%s?client_id=%s&redirect_uri=%s&type=user_agent", + proxy->priv->auth_endpoint, encoded_id, + encoded_uri); + + g_free (encoded_uri); + g_free (encoded_id); + + if (params) { + char * full_url = g_strdup_printf ("%s&%s", url, params->str); + g_free (url); + url = full_url; + g_string_free (params, TRUE); + } + + return url; +} + +/** + * oauth2_proxy_build_login_url: + * @proxy: an OAuth2Proxy object + * @redirect_uri: the uri to redirect to after the user authenticates + * + * Builds a url at which the user can log in to the specified OAuth2-based web + * service. See the documentation for oauth2_proxy_build_login_url_full() for + * detailed information. + * + * Returns: a newly allocated uri string + */ +char * +oauth2_proxy_build_login_url (OAuth2Proxy *proxy, + const char* redirect_uri) +{ + return oauth2_proxy_build_login_url_full (proxy, redirect_uri, NULL); +} + +/** + * oauth2_proxy_get_access_token: + * @proxy: an #OAuth2Proxy + * + * Get the current request or access token. + * + * Returns: the token, or %NULL if there is no token yet. This string is owned + * by #OAuth2Proxy and should not be freed. + */ +const char * +oauth2_proxy_get_access_token (OAuth2Proxy *proxy) +{ + return proxy->priv->access_token; +} + +/** + * oauth2_proxy_set_access_token: + * @proxy: an #OAuth2Proxy + * @token: the access token + * + * Set the access token. + */ +void +oauth2_proxy_set_access_token (OAuth2Proxy *proxy, const char *access_token) +{ + g_return_if_fail (OAUTH2_IS_PROXY (proxy)); + + if (proxy->priv->access_token) + g_free (proxy->priv->access_token); + + proxy->priv->access_token = g_strdup (access_token); +} + +/** + * oauth2_proxy_extract_access_token: + * @url: the url which contains an access token in its fragment + * + * A utility function to extract the access token from the url that results from + * the redirection after the user authenticates + */ +char * +oauth2_proxy_extract_access_token (const char *url) +{ + GHashTable *params; + char *token = NULL; + SoupURI *soupuri = soup_uri_new (url); + + if (soupuri->fragment != NULL) { + params = soup_form_decode (soupuri->fragment); + + if (params) { + char *encoded = g_hash_table_lookup (params, "access_token"); + if (encoded) + token = soup_uri_decode (encoded); + + g_hash_table_destroy (params); + } + } + + return token; +} diff --git a/rest/oauth2-proxy.h b/rest/oauth2-proxy.h new file mode 100644 index 0000000..0473c62 --- /dev/null +++ b/rest/oauth2-proxy.h @@ -0,0 +1,95 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2008, 2009, 2010 Intel Corporation. + * + * Authors: Rob Bradford <rob@linux.intel.com> + * Ross Burton <ross@linux.intel.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _OAUTH2_PROXY +#define _OAUTH2_PROXY + +#include <rest/rest-proxy.h> + +G_BEGIN_DECLS + +#define OAUTH2_TYPE_PROXY oauth2_proxy_get_type() + +#define OAUTH2_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), OAUTH2_TYPE_PROXY, OAuth2Proxy)) + +#define OAUTH2_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), OAUTH2_TYPE_PROXY, OAuth2ProxyClass)) + +#define OAUTH2_IS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OAUTH2_TYPE_PROXY)) + +#define OAUTH2_IS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), OAUTH2_TYPE_PROXY)) + +#define OAUTH2_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), OAUTH2_TYPE_PROXY, OAuth2ProxyClass)) + +typedef struct _OAuth2ProxyPrivate OAuth2ProxyPrivate; + +/** + * OAuth2Proxy: + * + * #OAuth2Proxy has no publicly available members. + */ +typedef struct { + RestProxy parent; + OAuth2ProxyPrivate *priv; +} OAuth2Proxy; + +typedef struct { + RestProxyClass parent_class; + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +} OAuth2ProxyClass; + +GType oauth2_proxy_get_type (void); + +RestProxy* oauth2_proxy_new (const char *client_id, + const char *auth_endpoint, + const gchar *url_format, + gboolean binding_required); + +RestProxy* oauth2_proxy_new_with_token (const char *client_id, + const char *access_token, + const char *auth_endpoint, + const gchar *url_format, + gboolean binding_required); + +char * oauth2_proxy_build_login_url_full (OAuth2Proxy *proxy, + const char* redirect_uri, + GHashTable* extra_params); + +char * oauth2_proxy_build_login_url (OAuth2Proxy *proxy, + const char* redirect_uri); + +const char * oauth2_proxy_get_access_token (OAuth2Proxy *proxy); + +void oauth2_proxy_set_access_token (OAuth2Proxy *proxy, const char *access_token); + +char * oauth2_proxy_extract_access_token (const char *url); + +G_END_DECLS + +#endif /* _OAUTH2_PROXY */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 0a112f3..fe265e6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,4 @@ -TESTS = proxy threaded oauth oauth-async flickr -# TODO: oauth-async is failing due to infinite looping for some reason. Need to -# fix this. -XFAIL_TESTS = oauth-async +TESTS = proxy threaded oauth oauth-async oauth2 flickr AM_CPPFLAGS = $(SOUP_CFLAGS) -I$(top_srcdir) AM_LDFLAGS = $(SOUP_LIBS) ../rest/librest-@API_VERSION@.la ../rest-extras/librest-extras-@API_VERSION@.la @@ -12,4 +9,5 @@ proxy_SOURCES = proxy.c threaded_SOURCES = threaded.c oauth_SOURCES = oauth.c oauth_async_SOURCES = oauth-async.c +oauth2_SOURCES = oauth2.c flickr_SOURCES = flickr.c diff --git a/tests/oauth2.c b/tests/oauth2.c new file mode 100644 index 0000000..e992b6a --- /dev/null +++ b/tests/oauth2.c @@ -0,0 +1,56 @@ +/* + * librest - RESTful web services access + * Copyright (c) 2010 Intel Corporation. + * + * Authors: Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <rest/oauth2-proxy.h> +#include <string.h> + +void +test_extract_token () +{ + char *token; + + /* test a url without a fragment */ + token = oauth2_proxy_extract_access_token ("http://example.com/"); + g_assert (token == NULL); + + /* test a url with a fragment but without an access_token parameter */ + token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#bar"); + g_assert (token == NULL); + + /* test simple access_token */ + token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#access_token=1234567890_12.34561abcdefg&bar"); + g_assert (strcmp(token, "1234567890_12.34561abcdefg") == 0); + + /* test access_token with url encoding */ + token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#access_token=1234567890%5F12%2E34561abcdefg&bar"); + g_assert (strcmp(token, "1234567890_12.34561abcdefg") == 0); +} + +int +main (int argc, char **argv) +{ + g_thread_init (NULL); + g_type_init (); + + test_extract_token (); + + return 0; +} |