From: Aki Tuomi Date: Wed, 20 Sep 2023 10:52:46 +0000 (+0300) Subject: lib-oauth2: Fail request if response has error X-Git-Tag: 2.4.0~2576 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf77725f3d194b1c9cd1eb1896a0ea38f6afca62;p=thirdparty%2Fdovecot%2Fcore.git lib-oauth2: Fail request if response has error --- diff --git a/src/lib-oauth2/oauth2-request.c b/src/lib-oauth2/oauth2-request.c index 01f140df3b..462e828b01 100644 --- a/src/lib-oauth2/oauth2-request.c +++ b/src/lib-oauth2/oauth2-request.c @@ -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); } diff --git a/src/lib-oauth2/test-oauth2-json.c b/src/lib-oauth2/test-oauth2-json.c index 87caedcb28..3a2ca1788f 100644 --- a/src/lib-oauth2/test-oauth2-json.c +++ b/src/lib-oauth2/test-oauth2-json.c @@ -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);