diff options
Diffstat (limited to 'lib/oauth2.c')
| -rw-r--r-- | lib/oauth2.c | 76 | 
1 files changed, 59 insertions, 17 deletions
| diff --git a/lib/oauth2.c b/lib/oauth2.c index 6921a6d5..bfd4b143 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 ) @@ -78,7 +95,6 @@ int oauth2_access_token( const struct oauth2_service *sp,  	                     "Host: %s\r\n"  	                     "Content-Type: application/x-www-form-urlencoded\r\n"  	                     "Content-Length: %zd\r\n" -	                     "Connection: close\r\n"  	                     "\r\n"  	                     "%s", url_p.file, url_p.host, strlen( args_s ), args_s );  	g_free( args_s ); @@ -98,10 +114,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 +150,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 +182,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 );  } | 
