]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-oauth2: Fail request if response has error
authorAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 20 Sep 2023 10:52:46 +0000 (13:52 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 26 Sep 2023 11:45:11 +0000 (11:45 +0000)
src/lib-oauth2/oauth2-request.c
src/lib-oauth2/test-oauth2-json.c

index 01f140df3b6983c0e95cdacbd01167c0b35371d7..462e828b01712e0c0f5e7473299f5bcefae548bd 100644 (file)
@@ -78,6 +78,11 @@ oauth2_request_continue(struct oauth2_request *req, const char *error)
        oauth2_request_callback(req, &res);
 }
 
+static int request_field_cmp(const char *key, const struct oauth2_field *field)
+{
+       return strcmp(key, field->name);
+}
+
 void oauth2_request_parse_json(struct oauth2_request *req)
 {
        enum json_type type;
@@ -126,6 +131,19 @@ void oauth2_request_parse_json(struct oauth2_request *req)
 
        i_stream_unref(&req->is);
 
+       /* check if fields contain error now */
+       const struct oauth2_field *error_field =
+               array_lsearch(&req->fields, "error", request_field_cmp);
+       if (error_field != NULL) {
+               /* seems it failed, though */
+               error = error_field->value;
+               /* check for detailed error */
+               error_field = array_lsearch(&req->fields, "error_description",
+                                           request_field_cmp);
+               if (error_field != NULL)
+                       error = error_field->value;
+       }
+
        req->json_parsed_cb(req, error);
 }
 
index 87caedcb284ee5d37eca8ae1f1db90fae572125d..3a2ca1788f01cf823a17b724b468680e46c96c70 100644 (file)
@@ -94,10 +94,72 @@ static void test_oauth2_json_valid(void)
        test_end();
 }
 
+static void
+test_oauth_json_has_error(struct oauth2_request *req,
+                         const char *error)
+{
+       const char *expected_error = req->req_context;
+       test_assert(error != NULL);
+       test_assert_strcmp(expected_error, error);
+}
+
+static void test_oauth2_json_error(void)
+{
+       test_begin("oauth2 json error");
+
+       const char *test_input_1 =
+"{\"error\":\"invalid_request\"}";
+       const char *test_input_2 =
+"{\"error\":\"invalid_request\",\"error_description\":\"Access denied\"}";
+
+       /* Create mock request */
+       pool_t pool = pool_alloconly_create_clean("oauth2 json test", 1024);
+       struct oauth2_request *req = p_new(pool, struct oauth2_request, 1);
+       req->pool = pool;
+       p_array_init(&req->fields, req->pool, 1);
+       req->is = test_istream_create_data(test_input_1, strlen(test_input_1));
+       req->parser = json_parser_init(req->is);
+       req->req_context = "invalid_request";
+       req->json_parsed_cb = test_oauth_json_has_error;
+
+       /* Parse the JSON response */
+       for (size_t pos = 0; pos <= strlen(test_input_1); pos +=2) {
+               test_istream_set_size(req->is, pos);
+               oauth2_request_parse_json(req);
+               if (req->is == NULL)
+                       break;
+       }
+
+                       
+       pool_unref(&pool);
+
+       pool = pool_alloconly_create_clean("oauth2 json test", 1024);
+       req = p_new(pool, struct oauth2_request, 1);
+       req->pool = pool;
+       p_array_init(&req->fields, req->pool, 1);
+       req->is = test_istream_create_data(test_input_2, strlen(test_input_2));
+       req->parser = json_parser_init(req->is);
+       req->req_context = "Access denied";
+       req->json_parsed_cb = test_oauth_json_has_error;
+
+       /* Parse the JSON response */
+       for (size_t pos = 0; pos <= strlen(test_input_2); pos +=2) {
+               test_istream_set_size(req->is, pos);
+               oauth2_request_parse_json(req);
+               if (req->is == NULL)
+                       break;
+       }
+
+       pool_unref(&pool);
+
+       test_end();
+}
+
 int main(void)
 {
        static void (*const test_functions[])(void) = {
                test_oauth2_json_valid,
+               test_oauth2_json_error,
                NULL
        };
        return test_run(test_functions);