LibOAuth Sample Overview

Mobile native

The LibOAuth sample application demonstrates how you can get access tokens from various resource owners, such as Twitter and Tumblr, who use the OAuth protocol RFC5849.

The following figure illustrates the main view of the LibOAuth application.

Figure: LibOAuth main view

LibOAuth main view

The application opens with the main screen that lists various resource providers. To get an access token from a specific provider, select the provider from the list.

Prerequisites

  • To ensure proper application execution, the following privileges must be set:

    • http://tizen.org/privilege/network.get
    • http://tizen.org/privilege/internet
  • Internet connection must be enabled in the device.
  • The system time in the device must be adjusted to the respective time zone and the time must be accurate.
  • The dummy client ID and dummy client secret in the oauth_provider_configs.h file must be replaced with the respective App ID and App secret in the LibOAuth sample application.

    Obtain the needed client IDs and secrets from the respective resource owners. For example, the Twitter client ID and secret can be obtained from Twitter Apps as follows:

    1. Go to Twitter Apps, sign in to your Twitter account, and click Create New App.
    2. Provide the application Name, Description, and URL for the LibOAuth sample and click Create your Twitter application.
    3. Obtain the client ID (consumer key) and secret by selecting (manage keys and access tokens) beside Application Settings > Consumer key.

Implementation

The OAuth 1.0 specification is defined in [RFC 5849] and it builds on the OAuth 1.0 [RFC 5849] deployment experience, as well as additional use cases and extensibility requirements gathered from the wider IETF community.

OAuth 1.0 provides a method for clients to access server resources on behalf of a resource owner (such as a different client or an end user). It also provides a process for end users to authorize third-party access to their server resources without sharing their credentials (typically, a username and password pair), using user-agent redirections.

Twitter

The following figure illustrates the 3-legged authorization process of Twitter. The 3-legged OAuth flow allows your application to obtain an access token by redirecting a user to resource provider and having them authorize your application.

Figure: 3-leg authorization

3-leg authorization

After you select Twitter Login on the main screen, the sign-in window appears. To get the access token, enter your Twitter account credentials and click Sign in. Once your account gets verified, the response is displayed on the screen as a popup.

You can cancel the operation by pressing the back key.

Figure: Twitter authorization

Twitter authorization Twitter authorization

static oauth_provider_data_s*
static oauth_provider_data_s*
__create_tw_data(void)
{
   oauth_provider_data_s *provider = calloc(1, sizeof(oauth_provider_data_s));

   provider->app_info = calloc(1, sizeof(oauth_provider_app_info_s));
   provider->app_info->cons_key = calloc(1, MAX_STR_LEN);
   provider->app_info->cons_secret = calloc(1, MAX_STR_LEN);

   provider->provider_name = calloc(1, MAX_URL_LEN);
   provider->token_url = calloc(1, MAX_URL_LEN);
   provider->auth_url = calloc(1, MAX_URL_LEN);
   provider->acc_tok_url = calloc(1, MAX_URL_LEN);

   snprintf(provider->provider_name, MAX_URL_LEN - 1, "%s", TWITTER_NAME);
   snprintf(provider->app_info->cons_key , MAX_STR_LEN - 1, "%s", TWITTER_CONS_KEY);
   snprintf(provider->app_info->cons_secret, MAX_STR_LEN - 1, "%s", TWITTER_CONS_SEC);

   snprintf(provider->token_url, MAX_URL_LEN - 1, "%s", TWITTER_REQ_TOK_URL);
   snprintf(provider->auth_url, MAX_URL_LEN - 1, "%s", TWITTER_AUTH_URL);
   snprintf(provider->acc_tok_url, MAX_URL_LEN - 1, "%s", TWITTER_ACC_TOK_URL);

   return provider;
}


