- Timestamp:
- 2011-07-26T11:58:38Z (13 years ago)
- Branches:
- master
- Children:
- 1174899
- Parents:
- 59c9adb4
- Location:
- lib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/oauth.h
r59c9adb4 r4a5d885 92 92 93 93 /* For reading misc. data. */ 94 void oauth_params_add( GSList **params, const char *key, const char *value ); 95 void oauth_params_free( GSList **params ); 96 char *oauth_params_string( GSList *params ); 94 97 const char *oauth_params_get( GSList **params, const char *key ); -
lib/oauth2.c
r59c9adb4 r4a5d885 23 23 24 24 #include <glib.h> 25 #include "http_client.h" 25 26 #include "oauth2.h" 27 #include "oauth.h" 28 #include "url.h" 26 29 27 30 struct oauth2_service oauth2_service_google = … … 41 44 NULL ); 42 45 } 46 47 struct oauth2_access_token_data 48 { 49 oauth2_token_callback func; 50 gpointer data; 51 }; 52 53 static char *oauth2_json_dumb_get( const char *json, const char *key ); 54 static void oauth2_access_token_done( struct http_request *req ); 55 56 int oauth2_access_token( const struct oauth2_service *sp, 57 const char *auth_type, const char *auth, 58 oauth2_token_callback func, gpointer data ) 59 { 60 GSList *args = NULL; 61 char *args_s, *s; 62 url_t url_p; 63 struct http_request *req; 64 struct oauth2_access_token_data *cb_data; 65 66 if( !url_set( &url_p, sp->base_url ) ) 67 return 0; 68 69 oauth_params_add( &args, "client_id", sp->consumer_key ); 70 oauth_params_add( &args, "client_secret", sp->consumer_secret ); 71 oauth_params_add( &args, "grant_type", auth_type ); 72 if( strcmp( auth_type, OAUTH2_AUTH_CODE ) == 0 ) 73 { 74 oauth_params_add( &args, "redirect_uri", "urn:ietf:wg:oauth:2.0:oob" ); 75 oauth_params_add( &args, "code", auth ); 76 } 77 else 78 { 79 oauth_params_add( &args, "refresh_token", auth ); 80 } 81 args_s = oauth_params_string( args ); 82 oauth_params_free( &args ); 83 84 s = g_strdup_printf( "POST %s%s HTTP/1.0\r\n" 85 "Host: %s\r\n" 86 "Content-Type: application/x-www-form-urlencoded\r\n" 87 "Content-Length: %zd\r\n" 88 "Connection: close\r\n" 89 "\r\n" 90 "%s", url_p.file, "token", url_p.host, strlen( args_s ), args_s ); 91 g_free( args_s ); 92 93 cb_data = g_new0( struct oauth2_access_token_data, 1 ); 94 cb_data->func = func; 95 cb_data->data = data; 96 97 req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, 98 s, oauth2_access_token_done, cb_data ); 99 100 g_free( s ); 101 102 if( req == NULL ) 103 g_free( cb_data ); 104 105 return req != NULL; 106 } 107 108 static void oauth2_access_token_done( struct http_request *req ) 109 { 110 struct oauth2_access_token_data *cb_data = req->data; 111 char *atoken = NULL, *rtoken = NULL; 112 113 if( req->status_code == 200 ) 114 { 115 atoken = oauth2_json_dumb_get( req->reply_body, "access_token" ); 116 rtoken = oauth2_json_dumb_get( req->reply_body, "refresh_token" ); 117 } 118 cb_data->func( cb_data->data, atoken, rtoken ); 119 g_free( atoken ); 120 g_free( rtoken ); 121 g_free( cb_data ); 122 } 123 124 /* Super dumb. I absolutely refuse to use/add a complete json parser library 125 (adding a new dependency to BitlBee for the first time in.. 6 years?) just 126 to parse 100 bytes of data. So I have to do my own parsing because OAuth2 127 dropped support for XML. (GRRR!) This is very dumb and for example won't 128 work for integer values, nor will it strip/handle backslashes. */ 129 static char *oauth2_json_dumb_get( const char *json, const char *key ) 130 { 131 int is_key; /* 1 == reading key, 0 == reading value */ 132 int found_key = 0; 133 134 while( json && *json ) 135 { 136 /* Grab strings and see if they're what we're looking for. */ 137 if( *json == '"' || *json == '\'' ) 138 { 139 char q = *json; 140 const char *str_start; 141 json ++; 142 str_start = json; 143 144 while( *json ) 145 { 146 /* \' and \" are not string terminators. */ 147 if( *json == '\\' && json[1] == q ) 148 json ++; 149 /* But without a \ it is. */ 150 else if( *json == q ) 151 break; 152 json ++; 153 } 154 if( *json == '\0' ) 155 return NULL; 156 157 if( is_key && strncmp( str_start, key, strlen( key ) ) == 0 ) 158 { 159 found_key = 1; 160 } 161 else if( !is_key && found_key ) 162 { 163 char *ret = g_memdup( str_start, json - str_start + 1 ); 164 ret[json-str_start] = '\0'; 165 return ret; 166 } 167 168 } 169 else if( *json == '{' || *json == ',' ) 170 { 171 found_key = 0; 172 is_key = 1; 173 } 174 else if( *json == ':' ) 175 is_key = 0; 176 177 json ++; 178 } 179 180 return NULL; 181 } -
lib/oauth2.h
r59c9adb4 r4a5d885 2 2 * * 3 3 * BitlBee - An IRC to IM gateway * 4 * Simple OAuth client (consumer) implementation.*4 * Simple OAuth2 client (consumer) implementation. * 5 5 * * 6 6 * Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net> * … … 22 22 \***************************************************************************/ 23 23 24 struct oauth2_info; 24 /* Implementation mostly based on my experience with writing the previous OAuth 25 module, and from http://code.google.com/apis/accounts/docs/OAuth2.html . */ 25 26 26 /* Callback function called twice during the access token request process. 27 Return FALSE if something broke and the process must be aborted. */ 28 typedef gboolean (*oauth_cb)( struct oauth2_info * ); 29 30 struct oauth2_info 31 { 32 const struct oauth_service *sp; 33 34 oauth_cb func; 35 void *data; 36 37 struct http_request *http; 38 39 // char *auth_url; 40 // char *request_token; 41 42 // char *token; 43 // char *token_secret; 44 // GSList *params; 45 }; 27 typedef void (*oauth2_token_callback)( gpointer data, const char *atoken, const char *rtoken ); 46 28 47 29 struct oauth2_service … … 52 34 }; 53 35 36 /* Currently suitable for authenticating to Google Talk only, and only for 37 accounts that have 2-factor authorization enabled. */ 54 38 extern struct oauth2_service oauth2_service_google; 55 39 56 /* http://oauth.net/core/1.0a/#auth_step1 (section 6.1) 57 Request an initial anonymous token which can be used to construct an 58 authorization URL for the user. This is passed to the callback function 59 in a struct oauth2_info. */ 40 #define OAUTH2_AUTH_CODE "authorization_code" 41 #define OAUTH2_AUTH_REFRESH "refresh_token" 42 43 /* Generate a URL the user should open in his/her browser to get an 44 authorization code. */ 60 45 char *oauth2_url( const struct oauth2_service *sp, const char *scope ); 61 46 62 /* http://oauth.net/core/1.0a/#auth_step3 (section 6.3) 63 The user gets a PIN or so which we now exchange for the final access 64 token. This is passed to the callback function in the same 65 struct oauth2_info. */ 66 gboolean oauth2_access_token( const char *pin, struct oauth2_info *st ); 67 68 /* Shouldn't normally be required unless the process is aborted by the user. */ 69 void oauth2_info_free( struct oauth2_info *info ); 47 /* Exchanges an auth code or refresh token for an access token. 48 auth_type is one of the two OAUTH2_AUTH_.. constants above. */ 49 int oauth2_access_token( const struct oauth2_service *sp, 50 const char *auth_type, const char *auth, 51 oauth2_token_callback func, gpointer data );
Note: See TracChangeset
for help on using the changeset viewer.