Fix memleak when setting proxy property
[profile/ivi/gsignond-plugin-oauth.git] / test / oauth1tests.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012 Intel Corporation.
7  *
8  * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include <check.h>
27 #include <stdlib.h>
28 #include "gsignond-oauth-plugin.h"
29 #include <gsignond/gsignond-session-data.h>
30 #include <gsignond/gsignond-plugin-interface.h>
31 #include <gsignond/gsignond-error.h>
32 #include <gsignond/gsignond-config.h>
33 #include <gsignond/gsignond-utils.h>
34 #include <libsoup/soup.h>
35
36 static void response_callback(GSignondPlugin* plugin, GSignondSessionData* result,
37                      gpointer user_data)
38 {
39     GSignondSessionData** user_data_p = user_data;
40     *user_data_p = result;
41     gsignond_dictionary_ref(result);
42 }
43
44 static void store_callback(GSignondPlugin* plugin, GSignondSessionData* result,
45                      gpointer user_data)
46 {
47     response_callback(plugin, result, user_data);
48 }
49
50 static void user_action_required_callback(GSignondPlugin* plugin, 
51                                           GSignondSignonuiData* ui_request, 
52                                           gpointer user_data)
53 {
54     GSignondSignonuiData** user_data_p = user_data;
55     *user_data_p = ui_request;
56     gsignond_dictionary_ref(ui_request);
57 }
58
59 static void error_callback(GSignondPlugin* plugin, GError* error,
60                      gpointer user_data)
61 {
62     GError** user_data_p = user_data;
63     *user_data_p = g_error_copy(error);
64 }
65
66 static GVariant* make_normal_token()
67 {
68     GSignondDictionary* token = gsignond_dictionary_new();
69     gsignond_dictionary_set_string(token, "AccessToken", "megaaccesstoken");
70     gsignond_dictionary_set_string(token, "TokenSecret", "megatokensecret");
71     gsignond_dictionary_set_string(token, "Realm", "megarealm");
72     GVariant* token_var = gsignond_dictionary_to_variant(token);
73     gsignond_dictionary_unref(token);
74     return token_var;
75 }
76
77 static GVariant* make_no_realm_token()
78 {
79     GSignondDictionary* token = gsignond_dictionary_new();
80     gsignond_dictionary_set_string(token, "AccessToken", "megaaccesstoken");
81     gsignond_dictionary_set_string(token, "TokenSecret", "megatokensecret");
82     GVariant* token_var = gsignond_dictionary_to_variant(token);
83     gsignond_dictionary_unref(token);
84     return token_var;
85 }
86
87 static GSignondDictionary* make_tokens(const gchar* client_id, GVariant* token)
88 {
89     GSignondDictionary* tokens = gsignond_dictionary_new();
90     gsignond_dictionary_set(tokens, client_id, token);
91     return tokens;
92 }
93
94 START_TEST (test_oauth1_request)
95 {
96     gpointer plugin;
97     
98     plugin = g_object_new(GSIGNOND_TYPE_OAUTH_PLUGIN, NULL);
99     fail_if(plugin == NULL);
100
101     GSignondSessionData* result = NULL;
102     GSignondSessionData* store = NULL;
103     GSignondSignonuiData* ui_action = NULL;
104     GError* error = NULL;
105
106     g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result);
107     g_signal_connect(plugin, "user-action-required", 
108                      G_CALLBACK(user_action_required_callback), &ui_action);
109     g_signal_connect(plugin, "store", G_CALLBACK(store_callback), &store);
110     g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
111
112     GSignondSessionData* data = gsignond_dictionary_new();
113     GSignondDictionary* tokens = make_tokens("megaclient", make_normal_token());
114
115     // unknown mechanism
116     gsignond_plugin_request_initial(plugin, data, tokens, "unknown-mech");
117
118     fail_if(result != NULL);    
119     fail_if(ui_action != NULL);
120     fail_if(store != NULL);
121     fail_if(error == NULL);
122     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
123                                 GSIGNOND_ERROR_MECHANISM_NOT_AVAILABLE));
124     g_error_free(error);
125     error = NULL;
126     
127     // empty data
128     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
129
130     fail_if(result != NULL);    
131     fail_if(ui_action != NULL);
132     fail_if(store != NULL);
133     fail_if(error == NULL);
134     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
135                                 GSIGNOND_ERROR_MISSING_DATA));
136     g_error_free(error);
137     error = NULL;
138
139     gsignond_dictionary_set_string(data, "ConsumerKey", "megaclient");
140     
141     // try using normal token without requesting realm
142     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_DEFAULT);
143     gsignond_dictionary_unref(tokens);
144     tokens = make_tokens("megaclient", make_normal_token());
145     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
146     fail_if(result != NULL);    
147     fail_if(ui_action != NULL);
148     fail_if(store != NULL);
149     fail_if(error == NULL);
150     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
151                                 GSIGNOND_ERROR_MISSING_DATA));
152     g_error_free(error);
153     error = NULL;    
154
155     // try using normal token with realm
156     gsignond_dictionary_set_string(data, "Realm", "megarealm");
157     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
158     fail_if(result == NULL);
159     fail_if(g_strcmp0(gsignond_dictionary_get_string(result, "AccessToken"),
160                       "megaaccesstoken") != 0);
161     fail_if(g_strcmp0(gsignond_dictionary_get_string(result, "TokenSecret"),
162                       "megatokensecret") != 0);
163     fail_if(g_strcmp0(gsignond_dictionary_get_string(result, "Realm"),
164                       "megarealm") != 0);
165     gsignond_dictionary_unref(result);
166     result = NULL;
167     fail_if(ui_action != NULL);
168     fail_if(store != NULL);
169     fail_if(error != NULL);
170     
171     //try using no-realm token with realm request
172     gsignond_dictionary_unref(tokens);
173     tokens = make_tokens("megaclient", make_no_realm_token());
174     gsignond_dictionary_set_string(data, "Realm", "megarealm");
175     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
176     fail_if(result != NULL);    
177     fail_if(ui_action != NULL);
178     fail_if(store != NULL);
179     fail_if(error == NULL);
180     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
181                                 GSIGNOND_ERROR_MISSING_DATA));
182     g_error_free(error);
183     error = NULL;
184     
185     //try using no-realm token with no-realm request
186     gsignond_dictionary_remove(data, "Realm");
187     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
188     fail_if(result == NULL);
189     fail_if(g_strcmp0(gsignond_dictionary_get_string(result, "AccessToken"),
190                       "megaaccesstoken") != 0);
191     fail_if(g_strcmp0(gsignond_dictionary_get_string(result, "TokenSecret"),
192                       "megatokensecret") != 0);
193     fail_if(gsignond_dictionary_get(result, "Realm") != NULL);
194     gsignond_dictionary_unref(result);
195     result = NULL;
196     fail_if(ui_action != NULL);
197     fail_if(store != NULL);
198     fail_if(error != NULL);
199
200     //don't reuse token
201     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_REQUEST_PASSWORD);
202     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
203
204     fail_if(result != NULL);    
205     fail_if(ui_action != NULL);
206     fail_if(store != NULL);
207     fail_if(error == NULL);
208     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
209                                 GSIGNOND_ERROR_MISSING_DATA));
210     g_error_free(error);
211     error = NULL;
212
213     gsignond_dictionary_unref(data);
214     gsignond_dictionary_unref(tokens);
215     g_object_unref(plugin);    
216 }
217 END_TEST
218
219 START_TEST (test_oauth1_allowed_realms)
220 {
221     gpointer plugin;
222     
223     plugin = g_object_new(GSIGNOND_TYPE_OAUTH_PLUGIN, NULL);
224     fail_if(plugin == NULL);
225
226     GSignondSessionData* result = NULL;
227     GSignondSessionData* store = NULL;
228     GSignondSignonuiData* ui_action = NULL;
229     GError* error = NULL;
230
231     g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result);
232     g_signal_connect(plugin, "user-action-required", 
233                      G_CALLBACK(user_action_required_callback), &ui_action);
234     g_signal_connect(plugin, "store", G_CALLBACK(store_callback), &store);
235     g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
236
237     GSignondSessionData* data = gsignond_dictionary_new();
238     GSignondDictionary* tokens = make_tokens("someotherclient", make_normal_token());
239     gsignond_dictionary_set_string(data, "ConsumerKey", "megaclient");
240     gsignond_dictionary_set_string(data, "Realm", "megarealm");
241     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_DEFAULT);
242     gsignond_dictionary_set_string(data, "RequestEndpoint", "https://localhost/somepath");    
243     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
244
245     //no allowed realms
246     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
247     fail_if(result != NULL);    
248     fail_if(ui_action != NULL);
249     fail_if(store != NULL);
250     fail_if(error == NULL);
251     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
252                                 GSIGNOND_ERROR_MISSING_DATA));
253     fail_unless(g_strcmp0(error->message, "Missing realm list") == 0);
254     g_error_free(error);
255     error = NULL;
256     
257     //allowed realms is empty
258     const gchar *empty_realm_list[] = { NULL };
259     GSequence *allowed_realms = gsignond_copy_array_to_sequence(empty_realm_list);
260     gsignond_session_data_set_allowed_realms(data, allowed_realms);
261     g_sequence_free(allowed_realms);
262     
263     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
264     fail_if(result != NULL);    
265     fail_if(ui_action != NULL);
266     fail_if(store != NULL);
267     fail_if(error == NULL);
268     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
269                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
270     fail_unless(g_strcmp0(error->message, "Unauthorized host") == 0);
271     g_error_free(error);
272     error = NULL;
273
274     //allowed realms does not contain same domain
275     const gchar *non_realm_list[] = { "somedomain1.com", "somedomain2.com", "somedomain3.com", NULL };
276     allowed_realms = gsignond_copy_array_to_sequence(non_realm_list);
277     gsignond_session_data_set_allowed_realms(data, allowed_realms);
278     g_sequence_free(allowed_realms);
279     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
280     fail_if(result != NULL);    
281     fail_if(ui_action != NULL);
282     fail_if(store != NULL);
283     fail_if(error == NULL);
284     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
285                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
286     fail_unless(g_strcmp0(error->message, "Unauthorized host") == 0);
287     g_error_free(error);
288     error = NULL;
289
290     //allowed realms contains same domain
291     const gchar *realm_list[] = { "otherhost.somedomain.com", "localhost", "thehost.somedomain.com", NULL };
292     allowed_realms = gsignond_copy_array_to_sequence(realm_list);
293     gsignond_session_data_set_allowed_realms(data, allowed_realms);
294     g_sequence_free(allowed_realms);
295     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
296     fail_if(result != NULL);    
297     fail_if(ui_action != NULL);
298     fail_if(store != NULL);
299     fail_if(error == NULL);
300     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
301                                 GSIGNOND_ERROR_MISSING_DATA));
302     fail_unless(g_strcmp0(error->message, "Unknown oauth1 signature method") == 0);
303     g_error_free(error);
304     error = NULL;
305
306     gsignond_dictionary_unref(data);
307     gsignond_dictionary_unref(tokens);
308     g_object_unref(plugin);
309 }
310 END_TEST 
311
312 static void check_nonce(const gchar* nonce)
313 {
314     fail_if(nonce == NULL);
315     fail_if(strlen(nonce) < 20);
316 }
317
318 static void check_timestamp(const gchar* timestamp)
319 {
320     fail_if(timestamp == NULL);
321     fail_if(strlen(timestamp) < 10);
322 }
323
324 static void check_hmac_sha1_signature(const gchar* signature)
325 {
326     gsize sig_len;
327     guchar* signature_decoded = g_base64_decode_inplace(
328                                             soup_uri_decode(signature), &sig_len);
329     
330     fail_if(sig_len != 20);
331    
332     g_free(signature_decoded);
333 }
334
335 static void check_rsa_sha1_signature(const gchar* signature)
336 {
337     gsize sig_len;
338     guchar* signature_decoded = g_base64_decode_inplace(
339                                             soup_uri_decode(signature), &sig_len);
340
341     fail_if(sig_len != 256);
342    
343     g_free(signature_decoded);
344 }
345
346
347 static void
348 temporary_token_server_callback (SoupServer        *server,
349          SoupMessage       *msg, 
350          const char        *path,
351          GHashTable        *query,
352          SoupClientContext *client,
353          gpointer           user_data)
354 {
355     const gchar* normal_token_response = "oauth_token=hh5s93j4hdidpola&\
356 oauth_token_secret=hdhd0244k9j7ao03&oauth_callback_confirmed=true";
357     const gchar* invalid_body_error = "some invalid body";
358
359     fail_if(g_str_has_prefix (path, "/temporarytokenpath") == FALSE);
360     fail_if(g_strcmp0(msg->method, "POST") != 0);
361     const char* authorization = soup_message_headers_get_one(msg->request_headers,
362                                                              "Authorization");
363     fail_if(authorization == NULL);
364     //printf("temporary auth header %s\n", authorization);
365     fail_unless(g_str_has_prefix(authorization, "OAuth "));
366     GHashTable* auth_params = soup_header_parse_param_list (authorization+6);
367     
368     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "realm"), "megarealm") != 0);
369     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_consumer_key"), "megaclient") != 0);
370     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_version"), "1.0") != 0);
371     gchar* oauth_callback = soup_uri_decode(g_hash_table_lookup(auth_params, "oauth_callback"));
372     fail_if(g_strcmp0(oauth_callback, "http://localhost/somegsignondoauthcallback") != 0);
373     g_free(oauth_callback);
374
375     const gchar* signature_method = g_hash_table_lookup(auth_params, "oauth_signature_method");
376     if (g_strcmp0(signature_method, "PLAINTEXT") == 0) {
377         fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_signature"), "megasecret%26") != 0);
378     } else if (g_strcmp0(signature_method, "HMAC-SHA1") == 0) {
379         check_nonce(g_hash_table_lookup(auth_params, "oauth_nonce"));
380         check_timestamp(g_hash_table_lookup(auth_params, "oauth_timestamp"));
381         check_hmac_sha1_signature(g_hash_table_lookup(auth_params, "oauth_signature"));
382     } else if (g_strcmp0(signature_method, "RSA-SHA1") == 0) {
383         check_nonce(g_hash_table_lookup(auth_params, "oauth_nonce"));
384         check_timestamp(g_hash_table_lookup(auth_params, "oauth_timestamp"));
385         check_rsa_sha1_signature(g_hash_table_lookup(auth_params, "oauth_signature"));
386     }
387     
388     soup_header_free_param_list(auth_params);
389
390     if (g_strrstr(path, "error/invalid_body") != NULL) {
391         soup_message_set_status(msg, SOUP_STATUS_OK);
392         soup_message_set_response(msg, "application/x-www-form-urlencoded", 
393                                SOUP_MEMORY_STATIC,
394                                invalid_body_error, strlen(invalid_body_error));
395     } else if (g_strrstr(path, "error") != NULL) {
396         soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST);
397     } else {
398         soup_message_set_status (msg, SOUP_STATUS_OK);
399         soup_message_set_response (msg, "application/x-www-form-urlencoded", 
400                                SOUP_MEMORY_STATIC,
401                                normal_token_response, strlen(normal_token_response));
402     }
403 }
404
405 static void
406 access_token_server_callback (SoupServer        *server,
407          SoupMessage       *msg, 
408          const char        *path,
409          GHashTable        *query,
410          SoupClientContext *client,
411          gpointer           user_data)
412 {
413     const gchar* normal_token_response = "oauth_token=j49ddk933skd9dks\
414 &oauth_token_secret=ll399dj47dskfjdk";
415     const gchar* invalid_body_error = "some invalid body";
416
417     fail_if(g_str_has_prefix (path, "/accesstokenpath") == FALSE);
418     fail_if(g_strcmp0(msg->method, "POST") != 0);
419     const char* authorization = soup_message_headers_get_one(msg->request_headers,
420                                                              "Authorization");
421     fail_if(authorization == NULL);
422     //printf("access auth header %s\n", authorization);
423     fail_unless(g_str_has_prefix(authorization, "OAuth "));
424     GHashTable* auth_params = soup_header_parse_param_list (authorization+6);
425     
426     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "realm"), "megarealm") != 0);
427     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_consumer_key"), "megaclient") != 0);
428     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_version"), "1.0") != 0);
429     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_verifier"), "somerandomverifier") != 0);
430     fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_token"), "hh5s93j4hdidpola") != 0);
431
432     const gchar* signature_method = g_hash_table_lookup(auth_params, "oauth_signature_method");
433     if (g_strcmp0(signature_method, "PLAINTEXT") == 0) {
434         fail_if(g_strcmp0(g_hash_table_lookup(auth_params, "oauth_signature"), "megasecret%26hdhd0244k9j7ao03") != 0);
435     } else if (g_strcmp0(signature_method, "HMAC-SHA1") == 0) {
436         check_nonce(g_hash_table_lookup(auth_params, "oauth_nonce"));
437         check_timestamp(g_hash_table_lookup(auth_params, "oauth_timestamp"));
438         check_hmac_sha1_signature(g_hash_table_lookup(auth_params, "oauth_signature"));
439     } else if (g_strcmp0(signature_method, "RSA-SHA1") == 0) {
440         check_nonce(g_hash_table_lookup(auth_params, "oauth_nonce"));
441         check_timestamp(g_hash_table_lookup(auth_params, "oauth_timestamp"));
442         check_rsa_sha1_signature(g_hash_table_lookup(auth_params, "oauth_signature"));
443     }
444     
445     soup_header_free_param_list(auth_params);
446
447     if (g_strrstr(path, "error/invalid_body") != NULL) {
448         soup_message_set_status(msg, SOUP_STATUS_OK);
449         soup_message_set_response(msg, "application/x-www-form-urlencoded", 
450                                SOUP_MEMORY_STATIC,
451                                invalid_body_error, strlen(invalid_body_error));
452     } else if (g_strrstr(path, "error") != NULL) {
453         soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST);
454     } else {
455         soup_message_set_status (msg, SOUP_STATUS_OK);
456         soup_message_set_response (msg, "application/x-www-form-urlencoded", 
457                                SOUP_MEMORY_STATIC,
458                                normal_token_response, strlen(normal_token_response));
459     }
460 }
461     
462
463 START_TEST (test_oauth1_request_temporary_token)
464 {
465     gpointer plugin;
466     
467     plugin = g_object_new(GSIGNOND_TYPE_OAUTH_PLUGIN, NULL);
468     fail_if(plugin == NULL);
469
470     GSignondSessionData* result = NULL;
471     GSignondSessionData* store = NULL;
472     GSignondSignonuiData* ui_action = NULL;
473     GError* error = NULL;
474
475     g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result);
476     g_signal_connect(plugin, "user-action-required", 
477                      G_CALLBACK(user_action_required_callback), &ui_action);
478     g_signal_connect(plugin, "store", G_CALLBACK(store_callback), &store);
479     g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
480
481     GSignondSessionData* data = gsignond_dictionary_new();
482     GSignondDictionary* tokens = make_tokens("someotherclient", make_normal_token());
483     gsignond_dictionary_set_string(data, "ConsumerKey", "megaclient");
484     gsignond_dictionary_set_string(data, "Realm", "megarealm");
485     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_DEFAULT);
486     
487     //no RequestEndpoint
488     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
489     fail_if(result != NULL);    
490     fail_if(ui_action != NULL);
491     fail_if(store != NULL);
492     fail_if(error == NULL);
493     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
494                                 GSIGNOND_ERROR_MISSING_DATA));
495     g_error_free(error);
496     error = NULL;
497     
498     //RequestEndpoint does not use https
499     gsignond_dictionary_set_string(data, "RequestEndpoint", "http://localhost/somepath");
500     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
501     fail_if(result != NULL);    
502     fail_if(ui_action != NULL);
503     fail_if(store != NULL);
504     fail_if(error == NULL);
505     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
506                                 GSIGNOND_ERROR_MISSING_DATA));
507     fail_unless(g_strcmp0(error->message, "RequestEndpoint must use https") == 0);                                
508     g_error_free(error);
509     error = NULL;
510     
511     //no signature method
512     const gchar *realm_list[] = { "otherhost.somedomain.com", "localhost", "thehost.somedomain.com", NULL };
513     GSequence *allowed_realms = gsignond_copy_array_to_sequence(realm_list);
514     gsignond_session_data_set_allowed_realms(data, allowed_realms);
515     g_sequence_free(allowed_realms);
516     gsignond_dictionary_set_string(data, "RequestEndpoint", "https://localhost/somepath");    
517     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
518     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
519     fail_if(result != NULL);    
520     fail_if(ui_action != NULL);
521     fail_if(store != NULL);
522     fail_if(error == NULL);
523     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
524                                 GSIGNOND_ERROR_MISSING_DATA));
525     fail_unless(g_strcmp0(error->message, "Unknown oauth1 signature method") == 0);
526     g_error_free(error);
527     error = NULL;
528     
529     //unknown signature method
530     gsignond_dictionary_set_string(data, "SignatureMethod", "unknownmethod");    
531     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
532     fail_if(result != NULL);    
533     fail_if(ui_action != NULL);
534     fail_if(store != NULL);
535     fail_if(error == NULL);
536     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
537                                 GSIGNOND_ERROR_MISSING_DATA));
538     fail_unless(g_strcmp0(error->message, "Unknown oauth1 signature method") == 0);
539     g_error_free(error);
540     error = NULL;
541
542     //PLAINTEXT method, but no server
543     gsignond_dictionary_set_string(data, "SignatureMethod", "PLAINTEXT");
544     gsignond_dictionary_set_string(data, "ConsumerSecret", "megasecret");            
545     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
546     fail_if(result != NULL);    
547     fail_if(ui_action != NULL);
548     fail_if(store != NULL);
549     fail_if(error != NULL);
550
551     while (1) {
552         g_main_context_iteration(g_main_context_default(), TRUE);
553         if(error != NULL)
554             break;
555     }
556     fail_if(result != NULL);    
557     fail_if(ui_action != NULL);
558     fail_if(store != NULL);
559     fail_if(error == NULL);
560     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
561                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
562     fail_if(g_str_has_prefix(error->message, 
563                              "Temporary token endpoint returned an error") == FALSE);
564     g_error_free(error);
565     error = NULL;
566
567     //set up the server and try again
568     // to genenerate cert and key
569     // openssl genrsa -out privkey.pem 2048
570     // openssl req -new -x509 -key privkey.pem -out cacert.pem -days 365000
571     SoupServer* server = soup_server_new(SOUP_SERVER_SSL_CERT_FILE, "cacert.pem",
572                                          SOUP_SERVER_SSL_KEY_FILE, "privkey.pem",
573                                          NULL);
574     soup_server_add_handler (server, "/temporarytokenpath", temporary_token_server_callback,
575              NULL, NULL);
576     soup_server_run_async(server);
577     
578     gsignond_dictionary_set_boolean(data, "SslStrict", FALSE);
579     
580     gchar* server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath", soup_server_get_port(server));
581     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
582     g_free(server_uri);
583     gsignond_dictionary_set_string(data, "AuthorizationEndpoint", "https://localhost/authorization");
584
585     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
586     fail_if(result != NULL);    
587     fail_if(ui_action != NULL);
588     fail_if(store != NULL);
589     fail_if(error != NULL);
590
591     while (1) {
592         g_main_context_iteration(g_main_context_default(), TRUE);
593         if(ui_action != NULL)
594             break;
595     }
596     fail_if(result != NULL);    
597     fail_if(ui_action == NULL);
598
599     fail_if(g_strcmp0(gsignond_signonui_data_get_open_url(ui_action),
600                       "https://localhost/authorization?oauth_token=hh5s93j4hdidpola") != 0);
601     fail_if(g_strcmp0(gsignond_signonui_data_get_final_url(ui_action),
602                       "http://localhost/somegsignondoauthcallback") != 0);
603     
604     gsignond_dictionary_unref(ui_action);
605     ui_action = NULL;
606     fail_if(store != NULL);
607     fail_if(error != NULL);    
608
609     //reject the PLAINTEXT request
610     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
611     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
612     server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath/error", soup_server_get_port(server));
613     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
614     g_free(server_uri);
615     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
616     fail_if(result != NULL);    
617     fail_if(ui_action != NULL);
618     fail_if(store != NULL);
619     fail_if(error != NULL);
620
621     while (1) {
622         g_main_context_iteration(g_main_context_default(), TRUE);
623         if(error != NULL)
624             break;
625     }
626     fail_if(result != NULL);    
627     fail_if(ui_action != NULL);
628     fail_if(store != NULL);
629     fail_if(error == NULL);
630     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
631                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
632     fail_if(g_str_has_prefix(error->message, 
633                              "Temporary token endpoint returned an error") == FALSE);
634     g_error_free(error);
635     error = NULL;
636     
637     //provide invalid data for PLAINTEXT request
638     server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath/error/invalid_body", soup_server_get_port(server));
639     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
640     g_free(server_uri);
641     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
642     fail_if(result != NULL);    
643     fail_if(ui_action != NULL);
644     fail_if(store != NULL);
645     fail_if(error != NULL);
646
647     while (1) {
648         g_main_context_iteration(g_main_context_default(), TRUE);
649         if(error != NULL)
650             break;
651     }
652     fail_if(result != NULL);    
653     fail_if(ui_action != NULL);
654     fail_if(store != NULL);
655     fail_if(error == NULL);
656     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
657                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
658     fail_if(g_str_has_prefix(error->message, 
659                              "Temporary token endpoint returned an invalid response") == FALSE);
660     g_error_free(error);
661     error = NULL;
662
663     //HMAC-SHA1 request
664     gsignond_dictionary_set_string(data, "SignatureMethod", "HMAC-SHA1");
665     server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath", soup_server_get_port(server));
666     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
667     g_free(server_uri);
668     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
669     fail_if(result != NULL);    
670     fail_if(ui_action != NULL);
671     fail_if(store != NULL);
672     fail_if(error != NULL);
673
674     while (1) {
675         g_main_context_iteration(g_main_context_default(), TRUE);
676         if(ui_action != NULL)
677             break;
678     }
679     fail_if(result != NULL);    
680     fail_if(ui_action == NULL);
681
682     fail_if(g_strcmp0(gsignond_signonui_data_get_open_url(ui_action),
683                       "https://localhost/authorization?oauth_token=hh5s93j4hdidpola") != 0);
684     fail_if(g_strcmp0(gsignond_signonui_data_get_final_url(ui_action),
685                       "http://localhost/somegsignondoauthcallback") != 0);
686     
687     gsignond_dictionary_unref(ui_action);
688     ui_action = NULL;
689     fail_if(store != NULL);
690     fail_if(error != NULL);    
691     
692     //RSA-SHA1 request with no private key
693     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
694     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
695     gsignond_dictionary_set_string(data, "SignatureMethod", "RSA-SHA1");
696     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
697     fail_if(result != NULL);    
698     fail_if(ui_action != NULL);
699     fail_if(store != NULL);
700     fail_if(error == NULL);
701     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
702                                 GSIGNOND_ERROR_MISSING_DATA));
703     fail_if(g_str_has_prefix(error->message, 
704                              "Client did not supply RSAPrivateKey") == FALSE);
705     g_error_free(error);
706     error = NULL;    
707
708     //RSA-SHA1 request with invalid private key
709     gsignond_dictionary_set_string(data, "RSAPrivateKey", "some bogus key");
710     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
711     fail_if(result != NULL);    
712     fail_if(ui_action != NULL);
713     fail_if(store != NULL);
714     fail_if(error == NULL);
715     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
716                                 GSIGNOND_ERROR_MISSING_DATA));
717     fail_if(g_str_has_prefix(error->message, 
718                              "Invalid RSA private key") == FALSE);
719     g_error_free(error);
720     error = NULL;    
721     
722     //RSA-SHA1 request with valid private key
723     gchar* privkey;
724     fail_unless(g_file_get_contents("privkey.pem", &privkey, NULL, NULL));
725     gsignond_dictionary_set_string(data, "RSAPrivateKey", privkey);
726     g_free(privkey);
727     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
728     fail_if(result != NULL);    
729     fail_if(ui_action != NULL);
730     fail_if(store != NULL);
731     fail_if(error != NULL);
732
733     while (1) {
734         g_main_context_iteration(g_main_context_default(), TRUE);
735         if(ui_action != NULL)
736             break;
737     }
738     fail_if(result != NULL);    
739     fail_if(ui_action == NULL);
740
741     fail_if(g_strcmp0(gsignond_signonui_data_get_open_url(ui_action),
742                       "https://localhost/authorization?oauth_token=hh5s93j4hdidpola") != 0);
743     fail_if(g_strcmp0(gsignond_signonui_data_get_final_url(ui_action),
744                       "http://localhost/somegsignondoauthcallback") != 0);
745     
746     gsignond_dictionary_unref(ui_action);
747     ui_action = NULL;
748     fail_if(store != NULL);
749     fail_if(error != NULL);    
750     
751     gsignond_dictionary_unref(data);
752     gsignond_dictionary_unref(tokens);
753     g_object_unref(plugin);
754     g_object_unref(server);      
755 }
756 END_TEST 
757
758 START_TEST (test_oauth1_ui_request)
759 {
760     gpointer plugin;
761     
762     SoupServer* server = soup_server_new(SOUP_SERVER_SSL_CERT_FILE, "cacert.pem",
763                                          SOUP_SERVER_SSL_KEY_FILE, "privkey.pem",
764                                          NULL);
765     soup_server_add_handler (server, "/temporarytokenpath", temporary_token_server_callback,
766              NULL, NULL);
767     soup_server_run_async(server);
768
769     plugin = g_object_new(GSIGNOND_TYPE_OAUTH_PLUGIN, NULL);
770     fail_if(plugin == NULL);
771
772     GSignondSessionData* result = NULL;
773     GSignondSessionData* store = NULL;
774     GSignondSignonuiData* ui_action = NULL;
775     GError* error = NULL;
776
777     g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result);
778     g_signal_connect(plugin, "user-action-required", 
779                      G_CALLBACK(user_action_required_callback), &ui_action);
780     g_signal_connect(plugin, "store", G_CALLBACK(store_callback), &store);
781     g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
782
783     GSignondSessionData* data = gsignond_dictionary_new();
784     GSignondDictionary* tokens = make_tokens("someotherclient", make_normal_token());
785     GSignondSignonuiData* ui_data = gsignond_dictionary_new();
786
787     gsignond_dictionary_set_string(data, "ConsumerKey", "megaclient");
788     gsignond_dictionary_set_string(data, "Realm", "megarealm");
789     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_DEFAULT);
790     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
791     gsignond_dictionary_set_string(data, "SignatureMethod", "PLAINTEXT");
792     gsignond_dictionary_set_string(data, "ConsumerSecret", "megasecret");            
793     
794     gsignond_dictionary_set_boolean(data, "SslStrict", FALSE);
795     
796     gchar* server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath", soup_server_get_port(server));
797     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
798     g_free(server_uri);
799     gsignond_dictionary_set_string(data, "AuthorizationEndpoint", "https://localhost/authorization");
800
801     const gchar *realm_list[] = { "otherhost.somedomain.com", "localhost", "thehost.somedomain.com", NULL };
802     GSequence *allowed_realms = gsignond_copy_array_to_sequence(realm_list);
803     gsignond_session_data_set_allowed_realms(data, allowed_realms);
804     g_sequence_free(allowed_realms);
805     
806     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
807
808     fail_if(result != NULL);    
809     fail_if(ui_action != NULL);
810     fail_if(store != NULL);
811     fail_if(error != NULL);
812
813     while (1) {
814         g_main_context_iteration(g_main_context_default(), TRUE);
815         if(ui_action != NULL)
816             break;
817     }
818     fail_if(result != NULL);    
819     fail_if(ui_action == NULL);
820     gsignond_dictionary_unref(ui_action);
821     ui_action = NULL;
822     fail_if(store != NULL);
823     fail_if(error != NULL);    
824     
825     //return an empty response
826     gsignond_plugin_user_action_finished(plugin, ui_data);
827     fail_if(result != NULL);    
828     fail_if(ui_action != NULL);
829     fail_if(store != NULL);
830     fail_if(error == NULL);
831     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
832                                 GSIGNOND_ERROR_USER_INTERACTION));
833     fail_if(g_str_has_prefix(error->message, 
834                              "userActionFinished did not return an error value") == FALSE);
835     g_error_free(error);
836     error = NULL;
837     
838     //ui session was cancelled
839     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
840     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
841     gsignond_signonui_data_set_query_error(ui_data, SIGNONUI_ERROR_CANCELED);
842
843     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
844
845     fail_if(result != NULL);    
846     fail_if(ui_action != NULL);
847     fail_if(store != NULL);
848     fail_if(error != NULL);
849
850     while (1) {
851         g_main_context_iteration(g_main_context_default(), TRUE);
852         if(ui_action != NULL)
853             break;
854     }
855     fail_if(result != NULL);    
856     fail_if(ui_action == NULL);
857     gsignond_dictionary_unref(ui_action);
858     ui_action = NULL;
859     fail_if(store != NULL);
860     fail_if(error != NULL);    
861     
862     gsignond_plugin_user_action_finished(plugin, ui_data);
863     fail_if(result != NULL);    
864     fail_if(ui_action != NULL);
865     fail_if(store != NULL);
866     fail_if(error == NULL);
867     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
868                                 GSIGNOND_ERROR_SESSION_CANCELED));
869     fail_if(g_str_has_prefix(error->message, 
870                              "Session canceled") == FALSE);
871     g_error_free(error);
872     error = NULL;
873     
874     //some other ui error
875     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
876     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
877     gsignond_signonui_data_set_query_error(ui_data, SIGNONUI_ERROR_BAD_PARAMETERS);
878
879     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
880
881     fail_if(result != NULL);    
882     fail_if(ui_action != NULL);
883     fail_if(store != NULL);
884     fail_if(error != NULL);
885
886     while (1) {
887         g_main_context_iteration(g_main_context_default(), TRUE);
888         if(ui_action != NULL)
889             break;
890     }
891     fail_if(result != NULL);    
892     fail_if(ui_action == NULL);
893     gsignond_dictionary_unref(ui_action);
894     ui_action = NULL;
895     fail_if(store != NULL);
896     fail_if(error != NULL);    
897     
898     gsignond_plugin_user_action_finished(plugin, ui_data);
899     fail_if(result != NULL);    
900     fail_if(ui_action != NULL);
901     fail_if(store != NULL);
902     fail_if(error == NULL);
903     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
904                                 GSIGNOND_ERROR_USER_INTERACTION));
905     fail_if(g_str_has_prefix(error->message, 
906                              "userActionFinished error:") == FALSE);
907     g_error_free(error);
908     error = NULL;
909     
910     //no error, but no final url
911     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
912     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
913     gsignond_signonui_data_set_query_error(ui_data, SIGNONUI_ERROR_NONE);
914
915     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
916
917     fail_if(result != NULL);    
918     fail_if(ui_action != NULL);
919     fail_if(store != NULL);
920     fail_if(error != NULL);
921
922     while (1) {
923         g_main_context_iteration(g_main_context_default(), TRUE);
924         if(ui_action != NULL)
925             break;
926     }
927     fail_if(result != NULL);    
928     fail_if(ui_action == NULL);
929     gsignond_dictionary_unref(ui_action);
930     ui_action = NULL;
931     fail_if(store != NULL);
932     fail_if(error != NULL);    
933     
934     gsignond_plugin_user_action_finished(plugin, ui_data);
935     fail_if(result != NULL);    
936     fail_if(ui_action != NULL);
937     fail_if(store != NULL);
938     fail_if(error == NULL);
939     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
940                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
941     fail_if(g_str_has_prefix(error->message, 
942                              "Callback URI and URI supplied by UI don't match") == FALSE);
943     g_error_free(error);
944     error = NULL;
945     
946     //final url doesn't match callback url
947     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
948     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
949     gsignond_signonui_data_set_final_url(ui_data, "http://somebogusurl");
950
951     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
952
953     fail_if(result != NULL);    
954     fail_if(ui_action != NULL);
955     fail_if(store != NULL);
956     fail_if(error != NULL);
957
958     while (1) {
959         g_main_context_iteration(g_main_context_default(), TRUE);
960         if(ui_action != NULL)
961             break;
962     }
963     fail_if(result != NULL);    
964     fail_if(ui_action == NULL);
965     gsignond_dictionary_unref(ui_action);
966     ui_action = NULL;
967     fail_if(store != NULL);
968     fail_if(error != NULL);    
969     
970     gsignond_plugin_user_action_finished(plugin, ui_data);
971     fail_if(result != NULL);    
972     fail_if(ui_action != NULL);
973     fail_if(store != NULL);
974     fail_if(error == NULL);
975     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
976                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
977     fail_if(g_str_has_prefix(error->message, 
978                              "Callback URI and URI supplied by UI don't match") == FALSE);
979     g_error_free(error);
980     error = NULL;
981     
982     //correct final url, but no query
983     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
984     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
985     gsignond_signonui_data_set_url_response(ui_data, "http://localhost/somegsignondoauthcallback");
986
987     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
988
989     fail_if(result != NULL);    
990     fail_if(ui_action != NULL);
991     fail_if(store != NULL);
992     fail_if(error != NULL);
993
994     while (1) {
995         g_main_context_iteration(g_main_context_default(), TRUE);
996         if(ui_action != NULL)
997             break;
998     }
999     fail_if(result != NULL);    
1000     fail_if(ui_action == NULL);
1001     gsignond_dictionary_unref(ui_action);
1002     ui_action = NULL;
1003     fail_if(store != NULL);
1004     fail_if(error != NULL);    
1005     
1006     gsignond_plugin_user_action_finished(plugin, ui_data);
1007     fail_if(result != NULL);    
1008     fail_if(ui_action != NULL);
1009     fail_if(store != NULL);
1010     fail_if(error == NULL);
1011     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1012                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
1013     fail_if(g_str_has_prefix(error->message, 
1014                              "No query in returned redirect URI") == FALSE);
1015     g_error_free(error);
1016     error = NULL;
1017     
1018     //correct final url, with bogus token
1019     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1020     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1021     gsignond_signonui_data_set_url_response(ui_data, "http://localhost/somegsignondoauthcallback?oauth_token=somebogustoken");
1022
1023     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1024
1025     fail_if(result != NULL);    
1026     fail_if(ui_action != NULL);
1027     fail_if(store != NULL);
1028     fail_if(error != NULL);
1029
1030     while (1) {
1031         g_main_context_iteration(g_main_context_default(), TRUE);
1032         if(ui_action != NULL)
1033             break;
1034     }
1035     fail_if(result != NULL);    
1036     fail_if(ui_action == NULL);
1037     gsignond_dictionary_unref(ui_action);
1038     ui_action = NULL;
1039     fail_if(store != NULL);
1040     fail_if(error != NULL);    
1041     
1042     gsignond_plugin_user_action_finished(plugin, ui_data);
1043     fail_if(result != NULL);    
1044     fail_if(ui_action != NULL);
1045     fail_if(store != NULL);
1046     fail_if(error == NULL);
1047     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1048                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
1049     fail_if(g_str_has_prefix(error->message, 
1050                              "Token returned by callback URI and temporary token don't match") == FALSE);
1051     g_error_free(error);
1052     error = NULL;
1053     
1054     //correct final url, correct token, absent verifier
1055     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1056     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1057     gsignond_signonui_data_set_url_response(ui_data, "http://localhost/somegsignondoauthcallback?oauth_token=hh5s93j4hdidpola");
1058
1059     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1060
1061     fail_if(result != NULL);    
1062     fail_if(ui_action != NULL);
1063     fail_if(store != NULL);
1064     fail_if(error != NULL);
1065
1066     while (1) {
1067         g_main_context_iteration(g_main_context_default(), TRUE);
1068         if(ui_action != NULL)
1069             break;
1070     }
1071     fail_if(result != NULL);    
1072     fail_if(ui_action == NULL);
1073     gsignond_dictionary_unref(ui_action);
1074     ui_action = NULL;
1075     fail_if(store != NULL);
1076     fail_if(error != NULL);    
1077     
1078     gsignond_plugin_user_action_finished(plugin, ui_data);
1079     fail_if(result != NULL);    
1080     fail_if(ui_action != NULL);
1081     fail_if(store != NULL);
1082     fail_if(error == NULL);
1083     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1084                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
1085     fail_if(g_str_has_prefix(error->message, 
1086                              "No oauth_verifier in callback URI") == FALSE);
1087     g_error_free(error);
1088     error = NULL;
1089     
1090     //correct final url, correct token, correct verifier
1091     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1092     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1093     gsignond_signonui_data_set_url_response(ui_data, "http://localhost/somegsignondoauthcallback?oauth_token=hh5s93j4hdidpola&oauth_verifier=somerandomverifier");
1094
1095     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1096
1097     fail_if(result != NULL);    
1098     fail_if(ui_action != NULL);
1099     fail_if(store != NULL);
1100     fail_if(error != NULL);
1101
1102     while (1) {
1103         g_main_context_iteration(g_main_context_default(), TRUE);
1104         if(ui_action != NULL)
1105             break;
1106     }
1107     fail_if(result != NULL);    
1108     fail_if(ui_action == NULL);
1109     gsignond_dictionary_unref(ui_action);
1110     ui_action = NULL;
1111     fail_if(store != NULL);
1112     fail_if(error != NULL);    
1113     
1114     gsignond_plugin_user_action_finished(plugin, ui_data);
1115     fail_if(result != NULL);    
1116     fail_if(ui_action != NULL);
1117     fail_if(store != NULL);
1118     fail_if(error == NULL);
1119     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1120                                 GSIGNOND_ERROR_MISSING_DATA));
1121     fail_if(g_str_has_prefix(error->message, 
1122                              "Client did not supply TokenEndpoint") == FALSE);
1123     g_error_free(error);
1124     error = NULL;
1125     
1126     gsignond_dictionary_unref(data);
1127     gsignond_dictionary_unref(tokens);
1128     gsignond_dictionary_unref(ui_data);
1129     g_object_unref(plugin);
1130     g_object_unref(server);      
1131 }
1132 END_TEST
1133
1134 START_TEST (test_oauth1_request_access_token)
1135 {
1136     gpointer plugin;
1137     
1138     SoupServer* server = soup_server_new(SOUP_SERVER_SSL_CERT_FILE, "cacert.pem",
1139                                          SOUP_SERVER_SSL_KEY_FILE, "privkey.pem",
1140                                          NULL);
1141     soup_server_add_handler (server, "/temporarytokenpath", temporary_token_server_callback,
1142              NULL, NULL);
1143     soup_server_add_handler (server, "/accesstokenpath", access_token_server_callback,
1144              NULL, NULL);
1145     soup_server_run_async(server);
1146
1147     plugin = g_object_new(GSIGNOND_TYPE_OAUTH_PLUGIN, NULL);
1148     fail_if(plugin == NULL);
1149
1150     GSignondSessionData* result = NULL;
1151     GSignondSessionData* store = NULL;
1152     GSignondSignonuiData* ui_action = NULL;
1153     GError* error = NULL;
1154
1155     g_signal_connect(plugin, "response-final", G_CALLBACK(response_callback), &result);
1156     g_signal_connect(plugin, "user-action-required", 
1157                      G_CALLBACK(user_action_required_callback), &ui_action);
1158     g_signal_connect(plugin, "store", G_CALLBACK(store_callback), &store);
1159     g_signal_connect(plugin, "error", G_CALLBACK(error_callback), &error);
1160
1161     GSignondSessionData* data = gsignond_dictionary_new();
1162     GSignondDictionary* tokens = make_tokens("someotherclient", make_normal_token());
1163     GSignondSignonuiData* ui_data = gsignond_dictionary_new();
1164
1165     gsignond_dictionary_set_string(data, "ConsumerKey", "megaclient");
1166     gsignond_dictionary_set_string(data, "Realm", "megarealm");
1167     gsignond_session_data_set_ui_policy(data, GSIGNOND_UI_POLICY_DEFAULT);
1168     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1169     gsignond_dictionary_set_string(data, "SignatureMethod", "PLAINTEXT");
1170     gsignond_dictionary_set_string(data, "ConsumerSecret", "megasecret");            
1171     
1172     gsignond_dictionary_set_boolean(data, "SslStrict", FALSE);
1173     
1174     gchar* server_uri = g_strdup_printf("https://localhost:%d/temporarytokenpath", soup_server_get_port(server));
1175     gsignond_dictionary_set_string(data, "RequestEndpoint", server_uri);
1176     g_free(server_uri);
1177     gsignond_dictionary_set_string(data, "AuthorizationEndpoint", "https://localhost/authorization");
1178     gsignond_signonui_data_set_url_response(ui_data, "http://localhost/somegsignondoauthcallback?oauth_token=hh5s93j4hdidpola&oauth_verifier=somerandomverifier");
1179     gsignond_signonui_data_set_query_error(ui_data, SIGNONUI_ERROR_NONE);
1180
1181     const gchar *realm_list[] = { "otherhost.somedomain.com", "localhost", "thehost.somedomain.com", NULL };
1182     GSequence *allowed_realms = gsignond_copy_array_to_sequence(realm_list);
1183     gsignond_session_data_set_allowed_realms(data, allowed_realms);
1184     g_sequence_free(allowed_realms);
1185     
1186     //bogus token endpoint
1187     gsignond_dictionary_set_string(data, "TokenEndpoint", "some bogus endpoint");
1188     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1189
1190     fail_if(result != NULL);    
1191     fail_if(ui_action != NULL);
1192     fail_if(store != NULL);
1193     fail_if(error != NULL);
1194
1195     while (1) {
1196         g_main_context_iteration(g_main_context_default(), TRUE);
1197         if(ui_action != NULL)
1198             break;
1199     }
1200     fail_if(result != NULL);    
1201     fail_if(ui_action == NULL);
1202     gsignond_dictionary_unref(ui_action);
1203     ui_action = NULL;
1204     fail_if(store != NULL);
1205     fail_if(error != NULL);
1206
1207     gsignond_plugin_user_action_finished(plugin, ui_data);
1208     fail_if(result != NULL);    
1209     fail_if(ui_action != NULL);
1210     fail_if(store != NULL);
1211     fail_if(error == NULL);
1212     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1213                                 GSIGNOND_ERROR_MISSING_DATA));
1214     fail_if(g_str_has_prefix(error->message, 
1215                              "Client did not supply a valid TokenEndpoint") == FALSE);
1216     g_error_free(error);
1217     error = NULL;
1218     
1219     //token endpoint that doesn't use https
1220     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1221     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1222     gsignond_dictionary_remove(data, "_OauthVerifier");
1223     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1224     
1225     gsignond_dictionary_set_string(data, "TokenEndpoint", "http://somehost");
1226     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1227
1228     fail_if(result != NULL);    
1229     fail_if(ui_action != NULL);
1230     fail_if(store != NULL);
1231     fail_if(error != NULL);
1232     while (1) {
1233         g_main_context_iteration(g_main_context_default(), TRUE);
1234         if(ui_action != NULL)
1235             break;
1236     }
1237     fail_if(result != NULL);    
1238     fail_if(ui_action == NULL);
1239     gsignond_dictionary_unref(ui_action);
1240     ui_action = NULL;
1241     fail_if(store != NULL);
1242     fail_if(error != NULL);
1243
1244     gsignond_plugin_user_action_finished(plugin, ui_data);
1245     fail_if(result != NULL);    
1246     fail_if(ui_action != NULL);
1247     fail_if(store != NULL);
1248     fail_if(error == NULL);
1249     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1250                                 GSIGNOND_ERROR_MISSING_DATA));
1251     fail_if(g_str_has_prefix(error->message, 
1252                              "TokenEndpoint must use https") == FALSE);
1253     g_error_free(error);
1254     error = NULL;
1255     
1256     //token endpoint returned an error
1257     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1258     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1259     gsignond_dictionary_remove(data, "_OauthVerifier");
1260     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1261
1262     server_uri = g_strdup_printf("https://localhost:%d/accesstokenpath/error", soup_server_get_port(server));
1263     gsignond_dictionary_set_string(data, "TokenEndpoint", server_uri);
1264     g_free(server_uri);
1265
1266     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1267
1268     fail_if(result != NULL);    
1269     fail_if(ui_action != NULL);
1270     fail_if(store != NULL);
1271     fail_if(error != NULL);
1272     while (1) {
1273         g_main_context_iteration(g_main_context_default(), TRUE);
1274         if(ui_action != NULL)
1275             break;
1276     }
1277     fail_if(result != NULL);    
1278     fail_if(ui_action == NULL);
1279     gsignond_dictionary_unref(ui_action);
1280     ui_action = NULL;
1281     fail_if(store != NULL);
1282     fail_if(error != NULL);
1283
1284     gsignond_plugin_user_action_finished(plugin, ui_data);
1285     fail_if(result != NULL);    
1286     fail_if(ui_action != NULL);
1287     fail_if(store != NULL);
1288     fail_if(error != NULL);
1289     while (1) {
1290         g_main_context_iteration(g_main_context_default(), TRUE);
1291         if(error != NULL)
1292             break;
1293     }
1294     fail_if(result != NULL);    
1295     fail_if(ui_action != NULL);
1296     fail_if(store != NULL);
1297     fail_if(error == NULL);
1298     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1299                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
1300     fail_if(g_str_has_prefix(error->message, 
1301                              "Access token endpoint returned an error") == FALSE);
1302     g_error_free(error);
1303     error = NULL;
1304     
1305     //token endpoint returned a bogus response
1306     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1307     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1308     gsignond_dictionary_remove(data, "_OauthVerifier");
1309     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1310
1311     server_uri = g_strdup_printf("https://localhost:%d/accesstokenpath/error/invalid_body", soup_server_get_port(server));
1312     gsignond_dictionary_set_string(data, "TokenEndpoint", server_uri);
1313     g_free(server_uri);
1314
1315     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1316
1317     fail_if(result != NULL);    
1318     fail_if(ui_action != NULL);
1319     fail_if(store != NULL);
1320     fail_if(error != NULL);
1321     while (1) {
1322         g_main_context_iteration(g_main_context_default(), TRUE);
1323         if(ui_action != NULL)
1324             break;
1325     }
1326     fail_if(result != NULL);    
1327     fail_if(ui_action == NULL);
1328     gsignond_dictionary_unref(ui_action);
1329     ui_action = NULL;
1330     fail_if(store != NULL);
1331     fail_if(error != NULL);
1332
1333     gsignond_plugin_user_action_finished(plugin, ui_data);
1334     fail_if(result != NULL);    
1335     fail_if(ui_action != NULL);
1336     fail_if(store != NULL);
1337     fail_if(error != NULL);
1338     while (1) {
1339         g_main_context_iteration(g_main_context_default(), TRUE);
1340         if(error != NULL)
1341             break;
1342     }
1343     fail_if(result != NULL);    
1344     fail_if(ui_action != NULL);
1345     fail_if(store != NULL);
1346     fail_if(error == NULL);
1347     fail_unless(g_error_matches(error, GSIGNOND_ERROR, 
1348                                 GSIGNOND_ERROR_NOT_AUTHORIZED));
1349     fail_if(g_str_has_prefix(error->message, 
1350                              "Access token endpoint returned an invalid response") == FALSE);
1351     g_error_free(error);
1352     error = NULL;
1353
1354     //token endpoint returned a valid response for PLAINTEXT
1355     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1356     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1357     gsignond_dictionary_remove(data, "_OauthVerifier");
1358     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1359
1360     server_uri = g_strdup_printf("https://localhost:%d/accesstokenpath", soup_server_get_port(server));
1361     gsignond_dictionary_set_string(data, "TokenEndpoint", server_uri);
1362     g_free(server_uri);
1363
1364     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1365
1366     fail_if(result != NULL);    
1367     fail_if(ui_action != NULL);
1368     fail_if(store != NULL);
1369     fail_if(error != NULL);
1370     while (1) {
1371         g_main_context_iteration(g_main_context_default(), TRUE);
1372         if(ui_action != NULL)
1373             break;
1374     }
1375     fail_if(result != NULL);    
1376     fail_if(ui_action == NULL);
1377     gsignond_dictionary_unref(ui_action);
1378     ui_action = NULL;
1379     fail_if(store != NULL);
1380     fail_if(error != NULL);
1381
1382     gsignond_plugin_user_action_finished(plugin, ui_data);
1383     fail_if(result != NULL);    
1384     fail_if(ui_action != NULL);
1385     fail_if(store != NULL);
1386     fail_if(error != NULL);
1387     while (1) {
1388         g_main_context_iteration(g_main_context_default(), TRUE);
1389         if(result != NULL)
1390             break;
1391     }
1392     fail_if(result == NULL);
1393     const gchar* realm = gsignond_dictionary_get_string(result, "Realm");
1394     const gchar* token_s = gsignond_dictionary_get_string(result, "AccessToken");
1395     const gchar* secret = gsignond_dictionary_get_string(result, "TokenSecret");
1396     fail_if(g_strcmp0(realm, "megarealm") != 0);
1397     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1398     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1399     gsignond_dictionary_unref(result);
1400     result = NULL;
1401     fail_if(ui_action != NULL);
1402     fail_if(store == NULL);
1403
1404     fail_if(g_hash_table_size(store) != 2);
1405     GSignondDictionary* token = gsignond_dictionary_new_from_variant(
1406         gsignond_dictionary_get(store, "megaclient"));
1407     fail_if(token == NULL);
1408     realm = gsignond_dictionary_get_string(token, "Realm");
1409     token_s = gsignond_dictionary_get_string(token, "AccessToken");
1410     secret = gsignond_dictionary_get_string(token, "TokenSecret");
1411     fail_if(g_strcmp0(realm, "megarealm") != 0);
1412     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1413     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1414     gsignond_dictionary_unref(token);
1415     
1416     gsignond_dictionary_unref(store);
1417     store = NULL;
1418     fail_if(error != NULL);
1419     
1420     // valid response for HMAC-SHA1
1421     gsignond_dictionary_remove(tokens, "megaclient");
1422     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1423     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1424     gsignond_dictionary_remove(data, "_OauthVerifier");
1425     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1426     
1427     gsignond_dictionary_set_string(data, "SignatureMethod", "HMAC-SHA1");
1428
1429     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1430
1431     fail_if(result != NULL);    
1432     fail_if(ui_action != NULL);
1433     fail_if(store != NULL);
1434     fail_if(error != NULL);
1435     while (1) {
1436         g_main_context_iteration(g_main_context_default(), TRUE);
1437         if(ui_action != NULL)
1438             break;
1439     }
1440     fail_if(result != NULL);    
1441     fail_if(ui_action == NULL);
1442     gsignond_dictionary_unref(ui_action);
1443     ui_action = NULL;
1444     fail_if(store != NULL);
1445     fail_if(error != NULL);
1446
1447     gsignond_plugin_user_action_finished(plugin, ui_data);
1448     fail_if(result != NULL);    
1449     fail_if(ui_action != NULL);
1450     fail_if(store != NULL);
1451     fail_if(error != NULL);
1452     while (1) {
1453         g_main_context_iteration(g_main_context_default(), TRUE);
1454         if(result != NULL)
1455             break;
1456     }
1457     fail_if(result == NULL);
1458     realm = gsignond_dictionary_get_string(result, "Realm");
1459     token_s = gsignond_dictionary_get_string(result, "AccessToken");
1460     secret = gsignond_dictionary_get_string(result, "TokenSecret");
1461     fail_if(g_strcmp0(realm, "megarealm") != 0);
1462     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1463     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1464     gsignond_dictionary_unref(result);
1465     result = NULL;
1466     fail_if(ui_action != NULL);
1467     fail_if(store == NULL);
1468
1469     fail_if(g_hash_table_size(store) != 2);
1470     token = gsignond_dictionary_new_from_variant(
1471         gsignond_dictionary_get(store, "megaclient"));
1472     fail_if(token == NULL);
1473     realm = gsignond_dictionary_get_string(token, "Realm");
1474     token_s = gsignond_dictionary_get_string(token, "AccessToken");
1475     secret = gsignond_dictionary_get_string(token, "TokenSecret");
1476     fail_if(g_strcmp0(realm, "megarealm") != 0);
1477     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1478     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1479     gsignond_dictionary_unref(token);
1480     
1481     gsignond_dictionary_unref(store);
1482     store = NULL;
1483     fail_if(error != NULL);
1484     
1485     // valid response for RSA-SHA1
1486     gsignond_dictionary_remove(tokens, "megaclient");    
1487     gsignond_dictionary_remove(data, "_OauthTemporaryToken");
1488     gsignond_dictionary_remove(data, "_OauthTemporaryTokenSecret");
1489     gsignond_dictionary_remove(data, "_OauthVerifier");
1490     gsignond_dictionary_set_string(data, "Callback", "http://localhost/somegsignondoauthcallback");
1491     
1492     gsignond_dictionary_set_string(data, "SignatureMethod", "RSA-SHA1");
1493     gchar* privkey;
1494     fail_unless(g_file_get_contents("privkey.pem", &privkey, NULL, NULL));
1495     gsignond_dictionary_set_string(data, "RSAPrivateKey", privkey);
1496     g_free(privkey);
1497
1498     gsignond_plugin_request_initial(plugin, data, tokens, "oauth1");
1499
1500     fail_if(result != NULL);    
1501     fail_if(ui_action != NULL);
1502     fail_if(store != NULL);
1503     fail_if(error != NULL);
1504     while (1) {
1505         g_main_context_iteration(g_main_context_default(), TRUE);
1506         if(ui_action != NULL)
1507             break;
1508     }
1509     fail_if(result != NULL);    
1510     fail_if(ui_action == NULL);
1511     gsignond_dictionary_unref(ui_action);
1512     ui_action = NULL;
1513     fail_if(store != NULL);
1514     fail_if(error != NULL);
1515
1516     gsignond_plugin_user_action_finished(plugin, ui_data);
1517     fail_if(result != NULL);    
1518     fail_if(ui_action != NULL);
1519     fail_if(store != NULL);
1520     fail_if(error != NULL);
1521     while (1) {
1522         g_main_context_iteration(g_main_context_default(), TRUE);
1523         if(result != NULL)
1524             break;
1525     }
1526     fail_if(result == NULL);
1527     realm = gsignond_dictionary_get_string(result, "Realm");
1528     token_s = gsignond_dictionary_get_string(result, "AccessToken");
1529     secret = gsignond_dictionary_get_string(result, "TokenSecret");
1530     fail_if(g_strcmp0(realm, "megarealm") != 0);
1531     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1532     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1533     gsignond_dictionary_unref(result);
1534     result = NULL;
1535     fail_if(ui_action != NULL);
1536     fail_if(store == NULL);
1537
1538     fail_if(g_hash_table_size(store) != 2);
1539     token = gsignond_dictionary_new_from_variant(
1540         gsignond_dictionary_get(store, "megaclient"));
1541     fail_if(token == NULL);
1542     realm = gsignond_dictionary_get_string(token, "Realm");
1543     token_s = gsignond_dictionary_get_string(token, "AccessToken");
1544     secret = gsignond_dictionary_get_string(token, "TokenSecret");
1545     fail_if(g_strcmp0(realm, "megarealm") != 0);
1546     fail_if(g_strcmp0(token_s, "j49ddk933skd9dks") != 0);
1547     fail_if(g_strcmp0(secret, "ll399dj47dskfjdk") != 0);
1548     gsignond_dictionary_unref(token);
1549     
1550     gsignond_dictionary_unref(store);
1551     store = NULL;
1552     fail_if(error != NULL);
1553    
1554     
1555     gsignond_dictionary_unref(data);
1556     gsignond_dictionary_unref(tokens);
1557     gsignond_dictionary_unref(ui_data);
1558     g_object_unref(plugin);
1559     g_object_unref(server);      
1560 }
1561 END_TEST
1562     
1563     
1564
1565 void add_oauth1_tcase(Suite *s)
1566 {
1567     TCase *tc_oauth2 = tcase_create ("OAuth 1 tests");
1568     tcase_add_test (tc_oauth2, test_oauth1_request);
1569     tcase_add_test (tc_oauth2, test_oauth1_allowed_realms);
1570     tcase_add_test (tc_oauth2, test_oauth1_request_temporary_token);
1571     tcase_add_test (tc_oauth2, test_oauth1_ui_request);
1572     tcase_add_test (tc_oauth2, test_oauth1_request_access_token);
1573     suite_add_tcase (s, tc_oauth2);
1574 }