// Step 1: Get request token
int
get_access_token(oauth_provider_data_s *provider_data, on_access_token_received_cb cb, void *user_data)
{

   if (__curl == NULL)
      __curl = curl_easy_init();

   oauth_provider_data_full_s *oauth_full = calloc(1, sizeof(oauth_provider_data_full_s));
   oauth_full->provider_info = provider_data;
   oauth_full->cb = cb;
   oauth_full->user_data = user_data;

   char *oauth_header = __get_oauth_header(provider_data->token_url, provider_data->app_info->cons_key, 
                                           provider_data->app_info->cons_secret, NULL, NULL);
   int curl_err = 0;
   long http_code = 0;
   char *resp = __curl_post_request(provider_data->token_url, oauth_header, NULL, &curl_err, &http_code);
   if (resp == NULL) 
   {
      if (curl_err == CURLE_OK)
         return OAUTH_ERROR_SERVER;
      else
         return OAUTH_ERROR_NETWORK;
   }

   char *token = NULL;
   char *token_sec = NULL;

   __parse_reply(resp, &token, &token_sec);
   if ((token == NULL) || (token_sec == NULL)) 
   {
      SAFE_DELETE(token);
      SAFE_DELETE(token_sec);

      return OAUTH_ERROR_SERVER;
   }

   oauth_full->token_temp = token;

   oauth_full->token = calloc(1, sizeof(oauth_provider_token_s));
   oauth_full->token->acc_tok_secret = token_sec;

   char url[MAX_URL_LEN] = {0,};
   snprintf(url, MAX_URL_LEN - 1, "%s?oauth_token=%s", oauth_full->provider_info->auth_url, oauth_full->token_temp);
   __show_web_view(oauth_full, url);

   oauth_full->loading_popup = elm_popup_add(oauth_full->login_win);
   elm_popup_content_text_wrap_type_set(oauth_full->loading_popup, ELM_WRAP_MIXED);
   elm_object_text_set(oauth_full->loading_popup, "Loading...");
   elm_popup_orient_set(oauth_full->loading_popup, ELM_POPUP_ORIENT_BOTTOM);

   evas_object_show(oauth_full->loading_popup);

   return OAUTH_ERROR_NONE;
}

