diff options
author | Günther Wagner <info@gunibert.de> | 2022-01-12 18:26:38 +0000 |
---|---|---|
committer | Günther Wagner <info@gunibert.de> | 2022-01-12 18:26:38 +0000 |
commit | 6d65d8862ad7d39e55be0adb868c05f194250e74 (patch) | |
tree | 46ffe23af55fb90e3199b184b9c820e0f8af0c9a /examples | |
parent | 7766d718735270d1c0850685a3c7655a5726d60f (diff) | |
download | librest-6d65d8862ad7d39e55be0adb868c05f194250e74.tar.gz |
OAuth2 Pkce Workflow
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile.am | 13 | ||||
-rw-r--r-- | examples/gitlab-oauth2-example.c | 148 | ||||
-rw-r--r-- | examples/meson.build | 1 |
3 files changed, 149 insertions, 13 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am deleted file mode 100644 index 4f68e7c..0000000 --- a/examples/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -noinst_PROGRAMS = test-raw test-xml dump-xml post-twitter post-twitter-media get-flickr-favorites lastfm-shout continuous-twitter - -AM_CFLAGS = $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) $(SOUP_CFLAGS) -I$(top_srcdir) -AM_LDFLAGS = $(GLIB_LIBS) $(GTHREAD_LIBS) $(SOUP_LIBS) ../rest/librest-@API_VERSION@.la ../rest-extras/librest-extras-@API_VERSION@.la - -test_raw_SOURCES = test-raw.c -test_xml_SOURCES = test-xml.c -dump_xml_SOURCES = dump-xml.c -post_twitter_SOURCES = post-twitter.c -post_twitter_media_SOURCES = post-twitter-media.c -get_flickr_favorites_SOURCES = get-flickr-favorites.c -lastfm_shout_SOURCES = lastfm-shout.c -continuous_twitter_SOURCES = continuous-twitter.c diff --git a/examples/gitlab-oauth2-example.c b/examples/gitlab-oauth2-example.c new file mode 100644 index 0000000..f18cbab --- /dev/null +++ b/examples/gitlab-oauth2-example.c @@ -0,0 +1,148 @@ +/* gitlab-oauth2-example.c + * + * Copyright 2021 Günther Wagner <info@gunibert.de> + * + * 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. + */ + +/** + * This example shows the recommended PKCE authorization flow for Gitlab. + */ + +#include <glib.h> +#include <rest/rest.h> +#include <stdio.h> +#include <libsoup/soup.h> + +GMainLoop *loop; + +static void +load_projects (RestProxy *proxy) +{ + g_autoptr(GError) error = NULL; + RestProxyCall *call; + + call = rest_proxy_new_call (proxy); + rest_proxy_call_set_method (call, "GET"); + rest_proxy_call_set_function (call, "projects/426/issues"); + rest_proxy_call_sync (call, &error); + + g_print ("%s\n", rest_proxy_call_get_payload (call)); + g_main_loop_quit (loop); +} + +static void +gitlab_oauth2_example_refreshed_access_token (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + RestOAuth2Proxy *oauth2_proxy = (RestOAuth2Proxy *)object; + g_autoptr(GError) error = NULL; + + g_assert (G_IS_OBJECT (object)); + g_assert (G_IS_ASYNC_RESULT (result)); + + rest_oauth2_proxy_refresh_access_token_finish (oauth2_proxy, result, &error); + if (error) + g_error ("%s", error->message); + + g_print ("Access Token: %s\n", rest_oauth2_proxy_get_access_token (oauth2_proxy)); + g_print ("Refresh Token: %s\n", rest_oauth2_proxy_get_refresh_token (oauth2_proxy)); + GDateTime *expiration_date = rest_oauth2_proxy_get_expiration_date (oauth2_proxy); + if (expiration_date) + g_print ("Expires in: %s\n", g_date_time_format (expiration_date, "%X %x")); + + load_projects (REST_PROXY (oauth2_proxy)); +} + +static void +gitlab_oauth2_example_fetched_access_token (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + RestOAuth2Proxy *oauth2_proxy = (RestOAuth2Proxy *)object; + g_autoptr(GError) error = NULL; + + g_assert (G_IS_OBJECT (object)); + g_assert (G_IS_ASYNC_RESULT (result)); + + rest_oauth2_proxy_fetch_access_token_finish (oauth2_proxy, result, &error); + if (error) + g_error ("%s", error->message); + + g_print ("Access Token: %s\n", rest_oauth2_proxy_get_access_token (oauth2_proxy)); + g_print ("Refresh Token: %s\n", rest_oauth2_proxy_get_refresh_token (oauth2_proxy)); + GDateTime *expiration_date = rest_oauth2_proxy_get_expiration_date (oauth2_proxy); + if (expiration_date) + g_print ("Expires in: %s\n", g_date_time_format (expiration_date, "%X %x")); + + /* refresh token */ + rest_oauth2_proxy_refresh_access_token_async (oauth2_proxy, NULL, gitlab_oauth2_example_refreshed_access_token, user_data); +} + +gint +main (gint argc, + gchar *argv[]) +{ + g_autofree gchar *line = NULL; + size_t len = 0; + + gchar **environment = g_get_environ (); + gchar *authurl = "https://gitlab.gnome.org/oauth/authorize"; + gchar *tokenurl = "https://gitlab.gnome.org/oauth/token"; + gchar *redirecturl = "http://example.com"; + gchar *baseurl = "https://gitlab.gnome.org/api/v4/"; + const gchar *clientid = g_environ_getenv (environment, "REST_OAUTH2_CLIENT_ID"); + if (!clientid) + { + g_print ("You have to define your Gitlab Client ID as REST_OAUTH2_CLIENT_ID environment variable\n"); + return EXIT_SUCCESS; + } + + const gchar *clientsecret = g_environ_getenv (environment, "REST_OAUTH2_CLIENT_SECRET"); + if (!clientsecret) + { + g_print ("You have to define your Gitlab Client Secret as REST_OAUTH2_CLIENT_SECRET environment variable\n"); + return EXIT_SUCCESS; + } + RestPkceCodeChallenge *pkce = rest_pkce_code_challenge_new_random (); + gchar *state = NULL; + +#ifdef WITH_SOUP_2 + SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_HEADERS, -1); +#else + SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_HEADERS); +#endif + + RestOAuth2Proxy *oauth2_proxy = rest_oauth2_proxy_new (authurl, tokenurl, redirecturl, clientid, clientsecret, baseurl); + rest_proxy_add_soup_feature (REST_PROXY (oauth2_proxy), SOUP_SESSION_FEATURE (logger)); + const gchar *authorize_url = rest_oauth2_proxy_build_authorization_url (oauth2_proxy, rest_pkce_code_challenge_get_challenge (pkce), NULL, &state); + + g_print ("URL to authorize: %s\n", authorize_url); + + ssize_t chars = getline (&line, &len, stdin); + if (line[chars - 1] == '\n') { + line[chars - 1] = '\0'; + } + + g_print ("Got Authorization Grant: %s\n", line); + + /* fetch access token */ + rest_oauth2_proxy_fetch_access_token_async (oauth2_proxy, line, rest_pkce_code_challenge_get_verifier (pkce), NULL, gitlab_oauth2_example_fetched_access_token, NULL); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/meson.build b/examples/meson.build index 7d16dc7..375a72a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -7,6 +7,7 @@ example_names = [ 'get-flickr-favorites', 'lastfm-shout', 'continuous-twitter', + 'gitlab-oauth2-example', ] example_deps = [ |