source: lib/oauth2.c @ ba654ec

Last change on this file since ba654ec was ba654ec, checked in by Wilmer van der Gaast <wilmer@…>, at 2012-10-28T23:36:55Z

Use the new JSON code for OAuth2 processing.

Starting to see the use of convenience functions to dig through many layers
of structs..

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  Simple OAuth client (consumer) implementation.                           *
5*                                                                           *
6*  Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net>              *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include <glib.h>
25#include "http_client.h"
26#include "oauth2.h"
27#include "oauth.h"
28#include "json.h"
29#include "url.h"
30
31char *oauth2_url( const struct oauth2_service *sp )
32{
33        return g_strconcat( sp->auth_url,
34                            "?scope=", sp->scope,
35                            "&response_type=code"
36                            "&redirect_uri=", sp->redirect_url, 
37                            "&client_id=", sp->consumer_key,
38                            NULL );
39}
40
41struct oauth2_access_token_data
42{
43        oauth2_token_callback func;
44        gpointer data;
45};
46
47static void oauth2_access_token_done( struct http_request *req );
48
49int oauth2_access_token( const struct oauth2_service *sp,
50                         const char *auth_type, const char *auth,
51                         oauth2_token_callback func, gpointer data )
52{
53        GSList *args = NULL;
54        char *args_s, *s;
55        url_t url_p;
56        struct http_request *req;
57        struct oauth2_access_token_data *cb_data;
58       
59        if( !url_set( &url_p, sp->token_url ) )
60                return 0;
61       
62        oauth_params_add( &args, "client_id", sp->consumer_key );
63        oauth_params_add( &args, "client_secret", sp->consumer_secret );
64        oauth_params_add( &args, "grant_type", auth_type );
65        if( strcmp( auth_type, OAUTH2_AUTH_CODE ) == 0 )
66        {
67                oauth_params_add( &args, "redirect_uri", sp->redirect_url );
68                oauth_params_add( &args, "code", auth );
69        }
70        else
71        {
72                oauth_params_add( &args, "refresh_token", auth );
73        }
74        args_s = oauth_params_string( args );
75        oauth_params_free( &args );
76       
77        s = g_strdup_printf( "POST %s HTTP/1.0\r\n"
78                             "Host: %s\r\n"
79                             "Content-Type: application/x-www-form-urlencoded\r\n"
80                             "Content-Length: %zd\r\n"
81                             "Connection: close\r\n"
82                             "\r\n"
83                             "%s", url_p.file, url_p.host, strlen( args_s ), args_s );
84        g_free( args_s );
85       
86        cb_data = g_new0( struct oauth2_access_token_data, 1 );
87        cb_data->func = func;
88        cb_data->data = data;
89       
90        req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS,
91                              s, oauth2_access_token_done, cb_data );
92       
93        g_free( s );
94       
95        if( req == NULL )
96                g_free( cb_data );
97       
98        return req != NULL;
99}
100
101static void oauth2_access_token_done( struct http_request *req )
102{
103        struct oauth2_access_token_data *cb_data = req->data;
104        char *atoken = NULL, *rtoken = NULL;
105        const char *content_type;
106       
107        if( getenv( "BITLBEE_DEBUG" ) && req->reply_body )
108                printf( "%s\n", req->reply_body );
109       
110        content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 );
111       
112        if( req->status_code != 200 )
113        {
114        }
115        else if( content_type && strstr( content_type, "application/json" ) )
116        {
117                json_value *js = json_parse( req->reply_body );
118                if( js && js->type == json_object )
119                {
120                        int i;
121                       
122                        for( i = 0; i < js->u.object.length; i ++ )
123                        {
124                                if( js->u.object.values[i].value->type != json_string )
125                                        continue;
126                                if( strcmp( js->u.object.values[i].name, "access_token" ) == 0 )
127                                        atoken = g_strdup( js->u.object.values[i].value->u.string.ptr );
128                                if( strcmp( js->u.object.values[i].name, "refresh_token" ) == 0 )
129                                        rtoken = g_strdup( js->u.object.values[i].value->u.string.ptr );
130                        }
131                }
132                json_value_free( js );
133        }
134        else
135        {
136                /* Facebook use their own odd format here, seems to be URL-encoded. */
137                GSList *p_in = NULL;
138               
139                oauth_params_parse( &p_in, req->reply_body );
140                atoken = g_strdup( oauth_params_get( &p_in, "access_token" ) );
141                rtoken = g_strdup( oauth_params_get( &p_in, "refresh_token" ) );
142                oauth_params_free( &p_in );
143        }
144        if( getenv( "BITLBEE_DEBUG" ) )
145                printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken );
146       
147        cb_data->func( cb_data->data, atoken, rtoken );
148        g_free( atoken );
149        g_free( rtoken );
150        g_free( cb_data );
151}
Note: See TracBrowser for help on using the repository browser.