// Step 2: Get authorization (user enters their credentials, and allows access to this app)
static int
__show_web_view(oauth_provider_data_full_s *oauth_full, const char *url)
{
   int w = 400;
   int h = 400;

   system_info_get_platform_int("tizen.org/feature/screen.width", &w);
   system_info_get_platform_int("tizen.org/feature/screen.height", &h);

   oauth_full->login_win = elm_win_util_standard_add("Login", "");
   eext_object_event_callback_add(oauth_full->login_win, EEXT_CALLBACK_BACK, __handle_back_key, oauth_full);

   ewk_init();

   Evas *canvas = NULL;

   oauth_full->content_box = elm_box_add(oauth_full->login_win);
   elm_box_padding_set(oauth_full->content_box, 0, 3);
   evas_object_size_hint_weight_set(oauth_full->content_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(oauth_full->content_box, 0.0, 0.0);
   evas_object_show(oauth_full->content_box);

   canvas = evas_object_evas_get(oauth_full->login_win);

   oauth_full->ewk_view = ewk_view_add(canvas);
   if (oauth_full->ewk_view == NULL)
      return OAUTH_ERROR_SYSTEM;

   ewk_view_url_set(oauth_full->ewk_view, url);
   evas_object_size_hint_min_set(oauth_full->ewk_view, w, h);

   evas_object_size_hint_weight_set(oauth_full->ewk_view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   evas_object_size_hint_align_set(oauth_full->ewk_view, EVAS_HINT_FILL, EVAS_HINT_FILL);

   evas_object_smart_callback_add(oauth_full->ewk_view, "url,changed", __on_web_url_change, oauth_full);
   evas_object_smart_callback_add(oauth_full->ewk_view, "load,error", __on_web_url_load_error, oauth_full);
   evas_object_smart_callback_add(oauth_full->ewk_view, "load,finished", __on_web_url_load_finished, oauth_full);

   elm_box_pack_end(oauth_full->content_box, oauth_full->ewk_view);
   evas_object_show(oauth_full->ewk_view);

   evas_object_show(oauth_full->login_win);

   return 0;
}

// Step 3: Get access token
static void
_on_auth_grant_received(oauth_provider_data_full_s *oauth_full, const char *reply)
{
   if (reply == NULL)
   {
      SAFE_DELETE(oauth_full->token);
      __send_response(OAUTH_ERROR_SERVER, oauth_full);

      return;
   }

   gchar **full_list = g_strsplit(reply,"&", 5);

   char *token_full = full_list[0];
   if (token_full == NULL)
   {
      SAFE_DELETE(oauth_full->token);
      __send_response(OAUTH_ERROR_SERVER, oauth_full);

      return;
   }

   if (full_list[1] == NULL)
   {
      SAFE_DELETE(oauth_full->token);
      __send_response(OAUTH_ERROR_SERVER, oauth_full);

      return;
   }

   char *verf_full = full_list[1];
   if (verf_full == NULL)
   {
      SAFE_DELETE(oauth_full->token);
      __send_response(OAUTH_ERROR_SERVER, oauth_full);

      return;
   }

   gchar **token_list = g_strsplit(token_full, "=", 3);

   if (oauth_full->token_temp != NULL) 
   {
      free(oauth_full->token_temp);
      oauth_full->token_temp = NULL;
   }

   oauth_full->token_temp = strdup(token_list[1]);

   gchar **verf_list = g_strsplit(verf_full, "=", 3);
   if (verf_list == NULL)
   {
      SAFE_DELETE(oauth_full->token);
      __send_response(OAUTH_ERROR_SERVER, oauth_full);

      return;
   }

   oauth_full->verifier_temp = strdup(verf_list[1]);

   __start_access_token_request(oauth_full);
}

Tumblr

Tumblr, like Twitter, follows the 3-legged verification flow. The difference is that the user is always prompted to authorize access to the application, even if access has been previously granted.

After you select Tumblr Login on the main screen, the log-in window appears. To get the access token, enter your Tumblr account credentials and click Log in. Once your account gets verified, a permission window opens and you must authorize access by clicking Allow. The response is displayed on the screen as a popup.

You can cancel the operation by pressing the back key or by clicking No way.

Figure: Tumblr authorization

Tumblr authorization Tumblr authorization Tumblr authorization

static oauth_provider_data_s*
__create_tumblr_data(void)
{
   oauth_provider_data_s *provider = calloc(1, sizeof(oauth_provider_data_s));

   provider->app_info = calloc(1, sizeof(oauth_provider_app_info_s));
   provider->app_info->cons_key = calloc(1, MAX_STR_LEN);
   provider->app_info->cons_secret = calloc(1, MAX_STR_LEN);

   provider->provider_name = calloc(1, MAX_URL_LEN);
   provider->token_url = calloc(1, MAX_URL_LEN);
   provider->auth_url = calloc(1, MAX_URL_LEN);
   provider->acc_tok_url = calloc(1, MAX_URL_LEN);

   snprintf(provider->provider_name, MAX_URL_LEN - 1, "%s", TUMBLR_NAME);
   snprintf(provider->app_info->cons_key , MAX_STR_LEN - 1, "%s", TUMBLR_CONS_KEY);
   snprintf(provider->app_info->cons_secret, MAX_STR_LEN - 1, "%s", TUMBLR_CONS_SEC);

   snprintf(provider->token_url, MAX_URL_LEN - 1, "%s", TUMBLR_REQ_TOK_URL);
   snprintf(provider->auth_url, MAX_URL_LEN - 1, "%s", TUMBLR_AUTH_URL);
   snprintf(provider->acc_tok_url, MAX_URL_LEN - 1, "%s", TUMBLR_ACC_TOK_URL);

   return provider;
}