aboutsummaryrefslogtreecommitdiffstats
path: root/lib/oauth2.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/oauth2.c')
-rw-r--r--lib/oauth2.c75
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 );
}