diff options
Diffstat (limited to 'lib/oauth2.c')
-rw-r--r-- | lib/oauth2.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/lib/oauth2.c b/lib/oauth2.c index 6921a6d5..69ce9d58 100644 --- a/lib/oauth2.c +++ b/lib/oauth2.c @@ -1,9 +1,9 @@ /***************************************************************************\ * * * BitlBee - An IRC to IM gateway * -* Simple OAuth client (consumer) implementation. * +* Simple OAuth2 client (consumer) implementation. * * * -* Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net> * +* Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -21,11 +21,28 @@ * * \***************************************************************************/ +/* Out of protest, I should rename this file. OAuth2 is a pathetic joke, and + of all things, DEFINITELY NOT A STANDARD. The only thing various OAuth2 + implementations have in common is that name, wrongfully stolen from + a pretty nice standard called OAuth 1.0a. That, and the fact that they + use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its + responses. + + Apparently too many people were too retarded to comprehend the elementary + bits of crypto in OAuth 1.0a (took me one afternoon to implement) so + the standard was replaced with what comes down to a complicated scheme + around what's really just application-specific passwords. + + And then a bunch of mostly incompatible implementations. Great work, guys. + + http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ */ + #include <glib.h> #include "http_client.h" #include "oauth2.h" #include "oauth.h" #include "json.h" +#include "json_util.h" #include "url.h" char *oauth2_url( const struct oauth2_service *sp ) @@ -98,10 +115,35 @@ int oauth2_access_token( const struct oauth2_service *sp, return req != NULL; } +static char* oauth2_parse_error( json_value *e ) +{ + /* This does a reasonable job with some of the flavours of error + responses I've seen. Because apparently it's not standardised. */ + + if( e->type == json_object ) + { + /* Facebook style */ + const char *msg = json_o_str( e, "message" ); + const char *type = json_o_str( e, "type" ); + json_value *code_o = json_o_get( e, "code" ); + int code = 0; + + if( code_o && code_o->type == json_integer ) + code = code_o->u.integer; + + return g_strdup_printf( "Error %d: %s", code, msg ? msg : type ? type : "Unknown error" ); + } + else if( e->type == json_string ) + { + return g_strdup( e->u.string.ptr ); + } + return NULL; +} + static void oauth2_access_token_done( struct http_request *req ) { struct oauth2_access_token_data *cb_data = req->data; - char *atoken = NULL, *rtoken = NULL; + char *atoken = NULL, *rtoken = NULL, *error = NULL; char *content_type; if( getenv( "BITLBEE_DEBUG" ) && req->reply_body ) @@ -109,24 +151,22 @@ static void oauth2_access_token_done( struct http_request *req ) content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 ); - if( req->status_code != 200 ) - { - } - else if( content_type && strstr( content_type, "application/json" ) ) + if( content_type && ( strstr( content_type, "application/json" ) || + strstr( content_type, "text/javascript" ) ) ) { json_value *js = json_parse( req->reply_body ); if( js && js->type == json_object ) { - int i; - - for( i = 0; i < js->u.object.length; i ++ ) + JSON_O_FOREACH( js, k, v ) { - if( js->u.object.values[i].value->type != json_string ) + if( strcmp( k, "error" ) == 0 ) + error = oauth2_parse_error( v ); + if( v->type != json_string ) continue; - if( strcmp( js->u.object.values[i].name, "access_token" ) == 0 ) - atoken = g_strdup( js->u.object.values[i].value->u.string.ptr ); - if( strcmp( js->u.object.values[i].name, "refresh_token" ) == 0 ) - rtoken = g_strdup( js->u.object.values[i].value->u.string.ptr ); + if( strcmp( k, "access_token" ) == 0 ) + atoken = g_strdup( v->u.string.ptr ); + if( strcmp( k, "refresh_token" ) == 0 ) + rtoken = g_strdup( v->u.string.ptr ); } } json_value_free( js ); @@ -143,10 +183,13 @@ static void oauth2_access_token_done( struct http_request *req ) } if( getenv( "BITLBEE_DEBUG" ) ) printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken ); + if( !atoken && !rtoken && !error ) + error = g_strdup( "Unusuable response" ); - cb_data->func( cb_data->data, atoken, rtoken ); + cb_data->func( cb_data->data, atoken, rtoken, error ); g_free( content_type ); g_free( atoken ); g_free( rtoken ); + g_free( error ); g_free( cb_data ); } |