diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-18 22:56:44 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-18 22:56:44 +0100 |
commit | 64b663524a465efb7707a2c634be97b9fb6f963b (patch) | |
tree | d9f7aea9f8e75a4f00de06a1965eaad16581cd2f | |
parent | 18c6d369d777a1d38ef450f868c22de1d0ebba2d (diff) |
Restructured and updated code a little bit to support new-style (much better
and "proper" OAuth2) Facebook OAuth support. (And, add wl.offline scope to get
tokens that don't expire after an hour.)
-rw-r--r-- | protocols/jabber/jabber.c | 23 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 1 | ||||
-rw-r--r-- | protocols/jabber/sasl.c | 47 |
3 files changed, 39 insertions, 32 deletions
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index bf849e2a..50ee6f2d 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -151,16 +151,27 @@ static void jabber_login( account_t *acc ) else jd->oauth2_service = &oauth2_service_google; - /* For the first login with OAuth, we have to authenticate via the browser. - For subsequent logins, exchange the refresh token for a valid access - token (even though the last one maybe didn't expire yet). */ - if( strncmp( acc->pass, "refresh_token=", 14 ) != 0 ) + /* First see if we have a refresh token, in which case any + access token we *might* have has probably expired already + anyway. */ + if( strstr( acc->pass, "refresh_token=" ) ) + { + sasl_oauth2_refresh( ic, acc->pass + 14 ); + } + /* If we don't have a refresh token, let's hope the access + token is still usable. */ + else if( strstr( acc->pass, "access_token=" ) ) + { + sasl_oauth2_load_access_token( ic ); + jabber_connect( ic ); + } + /* If we don't have any, start the OAuth process now. Don't + even open an XMPP connection yet. */ + else { sasl_oauth2_init( ic ); ic->flags |= OPT_SLOW_LOGIN; } - else - sasl_oauth2_refresh( ic, acc->pass + 14 ); } else jabber_connect( ic ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 0a46633e..57f01695 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -326,6 +326,7 @@ gboolean sasl_supported( struct im_connection *ic ); void sasl_oauth2_init( struct im_connection *ic ); int sasl_oauth2_get_refresh_token( struct im_connection *ic, const char *msg ); int sasl_oauth2_refresh( struct im_connection *ic, const char *refresh_token ); +int sasl_oauth2_load_access_token( struct im_connection *ic ); extern const struct oauth2_service oauth2_service_google; extern const struct oauth2_service oauth2_service_facebook; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 89ab1337..622bff74 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -51,7 +51,7 @@ const struct oauth2_service oauth2_service_mslive = "https://oauth.live.com/authorize", "https://oauth.live.com/token", "http://www.bitlbee.org/main.php/Messenger/oauth2.html", - "wl.messenger", + "wl.offline_access%20wl.messenger", "000000004C06FCD1", "IRKlBPzJJAWcY-TbZjiTEJu9tn7XCFaV", }; @@ -87,13 +87,13 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) { if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) sup_plain = 1; - if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) + else if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) sup_digest = 1; - if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 ) + else if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 ) sup_gtalk = 1; - if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 ) + else if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 ) sup_fb = 1; - if( c->text && g_strcasecmp( c->text, "X-MESSENGER-OAUTH2" ) == 0 ) + else if( c->text && g_strcasecmp( c->text, "X-MESSENGER-OAUTH2" ) == 0 ) sup_ms = 1; c = c->next; @@ -134,7 +134,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) reply->text = g_strdup( jd->oauth2_access_token ); reply->text_len = strlen( jd->oauth2_access_token ); } - else if( sup_fb && want_oauth && strstr( ic->acc->pass, "session_key=" ) ) + else if( sup_fb && want_oauth ) { xt_add_attr( reply, "mechanism", "X-FACEBOOK-PLATFORM" ); jd->flags |= JFLAG_SASL_FB; @@ -291,40 +291,23 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) Mechanism is described on http://developers.facebook.com/docs/chat/ and in their Python module. It's all mostly useless because the tokens expire after 24h. */ - GSList *p_in = NULL, *p_out = NULL, *p; - md5_state_t md5; - char time[33], *token; - const char *secret; + GSList *p_in = NULL, *p_out = NULL; + char time[33]; oauth_params_parse( &p_in, dec ); oauth_params_add( &p_out, "nonce", oauth_params_get( &p_in, "nonce" ) ); oauth_params_add( &p_out, "method", oauth_params_get( &p_in, "method" ) ); oauth_params_free( &p_in ); - token = g_strdup( ic->acc->pass ); - oauth_params_parse( &p_in, token ); - g_free( token ); - oauth_params_add( &p_out, "session_key", oauth_params_get( &p_in, "session_key" ) ); - g_snprintf( time, sizeof( time ), "%lld", (long long) ( gettime() * 1000 ) ); oauth_params_add( &p_out, "call_id", time ); oauth_params_add( &p_out, "api_key", oauth2_service_facebook.consumer_key ); oauth_params_add( &p_out, "v", "1.0" ); oauth_params_add( &p_out, "format", "XML" ); - - md5_init( &md5 ); - for( p = p_out; p; p = p->next ) - md5_append( &md5, p->data, strlen( p->data ) ); - - secret = oauth_params_get( &p_in, "secret" ); - if( secret ) - md5_append( &md5, (unsigned char*) secret, strlen( secret ) ); - md5_finish_ascii( &md5, time ); - oauth_params_add( &p_out, "sig", time ); + oauth_params_add( &p_out, "access_token", jd->oauth2_access_token ); reply = oauth_params_string( p_out ); oauth_params_free( &p_out ); - oauth_params_free( &p_in ); } else if( !( s = sasl_get_part( dec, "rspauth" ) ) ) { @@ -520,6 +503,18 @@ int sasl_oauth2_refresh( struct im_connection *ic, const char *refresh_token ) refresh_token, sasl_oauth2_got_token, ic ); } +int sasl_oauth2_load_access_token( struct im_connection *ic ) +{ + struct jabber_data *jd = ic->proto_data; + GSList *p_in = NULL; + + oauth_params_parse( &p_in, ic->acc->pass ); + jd->oauth2_access_token = g_strdup( oauth_params_get( &p_in, "access_token" ) ); + oauth_params_free( &p_in ); + + return jd->oauth2_access_token != NULL; +} + static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token ) { struct im_connection *ic = data; |