SUPPORT-8592. Работа с jwt-токенами вынесена в отдельный файл

This commit is contained in:
alashkova 2024-10-18 16:27:41 +03:00
parent 010fe49dda
commit 1c99d4016c
4 changed files with 92 additions and 72 deletions

View file

@ -112,6 +112,7 @@ ADD_EXECUTABLE (${PROJECT_NAME}
${UTILS_DIR}/gconf_file.c
${UTILS_DIR}/glib_utils.c
${UTILS_DIR}/json_parser.c
${UTILS_DIR}/jwt.c
${UTILS_DIR}/library.c
${UTILS_DIR}/logger.c
${UTILS_DIR}/str_t.c

View file

@ -4,7 +4,7 @@
#include "utils/base64.h"
#include "utils/cryptopro.h"
#include "utils/json_parser.h"
#include "utils/jwt.h"
#define VERIFY_CONF_SECTION "verify"
@ -22,8 +22,6 @@ static const str_t VERIFY_CONF_DEFAULT_LOCATION = str_t_const("/verify");
static const int CLIENT_MAX_BODY_SIZE = 8192;
static const char* ACCEPTABLE_CONTENT_TYPE = "text/plain";
static const char* JWT_ALG_FIELD_NAME = "alg";
typedef struct verify_service_s {
const verify_conf_t *conf;
@ -240,73 +238,6 @@ fcgi_verify_request_clear(fcgi_verify_request_t *req_info)
memset(req_info, 0, sizeof(fcgi_verify_request_t));
}
static int
get_jwt_header_payload_and_sign(const str_t *jwt,
/*out*/ str_t *header,
/*out*/ str_t *header_payload,
/*out*/ str_t *sign)
{
LOG_TRACE("get_jwt_header_payload_and_sign enter");
size_t p_start = 0, p_end = 0;
for (size_t i = 0; i < jwt->len; i++) {
if (jwt->data[i] == '.') {
if (p_start == 0) {
p_start = i + 1;
} else {
p_end = i;
break;
}
}
}
if (p_start == 0 || p_end == 0) {
LOG_ERROR("Could not parse jwt. p_start = %zd, p_end = %zd", p_start, p_end);
return -1;
}
header->data = (char*)jwt->data;
header->len = p_start - 1;
header_payload->data = (char*)jwt->data;
header_payload->len = p_end;
sign->data = (char*)jwt->data + p_end + 1;
sign->len = jwt->len - p_end - 1;
LOG_DEBUG("header: %.*s", (int) header->len, header->data);
LOG_DEBUG("header_payload: %.*s", (int) header_payload->len, header_payload->data);
LOG_DEBUG("sign: %.*s", (int) sign->len, sign->data);
LOG_TRACE("get_jwt_header_payload_and_sign exit");
return 0;
}
static int
get_alg_from_header(const str_t *header, /*out*/ str_t *alg)
{
LOG_TRACE("get_alg_from_header");
Hjson_parser parser = json_parser_create(header->data, header->len);
if (parser == NULL) {
goto error;
}
if (json_get_string_member(parser, JWT_ALG_FIELD_NAME, alg)) {
goto error;
}
json_parser_free(parser);
return 0;
error:
json_parser_free(parser);
LOG_ERROR("get_alg_from_header exit with error");
return -1;
}
static fcgi_handler_status_t
verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx)
{
@ -325,7 +256,7 @@ verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx)
str_t header_payload = str_t_null;
str_t alg = str_t_null;
if (get_jwt_header_payload_and_sign(&jwt, &header_base64, &header_payload, &sign_base64)) {
if (jwt_get_header_payload_and_sign(&jwt, &header_base64, &header_payload, &sign_base64)) {
goto error;
}
@ -351,7 +282,7 @@ verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx)
goto error;
}
if (get_alg_from_header(&header, &alg)) {
if (jwt_get_alg_from_header(&header, &alg)) {
goto error;
}

75
src/utils/jwt.c Normal file
View file

@ -0,0 +1,75 @@
#include "jwt.h"
#include "json_parser.h"
#include "logger.h"
#define JWT_ALG_FIELD_NAME "alg"
int
jwt_get_header_payload_and_sign(const str_t *jwt,
/*out*/ str_t *header,
/*out*/ str_t *header_payload,
/*out*/ str_t *sign)
{
LOG_TRACE("jwt_get_header_payload_and_sign enter");
size_t p_start = 0, p_end = 0;
for (size_t i = 0; i < jwt->len; i++) {
if (jwt->data[i] == '.') {
if (p_start == 0) {
p_start = i + 1;
} else {
p_end = i;
break;
}
}
}
if (p_start == 0 || p_end == 0) {
LOG_ERROR("Could not parse jwt. p_start = %zd, p_end = %zd", p_start, p_end);
return -1;
}
header->data = (char*)jwt->data;
header->len = p_start - 1;
header_payload->data = (char*)jwt->data;
header_payload->len = p_end;
sign->data = (char*)jwt->data + p_end + 1;
sign->len = jwt->len - p_end - 1;
LOG_DEBUG("header: %.*s", (int) header->len, header->data);
LOG_DEBUG("header_payload: %.*s", (int) header_payload->len, header_payload->data);
LOG_DEBUG("sign: %.*s", (int) sign->len, sign->data);
LOG_TRACE("jwt_get_header_payload_and_sign exit");
return 0;
}
int
jwt_get_alg_from_header(const str_t *header, /*out*/ str_t *alg)
{
LOG_TRACE("jwt_get_alg_from_header enter");
Hjson_parser parser = json_parser_create(header->data, header->len);
if (parser == NULL) {
goto error;
}
if (json_get_string_member(parser, JWT_ALG_FIELD_NAME, alg)) {
goto error;
}
json_parser_free(parser);
LOG_TRACE("jwt_get_alg_from_header exit");
return 0;
error:
json_parser_free(parser);
LOG_ERROR("jwt_get_alg_from_header exit with error");
return -1;
}

13
src/utils/jwt.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef JWT_H_INCLUDED
#define JWT_H_INCLUDED
#include "str_t.h"
int jwt_get_header_payload_and_sign(const str_t *jwt,
/*out*/ str_t *header,
/*out*/ str_t *header_payload,
/*out*/ str_t *sign);
int jwt_get_alg_from_header(const str_t *header, /*out*/ str_t *alg);
#endif // JWT_H_INCLUDED