From 3934bdda9d0ccfe9fe3f6856827c0016444ecdc0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 10 Jun 2023 08:34:36 -0400 Subject: [PATCH] Add other files that are new since 0.6.0 --- dep/jwt-cpp/cmake/HunterGate.cmake | 537 ++++++++++ dep/jwt-cpp/cmake/code-coverage.cmake | 12 + dep/jwt-cpp/cmake/jwt-cpp-config.cmake.in | 19 + .../cmake/private-find-boost-json.cmake | 16 + .../cmake/private-find-kazuho-picojson.cmake | 10 + dep/jwt-cpp/docs/faqs.md | 75 ++ dep/jwt-cpp/docs/ssl.md | 19 + dep/jwt-cpp/docs/traits.md | 60 ++ dep/jwt-cpp/example/CMakeLists.txt | 33 + dep/jwt-cpp/example/conan/CMakeLists.txt | 8 + dep/jwt-cpp/example/conan/README.md | 24 + dep/jwt-cpp/example/conan/conanfile.txt | 6 + dep/jwt-cpp/example/conan/main.cpp | 17 + dep/jwt-cpp/example/es256k.cpp | 40 + dep/jwt-cpp/example/jwks-verify.cpp | 57 ++ .../example/partial-claim-verifier.cpp | 91 ++ dep/jwt-cpp/example/print-claims.cpp | 11 + dep/jwt-cpp/example/private-claims.cpp | 46 + dep/jwt-cpp/example/rsa-create.cpp | 44 + dep/jwt-cpp/example/rsa-verify.cpp | 34 + dep/jwt-cpp/example/traits/CMakeLists.txt | 30 + dep/jwt-cpp/example/traits/README.md | 6 + dep/jwt-cpp/example/traits/boost-json.cpp | 52 + .../example/traits/danielaparker-jsoncons.cpp | 47 + .../example/traits/kazuho-picojson.cpp | 47 + dep/jwt-cpp/example/traits/nlohmann-json.cpp | 47 + .../jwt-cpp/traits/boost-json/defaults.h | 88 ++ .../jwt-cpp/traits/boost-json/traits.h | 80 ++ .../traits/danielaparker-jsoncons/defaults.h | 88 ++ .../traits/danielaparker-jsoncons/traits.h | 123 +++ .../jwt-cpp/traits/defaults.h.mustache | 90 ++ .../jwt-cpp/traits/kazuho-picojson/defaults.h | 84 ++ .../jwt-cpp/traits/kazuho-picojson/traits.h | 76 ++ .../jwt-cpp/traits/nlohmann-json/defaults.h | 88 ++ .../jwt-cpp/traits/nlohmann-json/traits.h | 77 ++ dep/jwt-cpp/nuget/jwt-cpp.nuspec | 29 + dep/jwt-cpp/nuget/jwt-cpp.targets | 8 + dep/jwt-cpp/tests/BaseTest.cpp | 110 +++ dep/jwt-cpp/tests/CMakeLists.txt | 66 ++ dep/jwt-cpp/tests/ClaimTest.cpp | 141 +++ dep/jwt-cpp/tests/HelperTest.cpp | 205 ++++ dep/jwt-cpp/tests/JwksTest.cpp | 118 +++ dep/jwt-cpp/tests/Keys.cpp | 220 +++++ dep/jwt-cpp/tests/OpenSSLErrorTest.cpp | 931 ++++++++++++++++++ dep/jwt-cpp/tests/TestMain.cpp | 6 + dep/jwt-cpp/tests/TokenFormatTest.cpp | 16 + dep/jwt-cpp/tests/TokenTest.cpp | 801 +++++++++++++++ dep/jwt-cpp/tests/cmake/CMakeLists.txt | 9 + .../tests/cmake/base64-is-disabled.cpp | 10 + dep/jwt-cpp/tests/cmake/defaults-enabled.cpp | 6 + dep/jwt-cpp/tests/cmake/libressl-is-used.cpp | 13 + .../tests/cmake/picojson-is-disabled.cpp | 10 + dep/jwt-cpp/tests/cmake/wolfssl-is-used.cpp | 21 + dep/jwt-cpp/tests/fuzz/BaseDecodeFuzz.cpp | 13 + dep/jwt-cpp/tests/fuzz/BaseEncodeFuzz.cpp | 9 + dep/jwt-cpp/tests/fuzz/CMakeLists.txt | 20 + dep/jwt-cpp/tests/fuzz/TokenDecodeFuzz.cpp | 27 + .../086a3aa337038cac8a75a05131444f222e48aee8 | 1 + .../8ebaef2304e91465585c8d7fcf4d9f939e08d6b4 | 1 + .../ba528234d9f6949ed9c9626c08a782f6e7c15b8b | 1 + .../de1028a3fe87471f027522c3ed9ec02b8364a006 | 1 + .../e8f531caaa67cecb1c7b162f3e1d4e320d79befd | 1 + .../9d891e731f75deae56884d79e9816736b7488080 | 1 + .../ff384e2421a333cd52f259cec14c7f790d595db9 | 1 + .../tests/fuzz/token-corpus/valid-sample | 1 + dep/jwt-cpp/tests/traits/BoostJsonTest.cpp | 128 +++ dep/jwt-cpp/tests/traits/JsonconsTest.cpp | 133 +++ dep/jwt-cpp/tests/traits/NlohmannTest.cpp | 128 +++ .../tests/traits/TraitsTest.cpp.mustache | 133 +++ 69 files changed, 5501 insertions(+) create mode 100644 dep/jwt-cpp/cmake/HunterGate.cmake create mode 100644 dep/jwt-cpp/cmake/code-coverage.cmake create mode 100644 dep/jwt-cpp/cmake/jwt-cpp-config.cmake.in create mode 100644 dep/jwt-cpp/cmake/private-find-boost-json.cmake create mode 100644 dep/jwt-cpp/cmake/private-find-kazuho-picojson.cmake create mode 100644 dep/jwt-cpp/docs/faqs.md create mode 100644 dep/jwt-cpp/docs/ssl.md create mode 100644 dep/jwt-cpp/docs/traits.md create mode 100644 dep/jwt-cpp/example/CMakeLists.txt create mode 100644 dep/jwt-cpp/example/conan/CMakeLists.txt create mode 100644 dep/jwt-cpp/example/conan/README.md create mode 100644 dep/jwt-cpp/example/conan/conanfile.txt create mode 100644 dep/jwt-cpp/example/conan/main.cpp create mode 100644 dep/jwt-cpp/example/es256k.cpp create mode 100644 dep/jwt-cpp/example/jwks-verify.cpp create mode 100644 dep/jwt-cpp/example/partial-claim-verifier.cpp create mode 100644 dep/jwt-cpp/example/print-claims.cpp create mode 100644 dep/jwt-cpp/example/private-claims.cpp create mode 100644 dep/jwt-cpp/example/rsa-create.cpp create mode 100644 dep/jwt-cpp/example/rsa-verify.cpp create mode 100644 dep/jwt-cpp/example/traits/CMakeLists.txt create mode 100644 dep/jwt-cpp/example/traits/README.md create mode 100644 dep/jwt-cpp/example/traits/boost-json.cpp create mode 100644 dep/jwt-cpp/example/traits/danielaparker-jsoncons.cpp create mode 100644 dep/jwt-cpp/example/traits/kazuho-picojson.cpp create mode 100644 dep/jwt-cpp/example/traits/nlohmann-json.cpp create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/boost-json/defaults.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/boost-json/traits.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/traits.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/defaults.h.mustache create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/defaults.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/traits.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/defaults.h create mode 100644 dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/traits.h create mode 100644 dep/jwt-cpp/nuget/jwt-cpp.nuspec create mode 100644 dep/jwt-cpp/nuget/jwt-cpp.targets create mode 100644 dep/jwt-cpp/tests/BaseTest.cpp create mode 100644 dep/jwt-cpp/tests/CMakeLists.txt create mode 100644 dep/jwt-cpp/tests/ClaimTest.cpp create mode 100644 dep/jwt-cpp/tests/HelperTest.cpp create mode 100644 dep/jwt-cpp/tests/JwksTest.cpp create mode 100644 dep/jwt-cpp/tests/Keys.cpp create mode 100644 dep/jwt-cpp/tests/OpenSSLErrorTest.cpp create mode 100644 dep/jwt-cpp/tests/TestMain.cpp create mode 100644 dep/jwt-cpp/tests/TokenFormatTest.cpp create mode 100644 dep/jwt-cpp/tests/TokenTest.cpp create mode 100644 dep/jwt-cpp/tests/cmake/CMakeLists.txt create mode 100644 dep/jwt-cpp/tests/cmake/base64-is-disabled.cpp create mode 100644 dep/jwt-cpp/tests/cmake/defaults-enabled.cpp create mode 100644 dep/jwt-cpp/tests/cmake/libressl-is-used.cpp create mode 100644 dep/jwt-cpp/tests/cmake/picojson-is-disabled.cpp create mode 100644 dep/jwt-cpp/tests/cmake/wolfssl-is-used.cpp create mode 100644 dep/jwt-cpp/tests/fuzz/BaseDecodeFuzz.cpp create mode 100644 dep/jwt-cpp/tests/fuzz/BaseEncodeFuzz.cpp create mode 100644 dep/jwt-cpp/tests/fuzz/CMakeLists.txt create mode 100644 dep/jwt-cpp/tests/fuzz/TokenDecodeFuzz.cpp create mode 100644 dep/jwt-cpp/tests/fuzz/decode-corpus/086a3aa337038cac8a75a05131444f222e48aee8 create mode 100644 dep/jwt-cpp/tests/fuzz/decode-corpus/8ebaef2304e91465585c8d7fcf4d9f939e08d6b4 create mode 100644 dep/jwt-cpp/tests/fuzz/decode-corpus/ba528234d9f6949ed9c9626c08a782f6e7c15b8b create mode 100644 dep/jwt-cpp/tests/fuzz/decode-corpus/de1028a3fe87471f027522c3ed9ec02b8364a006 create mode 100644 dep/jwt-cpp/tests/fuzz/decode-corpus/e8f531caaa67cecb1c7b162f3e1d4e320d79befd create mode 100644 dep/jwt-cpp/tests/fuzz/token-corpus/9d891e731f75deae56884d79e9816736b7488080 create mode 100644 dep/jwt-cpp/tests/fuzz/token-corpus/ff384e2421a333cd52f259cec14c7f790d595db9 create mode 100644 dep/jwt-cpp/tests/fuzz/token-corpus/valid-sample create mode 100644 dep/jwt-cpp/tests/traits/BoostJsonTest.cpp create mode 100644 dep/jwt-cpp/tests/traits/JsonconsTest.cpp create mode 100644 dep/jwt-cpp/tests/traits/NlohmannTest.cpp create mode 100644 dep/jwt-cpp/tests/traits/TraitsTest.cpp.mustache diff --git a/dep/jwt-cpp/cmake/HunterGate.cmake b/dep/jwt-cpp/cmake/HunterGate.cmake new file mode 100644 index 000000000..64ccde563 --- /dev/null +++ b/dep/jwt-cpp/cmake/HunterGate.cmake @@ -0,0 +1,537 @@ +# Copyright (c) 2013-2019, Ruslan Baratov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a gate file to Hunter package manager. +# Include this file using `include` command and add package you need, example: +# +# cmake_minimum_required(VERSION 3.2) +# +# include("cmake/HunterGate.cmake") +# HunterGate( +# URL "https://github.com/path/to/hunter/archive.tar.gz" +# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" +# ) +# +# project(MyProject) +# +# hunter_add_package(Foo) +# hunter_add_package(Boo COMPONENTS Bar Baz) +# +# Projects: +# * https://github.com/hunter-packages/gate/ +# * https://github.com/ruslo/hunter + +option(HUNTER_ENABLED "Enable Hunter package manager support" ON) + +if(HUNTER_ENABLED) + if(CMAKE_VERSION VERSION_LESS "3.2") + message( + FATAL_ERROR + "At least CMake version 3.2 required for Hunter dependency management." + " Update CMake or set HUNTER_ENABLED to OFF." + ) + endif() +endif() + +include(CMakeParseArguments) # cmake_parse_arguments + +option(HUNTER_STATUS_PRINT "Print working status" ON) +option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) +option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) +set(HUNTER_ROOT "" CACHE FILEPATH "Override the HUNTER_ROOT.") + +set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors") + +function(hunter_gate_status_print) + if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + message(STATUS "[hunter] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_status_debug) + if(HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + string(TIMESTAMP timestamp) + message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_error_page error_page) + message("------------------------------ ERROR ------------------------------") + message(" ${HUNTER_ERROR_PAGE}/${error_page}.html") + message("-------------------------------------------------------------------") + message("") + message(FATAL_ERROR "") +endfunction() + +function(hunter_gate_internal_error) + message("") + foreach(print_message ${ARGV}) + message("[hunter ** INTERNAL **] ${print_message}") + endforeach() + message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("error.internal") +endfunction() + +function(hunter_gate_fatal_error) + cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}") + if("${hunter_ERROR_PAGE}" STREQUAL "") + hunter_gate_internal_error("Expected ERROR_PAGE") + endif() + message("") + foreach(x ${hunter_UNPARSED_ARGUMENTS}) + message("[hunter ** FATAL ERROR **] ${x}") + endforeach() + message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("${hunter_ERROR_PAGE}") +endfunction() + +function(hunter_gate_user_error) + hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data") +endfunction() + +function(hunter_gate_self root version sha1 result) + string(COMPARE EQUAL "${root}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("root is empty") + endif() + + string(COMPARE EQUAL "${version}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("version is empty") + endif() + + string(COMPARE EQUAL "${sha1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("sha1 is empty") + endif() + + string(SUBSTRING "${sha1}" 0 7 archive_id) + + if(EXISTS "${root}/cmake/Hunter") + set(hunter_self "${root}") + else() + set( + hunter_self + "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" + ) + endif() + + set("${result}" "${hunter_self}" PARENT_SCOPE) +endfunction() + +# Set HUNTER_GATE_ROOT cmake variable to suitable value. +function(hunter_gate_detect_root) + # Check CMake variable + if(HUNTER_ROOT) + set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") + return() + endif() + + # Check environment variable + if(DEFINED ENV{HUNTER_ROOT}) + set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") + return() + endif() + + # Check HOME environment variable + if(DEFINED ENV{HOME}) + set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") + return() + endif() + + # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) + if(WIN32) + if(DEFINED ENV{SYSTEMDRIVE}) + set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using SYSTEMDRIVE environment variable" + ) + return() + endif() + + if(DEFINED ENV{USERPROFILE}) + set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using USERPROFILE environment variable" + ) + return() + endif() + endif() + + hunter_gate_fatal_error( + "Can't detect HUNTER_ROOT" + ERROR_PAGE "error.detect.hunter.root" + ) +endfunction() + +function(hunter_gate_download dir) + string( + COMPARE + NOTEQUAL + "$ENV{HUNTER_DISABLE_AUTOINSTALL}" + "" + disable_autoinstall + ) + if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) + hunter_gate_fatal_error( + "Hunter not found in '${dir}'" + "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" + "Settings:" + " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" + " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" + ERROR_PAGE "error.run.install" + ) + endif() + string(COMPARE EQUAL "${dir}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("Empty 'dir' argument") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_URL empty") + endif() + + set(done_location "${dir}/DONE") + set(sha1_location "${dir}/SHA1") + + set(build_dir "${dir}/Build") + set(cmakelists "${dir}/CMakeLists.txt") + + hunter_gate_status_debug("Locking directory: ${dir}") + file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) + hunter_gate_status_debug("Lock done") + + if(EXISTS "${done_location}") + # while waiting for lock other instance can do all the job + hunter_gate_status_debug("File '${done_location}' found, skip install") + return() + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(MAKE_DIRECTORY "${build_dir}") # check directory permissions + + # Disabling languages speeds up a little bit, reduces noise in the output + # and avoids path too long windows error + file( + WRITE + "${cmakelists}" + "cmake_minimum_required(VERSION 3.2)\n" + "project(HunterDownload LANGUAGES NONE)\n" + "include(ExternalProject)\n" + "ExternalProject_Add(\n" + " Hunter\n" + " URL\n" + " \"${HUNTER_GATE_URL}\"\n" + " URL_HASH\n" + " SHA1=${HUNTER_GATE_SHA1}\n" + " DOWNLOAD_DIR\n" + " \"${dir}\"\n" + " TLS_VERIFY\n" + " ${HUNTER_TLS_VERIFY}\n" + " SOURCE_DIR\n" + " \"${dir}/Unpacked\"\n" + " CONFIGURE_COMMAND\n" + " \"\"\n" + " BUILD_COMMAND\n" + " \"\"\n" + " INSTALL_COMMAND\n" + " \"\"\n" + ")\n" + ) + + if(HUNTER_STATUS_DEBUG) + set(logging_params "") + else() + set(logging_params OUTPUT_QUIET) + endif() + + hunter_gate_status_debug("Run generate") + + # Need to add toolchain file too. + # Otherwise on Visual Studio + MDD this will fail with error: + # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") + else() + # 'toolchain_arg' can't be empty + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") + endif() + + string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) + if(no_make) + set(make_arg "") + else() + # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM + set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") + endif() + + execute_process( + COMMAND + "${CMAKE_COMMAND}" + "-H${dir}" + "-B${build_dir}" + "-G${CMAKE_GENERATOR}" + "${toolchain_arg}" + ${make_arg} + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error( + "Configure project failed." + "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" + "In directory ${dir}" + ) + endif() + + hunter_gate_status_print( + "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" + " ${HUNTER_GATE_URL}" + " -> ${dir}" + ) + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error("Build project failed") + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") + file(WRITE "${done_location}" "DONE") + + hunter_gate_status_debug("Finished") +endfunction() + +# Must be a macro so master file 'cmake/Hunter' can +# apply all variables easily just by 'include' command +# (otherwise PARENT_SCOPE magic needed) +macro(HunterGate) + if(HUNTER_GATE_DONE) + # variable HUNTER_GATE_DONE set explicitly for external project + # (see `hunter_download`) + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() + + # First HunterGate command will init Hunter, others will be ignored + get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) + + if(NOT HUNTER_ENABLED) + # Empty function to avoid error "unknown function" + function(hunter_add_package) + endfunction() + + set( + _hunter_gate_disabled_mode_dir + "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" + ) + if(EXISTS "${_hunter_gate_disabled_mode_dir}") + hunter_gate_status_debug( + "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" + ) + list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") + endif() + elseif(_hunter_gate_done) + hunter_gate_status_debug("Secondary HunterGate (use old settings)") + hunter_gate_self( + "${HUNTER_CACHED_ROOT}" + "${HUNTER_VERSION}" + "${HUNTER_SHA1}" + _hunter_self + ) + include("${_hunter_self}/cmake/Hunter") + else() + set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") + + string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) + if(_have_project_name) + hunter_gate_fatal_error( + "Please set HunterGate *before* 'project' command. " + "Detected project: ${PROJECT_NAME}" + ERROR_PAGE "error.huntergate.before.project" + ) + endif() + + cmake_parse_arguments( + HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} + ) + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) + string( + COMPARE + NOTEQUAL + "${HUNTER_GATE_UNPARSED_ARGUMENTS}" + "" + _have_unparsed + ) + string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) + string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) + + if(_have_unparsed) + hunter_gate_user_error( + "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" + ) + endif() + if(_empty_sha1) + hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") + endif() + if(_empty_url) + hunter_gate_user_error("URL suboption of HunterGate is mandatory") + endif() + if(_have_global) + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") + endif() + endif() + if(HUNTER_GATE_LOCAL) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") + endif() + endif() + if(_have_filepath) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") + endif() + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") + endif() + endif() + + hunter_gate_detect_root() # set HUNTER_GATE_ROOT + + # Beautify path, fix probable problems with windows path slashes + get_filename_component( + HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE + ) + hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") + if(NOT HUNTER_ALLOW_SPACES_IN_PATH) + string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) + if(NOT _contain_spaces EQUAL -1) + hunter_gate_fatal_error( + "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." + "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" + "(Use at your own risk!)" + ERROR_PAGE "error.spaces.in.hunter.root" + ) + endif() + endif() + + string( + REGEX + MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" + HUNTER_GATE_VERSION + "${HUNTER_GATE_URL}" + ) + string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) + if(_is_empty) + set(HUNTER_GATE_VERSION "unknown") + endif() + + hunter_gate_self( + "${HUNTER_GATE_ROOT}" + "${HUNTER_GATE_VERSION}" + "${HUNTER_GATE_SHA1}" + _hunter_self + ) + + set(_master_location "${_hunter_self}/cmake/Hunter") + if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") + # Hunter downloaded manually (e.g. by 'git clone') + set(_unused "xxxxxxxxxx") + set(HUNTER_GATE_SHA1 "${_unused}") + set(HUNTER_GATE_VERSION "${_unused}") + else() + get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) + set(_done_location "${_archive_id_location}/DONE") + set(_sha1_location "${_archive_id_location}/SHA1") + + # Check Hunter already downloaded by HunterGate + if(NOT EXISTS "${_done_location}") + hunter_gate_download("${_archive_id_location}") + endif() + + if(NOT EXISTS "${_done_location}") + hunter_gate_internal_error("hunter_gate_download failed") + endif() + + if(NOT EXISTS "${_sha1_location}") + hunter_gate_internal_error("${_sha1_location} not found") + endif() + file(READ "${_sha1_location}" _sha1_value) + string(TOLOWER "${_sha1_value}" _sha1_value_lower) + string(TOLOWER "${HUNTER_GATE_SHA1}" _HUNTER_GATE_SHA1_lower) + string(COMPARE EQUAL "${_sha1_value_lower}" "${_HUNTER_GATE_SHA1_lower}" _is_equal) + if(NOT _is_equal) + hunter_gate_internal_error( + "Short SHA1 collision:" + " ${_sha1_value} (from ${_sha1_location})" + " ${HUNTER_GATE_SHA1} (HunterGate)" + ) + endif() + if(NOT EXISTS "${_master_location}") + hunter_gate_user_error( + "Master file not found:" + " ${_master_location}" + "try to update Hunter/HunterGate" + ) + endif() + endif() + include("${_master_location}") + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() +endmacro() diff --git a/dep/jwt-cpp/cmake/code-coverage.cmake b/dep/jwt-cpp/cmake/code-coverage.cmake new file mode 100644 index 000000000..5e630bc8c --- /dev/null +++ b/dep/jwt-cpp/cmake/code-coverage.cmake @@ -0,0 +1,12 @@ +set(COVERAGE_CMAKE "${CMAKE_BINARY_DIR}/cmake/CodeCoverage.cmake") +if(NOT EXISTS ${COVERAGE_CMAKE}) + set(COVERAGE_URL "https://raw.githubusercontent.com/bilke/cmake-modules/master/CodeCoverage.cmake") + file(DOWNLOAD ${COVERAGE_URL} ${COVERAGE_CMAKE}) +endif() + +include(${COVERAGE_CMAKE}) + +function(setup_coverage TARGET) + target_compile_options(${TARGET} PRIVATE -g -O0 -fprofile-arcs -ftest-coverage) + target_link_libraries(${TARGET} PRIVATE gcov) +endfunction() diff --git a/dep/jwt-cpp/cmake/jwt-cpp-config.cmake.in b/dep/jwt-cpp/cmake/jwt-cpp-config.cmake.in new file mode 100644 index 000000000..029f3586c --- /dev/null +++ b/dep/jwt-cpp/cmake/jwt-cpp-config.cmake.in @@ -0,0 +1,19 @@ +@PACKAGE_INIT@ + +set(JWT_EXTERNAL_PICOJSON @JWT_EXTERNAL_PICOJSON@) +set(JWT_SSL_LIBRARY @JWT_SSL_LIBRARY@) + +include(CMakeFindDependencyMacro) +if(${JWT_SSL_LIBRARY} MATCHES "wolfSSL") + find_dependency(PkgConfig REQUIRED) + pkg_check_modules(wolfssl REQUIRED IMPORTED_TARGET wolfssl) + list(TRANSFORM wolfssl_INCLUDE_DIRS APPEND "/wolfssl") # This is required to access OpenSSL compatibility API +else() + find_dependency(${JWT_SSL_LIBRARY} REQUIRED) +endif() + +if(JWT_EXTERNAL_PICOJSON) + find_dependency(picojson REQUIRED) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/jwt-cpp-targets.cmake") diff --git a/dep/jwt-cpp/cmake/private-find-boost-json.cmake b/dep/jwt-cpp/cmake/private-find-boost-json.cmake new file mode 100644 index 000000000..70c7b6ccd --- /dev/null +++ b/dep/jwt-cpp/cmake/private-find-boost-json.cmake @@ -0,0 +1,16 @@ +if(TARGET boost_json) + return() +endif() + +unset(BOOSTJSON_INCLUDE_DIR CACHE) +find_path(BOOSTJSON_INCLUDE_DIR "boost/json.hpp" "boost/json/src.hpp") +if(EXISTS "${BOOSTJSON_INCLUDE_DIR}/boost/json.hpp") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/private-boost-json.cpp.in" "#include ") + configure_file("${CMAKE_CURRENT_BINARY_DIR}/private-boost-json.cpp.in" private-boost-json.cpp COPYONLY) + add_library(boost_json "${BOOSTJSON_INCLUDE_DIR}/boost/json.hpp" + "${BOOSTJSON_INCLUDE_DIR}/boost/json/src.hpp" + "${CMAKE_CURRENT_BINARY_DIR}/private-boost-json.cpp") + target_include_directories(boost_json PUBLIC ${BOOSTJSON_INCLUDE_DIR}) + target_compile_definitions(boost_json PUBLIC BOOST_JSON_STANDALONE) + target_compile_features(boost_json PUBLIC cxx_std_17) +endif() diff --git a/dep/jwt-cpp/cmake/private-find-kazuho-picojson.cmake b/dep/jwt-cpp/cmake/private-find-kazuho-picojson.cmake new file mode 100644 index 000000000..ccbed3065 --- /dev/null +++ b/dep/jwt-cpp/cmake/private-find-kazuho-picojson.cmake @@ -0,0 +1,10 @@ +if(TARGET kazuho_picojson) + return() +endif() + +unset(PICOJSON_INCLUDE_DIR CACHE) +find_path(PICOJSON_INCLUDE_DIR "picojson/picojson.h") +if(EXISTS "${PICOJSON_INCLUDE_DIR}/picojson/picojson.h") + add_library(kazuho_picojson INTERFACE) + target_include_directories(kazuho_picojson INTERFACE ${PICOJSON_INCLUDE_DIR}) +endif() diff --git a/dep/jwt-cpp/docs/faqs.md b/dep/jwt-cpp/docs/faqs.md new file mode 100644 index 000000000..48b107fd7 --- /dev/null +++ b/dep/jwt-cpp/docs/faqs.md @@ -0,0 +1,75 @@ +# Frequently Asked Questions + +## Handling Tokens + +### The generated JWT token can be decoded, is this correct and secure? + +This is the expected behaviour. While the integrity of tokens is ensured by the generated/verified hash, +the contents of the token are only **encoded and not encrypted**. This means you can be sure the token +has not been modified by an unauthorized party, but you should not store confidential information in it. +Anyone with access to the token can read all the claims you put into it. They can however not modify +them unless they have the (private or symmetric) key used to generate the token. If you need to put +confidential information into it, current industry recommends generating a random id and store the data on your +server, using the id to look it up whenever you need. + +### How can new keys be generated for my application? + +The algorithms provided are all based on OpenSSL, mixing other +cryptographic tools might not work. + +Here are a few links for your convenience: + +- [RSA](https://stackoverflow.com/a/44474607) +- [ED25519](https://stackoverflow.com/a/73118582) +- [ES256](https://github.com/Thalhammer/jwt-cpp/blob/68309438cf30679d6581d6cfbfeea0c028d9ed04/example/es256k.cpp#L5) + +### Can this library encrypt/decrypt claims? + +No it does not, see [#115](https://github.com/Thalhammer/jwt-cpp/issues/115) for more details. +More importantly you probably dont want to be using JWTs for anything sensitive. Read [this](https://stackoverflow.com/a/43497242/8480874) +for more. + +### Why are my tokens immediately expired? + +If you are generating tokens that seem to immediately expire, you are likely mixing local time where it is not required. The JWT specification +requires using UTC which this library does. + +Here is a simple example of creating a token that will expire in one hour: + +```cpp +auto token = jwt::create() + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); +``` + +### Can you add claims to a signed token? + +The signature includes both the header and payload, according to the RFCs... changing the payload would cause a discrepancy. +That should result in the token being rejected. For more details checkout [#194](https://github.com/Thalhammer/jwt-cpp/issues/194). + +### Why does `jwt::basic_claim` have no `as_object()` method? + +This was brought up in [#212](https://github.com/Thalhammer/jwt-cpp/issues/212#issuecomment-1054344192) and +[#101](https://github.com/Thalhammer/jwt-cpp/issues/101) as it's an excellent question. + +It simply was not required to handle the required keys in JWTs for signing or verification. All the the mandatory keys are numeric, +string or array types which required type definitions and access. + +The alternative is to use the `to_json()` method and use the libraries own APIs to pick the data type you need. + +## Build Issues + +### Missing \_HMAC and \_EVP_sha256 symbols on Mac + +There seems to exists a problem with the included openssl library of MacOS. Make sure you link to one provided by brew. +See [here](https://github.com/Thalhammer/jwt-cpp/issues/6) for more details. + +### Building on windows fails with syntax errors + +The header ``, which is often included in windowsprojects, defines macros for MIN and MAX which screw up std::numeric_limits. +See [here](https://github.com/Thalhammer/jwt-cpp/issues/5) for more details. To fix this do one of the following things: + +* define NOMINMAX, which suppresses this behaviour +* include this library before you include windows.h +* place `#undef max` and `#undef min` before you include this library diff --git a/dep/jwt-cpp/docs/ssl.md b/dep/jwt-cpp/docs/ssl.md new file mode 100644 index 000000000..4f001ac53 --- /dev/null +++ b/dep/jwt-cpp/docs/ssl.md @@ -0,0 +1,19 @@ +# Cryptography Libraries + +The underlying cryptography libraries describe [here](../README.md#ssl-compatibility) can be selected when +configuring CMake by explicitly setting `JWT_SSL_LIBRARY` to one of three values. The default is to use OpenSSL. + +- OpenSSL +- LibreSSL +- wolfSSL + +Here's an example: + +```sh +cmake . -DJWT_SSL_LIBRARY:STRING=wolfSSL +``` + +## Notes + +JWT-CPP relies on the OpenSSL API, as a result both LibreSSL and wolfSSL need to include their respective compatibility layers. +Most system already have OpenSSL so it's important to make sure when compiling your application it only includes one. Otherwise you may have missing symbols when linking. diff --git a/dep/jwt-cpp/docs/traits.md b/dep/jwt-cpp/docs/traits.md new file mode 100644 index 000000000..71eddb6af --- /dev/null +++ b/dep/jwt-cpp/docs/traits.md @@ -0,0 +1,60 @@ +# JSON Traits + +Traits define the compatibility mapping for JWT-CPP required functionality to the JSON implementation of choice. + +## Providing your own JSON Traits + +There are several key items that need to be provided to a `jwt::basic_claim` in order for it to be interoperable with you JSON library of choice. + +* type specifications +* conversion from generic "value type" to a specific type +* serialization and parsing + +If ever you are not sure, the traits are heavily checked against static asserts to make sure you provide everything that's required. + +> :warning: Not all JSON libraries are a like, you may need to extend certain types such that it can be used. See this [provided implementation](https://github.com/Thalhammer/jwt-cpp/blob/e6b92cca0b7088027269c481fa244e5c39df88ff/include/jwt-cpp/traits/danielaparker-jsoncons/traits.h#L18). + +```cpp +struct my_favorite_json_library_traits { + // Type Specifications + using value_type = json; // The generic "value type" implementation, most libraries have one + using object_type = json::object_t; // The "map type" string to value + using array_type = json::array_t; // The "list type" array of values + using string_type = std::string; // The "list of chars", must be a narrow char + using number_type = double; // The "precision type" + using integer_type = int64_t; // The "integral type" + using boolean_type = bool; // The "boolean type" + + // Translation between the implementation notion of type, to the jwt::json::type equivalent + static jwt::json::type get_type(const value_type &val) { + using jwt::json::type; + + if (val.type() == json::value_t::object) + return type::object; + if (val.type() == json::value_t::array) + return type::array; + if (val.type() == json::value_t::string) + return type::string; + if (val.type() == json::value_t::number_float) + return type::number; + if (val.type() == json::value_t::number_integer) + return type::integer; + if (val.type() == json::value_t::boolean) + return type::boolean; + + throw std::logic_error("invalid type"); + } + + // Conversion from generic value to specific type + static object_type as_object(const value_type &val); + static array_type as_array(const value_type &val); + static string_type as_string(const value_type &val); + static number_type as_number(const value_type &val); + static integer_type as_integer(const value_type &val); + static boolean_type as_boolean(const value_type &val); + + // serialization and parsing + static bool parse(value_type &val, string_type str); + static string_type serialize(const value_type &val); // with no extra whitespace, padding or indentation +}; +``` diff --git a/dep/jwt-cpp/example/CMakeLists.txt b/dep/jwt-cpp/example/CMakeLists.txt new file mode 100644 index 000000000..a153b57b1 --- /dev/null +++ b/dep/jwt-cpp/example/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.8) +project(jwt-cpp-examples) + +if(NOT TARGET jwt-cpp) + find_package(jwt-cpp CONFIG REQUIRED) +endif() + +add_subdirectory(traits) + +if(JWT_DISABLE_PICOJSON) + message(FATAL_ERROR "examples require picojson to be available!") +endif() + +add_executable(print-claims print-claims.cpp) +target_link_libraries(print-claims jwt-cpp::jwt-cpp) + +add_executable(private-claims private-claims.cpp) +target_link_libraries(private-claims jwt-cpp::jwt-cpp) + +add_executable(rsa-create rsa-create.cpp) +target_link_libraries(rsa-create jwt-cpp::jwt-cpp) + +add_executable(rsa-verify rsa-verify.cpp) +target_link_libraries(rsa-verify jwt-cpp::jwt-cpp) + +add_executable(jwks-verify jwks-verify.cpp) +target_link_libraries(jwks-verify jwt-cpp::jwt-cpp) + +add_executable(es256k es256k.cpp) +target_link_libraries(es256k jwt-cpp::jwt-cpp) + +add_executable(partial-claim-verifier partial-claim-verifier.cpp) +target_link_libraries(partial-claim-verifier jwt-cpp::jwt-cpp nlohmann_json::nlohmann_json) diff --git a/dep/jwt-cpp/example/conan/CMakeLists.txt b/dep/jwt-cpp/example/conan/CMakeLists.txt new file mode 100644 index 000000000..7bd897c16 --- /dev/null +++ b/dep/jwt-cpp/example/conan/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.8) +project(conan-example) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(${PROJECT_NAME} main.cpp) +target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) diff --git a/dep/jwt-cpp/example/conan/README.md b/dep/jwt-cpp/example/conan/README.md new file mode 100644 index 000000000..8032ffdef --- /dev/null +++ b/dep/jwt-cpp/example/conan/README.md @@ -0,0 +1,24 @@ +# Conan example + +In the current directory on Linux environment + +```sh +mkdir build && cd build +conan install .. && cmake .. +cmake --build . +``` + +run executable + +```sh +$ ./bin/conan-example +sub = "jrocket@example.com" +iss = "Online JWT Builder" +exp = 1641559177 +aud = "www.example.com" +Surname = "Rocket" +Role = ["Manager","Project Administrator"] +iat = 1610023177 +GivenName = "Johnny" +Email = "jrocket@example.com" +``` diff --git a/dep/jwt-cpp/example/conan/conanfile.txt b/dep/jwt-cpp/example/conan/conanfile.txt new file mode 100644 index 000000000..b2a27f124 --- /dev/null +++ b/dep/jwt-cpp/example/conan/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +jwt-cpp/0.6.0 +picojson/cci.20210117 + +[generators] +cmake diff --git a/dep/jwt-cpp/example/conan/main.cpp b/dep/jwt-cpp/example/conan/main.cpp new file mode 100644 index 000000000..9095ccb99 --- /dev/null +++ b/dep/jwt-cpp/example/conan/main.cpp @@ -0,0 +1,17 @@ +#include "jwt-cpp/jwt.h" +#include +#include + +int main() { + + std::string token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9." + "eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MTAwMjMxNzcsImV4cCI6MTY0MTU1OTE3NywiYXVkIjoid3" + "d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5h" + "bWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IE" + "FkbWluaXN0cmF0b3IiXX0.5EOfHnBmpdPvRHAuVDttgJQvbFuGEF7fC4uBSXAGg6c"; + + auto decoded = jwt::decode(token); + + for (auto& e : decoded.get_payload_json()) + std::cout << e.first << " = " << e.second << std::endl; +} diff --git a/dep/jwt-cpp/example/es256k.cpp b/dep/jwt-cpp/example/es256k.cpp new file mode 100644 index 000000000..d2a59745f --- /dev/null +++ b/dep/jwt-cpp/example/es256k.cpp @@ -0,0 +1,40 @@ +#include +#include + +int main() { + // openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-priv-key.pem + std::string es256k_priv_key = R"(-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIArnQWnspKtjiVuZuzuZ/l1Uqqq8gb2unLJ/6U/Saf4ioAcGBSuBBAAK +oUQDQgAEfy03KCKUpIPMIJBtIG4xOwGm0Np/yHKaK9EDZi0mZ7VUeeNKq476CU5X +940yusahgneePQrDMF2nWFEtBCOiXQ== +-----END EC PRIVATE KEY-----)"; + // openssl ec -in ec-secp256k1-priv-key.pem -pubout > ec-secp256k1-pub-key.pem + std::string es256k_pub_key = R"(-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEfy03KCKUpIPMIJBtIG4xOwGm0Np/yHKa +K9EDZi0mZ7VUeeNKq476CU5X940yusahgneePQrDMF2nWFEtBCOiXQ== +-----END PUBLIC KEY-----)"; + + auto token = jwt::create() + .set_issuer("auth0") + .set_type("JWT") + .set_id("es256k-create-example") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_payload_claim("sample", jwt::claim(std::string{"test"})) + .sign(jwt::algorithm::es256k(es256k_pub_key, es256k_priv_key, "", "")); + + std::cout << "token:\n" << token << std::endl; + + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::es256k(es256k_pub_key, es256k_priv_key, "", "")) + .with_issuer("auth0"); + + auto decoded = jwt::decode(token); + + verify.verify(decoded); + + for (auto& e : decoded.get_header_json()) + std::cout << e.first << " = " << e.second << std::endl; + for (auto& e : decoded.get_payload_json()) + std::cout << e.first << " = " << e.second << std::endl; +} diff --git a/dep/jwt-cpp/example/jwks-verify.cpp b/dep/jwt-cpp/example/jwks-verify.cpp new file mode 100644 index 000000000..2464a5fe6 --- /dev/null +++ b/dep/jwt-cpp/example/jwks-verify.cpp @@ -0,0 +1,57 @@ +#include +#include + +int main() { + std::string raw_jwks = + R"({"keys": [{ + "kid":"internal-gateway-jwt.api.sc.net", + "alg": "RS256", + "kty": "RSA", + "use": "sig", + "x5c": [ + "MIIC+DCCAeCgAwIBAgIJBIGjYW6hFpn2MA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTAeFw0xNjExMjIyMjIyMDVaFw0zMDA4MDEyMjIyMDVaMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnjZc5bm/eGIHq09N9HKHahM7Y31P0ul+A2wwP4lSpIwFrWHzxw88/7Dwk9QMc+orGXX95R6av4GF+Es/nG3uK45ooMVMa/hYCh0Mtx3gnSuoTavQEkLzCvSwTqVwzZ+5noukWVqJuMKNwjL77GNcPLY7Xy2/skMCT5bR8UoWaufooQvYq6SyPcRAU4BtdquZRiBT4U5f+4pwNTxSvey7ki50yc1tG49Per/0zA4O6Tlpv8x7Red6m1bCNHt7+Z5nSl3RX/QYyAEUX1a28VcYmR41Osy+o2OUCXYdUAphDaHo4/8rbKTJhlu8jEcc1KoMXAKjgaVZtG/v5ltx6AXY0CAwEAAaMvMC0wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUQxFG602h1cG+pnyvJoy9pGJJoCswDQYJKoZIhvcNAQEFBQADggEBAGvtCbzGNBUJPLICth3mLsX0Z4z8T8iu4tyoiuAshP/Ry/ZBnFnXmhD8vwgMZ2lTgUWwlrvlgN+fAtYKnwFO2G3BOCFw96Nm8So9sjTda9CCZ3dhoH57F/hVMBB0K6xhklAc0b5ZxUpCIN92v/w+xZoz1XQBHe8ZbRHaP1HpRM4M7DJk2G5cgUCyu3UBvYS41sHvzrxQ3z7vIePRA4WF4bEkfX12gvny0RsPkrbVMXX1Rj9t6V7QXrbPYBAO+43JvDGYawxYVvLhz+BJ45x50GFQmHszfY3BR9TPK8xmMmQwtIvLu1PMttNCs7niCYkSiUv2sc2mlq1i3IashGkkgmo=" + ], + "n": "yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz-cbe4rjmigxUxr-FgKHQy3HeCdK6hNq9ASQvMK9LBOpXDNn7mei6RZWom4wo3CMvvsY1w8tjtfLb-yQwJPltHxShZq5-ihC9irpLI9xEBTgG12q5lGIFPhTl_7inA1PFK97LuSLnTJzW0bj096v_TMDg7pOWm_zHtF53qbVsI0e3v5nmdKXdFf9BjIARRfVrbxVxiZHjU6zL6jY5QJdh1QCmENoejj_ytspMmGW7yMRxzUqgxcAqOBpVm0b-_mW3HoBdjQ", + "e": "AQAB", + "x5t": "NjVBRjY5MDlCMUIwNzU4RTA2QzZFMDQ4QzQ2MDAyQjVDNjk1RTM2Qg" + }, +{ + "kid":"internal-123456", + "use":"sig", + "x5c":["MIIG1TCCBL2gAwIBAgIIFvMVGp6t\/cMwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0IxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMTUwMwYDVQQDDCxTdGFuZGFyZCBDaGFydGVyZWQgQmFuayBTaWduaW5nIENBIEcxIC0gU0hBMjAeFw0xODEwMTAxMTI2MzVaFw0yMjEwMTAxMTI2MzVaMIG9MQswCQYDVQQGEwJTRzESMBAGA1UECAwJU2luZ2Fwb3JlMRIwEAYDVQQHDAlTaW5nYXBvcmUxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMRwwGgYDVQQLDBNGb3VuZGF0aW9uIFNlcnZpY2VzMSgwJgYDVQQDDB9pbnRlcm5hbC1nYXRld2F5LWp3dC5hcGkuc2MubmV0MRwwGgYJKoZIhvcNAQkBFg1BUElQU1NAc2MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVWBoIi3IJ4nOWXu7\/SDxczqMou1B+c4c2FdQrOXrK31HxAaz4WEtma9BLXFdFHJ5mCCPIvdUcVxxnCynqhMOkZ\/a7acQbUD9cDzI8isMB9JL7VooDw0CctxHxffjqQQVIEhC2Q7zsM1pQayR7cl+pbBlvHIoRxq2n1B0fFvfoiosjf4kDiCpgHdM+v5Hw9aVYmUbroHxmQWqhB0iRTJQPPLZqqQVC50A1Q\/96gkwoODyotc46Uy9wYEpdGrtDG\/thWay3fmMsjpWR0U25xFIrxTrfCGBblYpD7juukWWml2E9rtE2rHgUxbymxXjEw7xrMwcGrhOGyqwoBqJy1JVwIDAQABo4ICLTCCAikwZAYIKwYBBQUHAQEEWDBWMFQGCCsGAQUFBzABhkhodHRwOi8vY29yZW9jc3AuZ2xvYmFsLnN0YW5kYXJkY2hhcnRlcmVkLmNvbS9lamJjYS9wdWJsaWN3ZWIvc3RhdHVzL29jc3AwHQYDVR0OBBYEFIinW4BNDeVEFcuLf8YjZjtySoW9MAwGA1UdEwEB\/wQCMAAwHwYDVR0jBBgwFoAUfNZMoZi33nKrcmVU3TFVQnuEi\/4wggFCBgNVHR8EggE5MIIBNTCCATGggcKggb+GgbxodHRwOi8vY29yZWNybC5nbG9iYWwuc3RhbmRhcmRjaGFydGVyZWQuY29tL2VqYmNhL3B1YmxpY3dlYi93ZWJkaXN0L2NlcnRkaXN0P2NtZD1jcmwmaXNzdWVyPUNOPVN0YW5kYXJkJTIwQ2hhcnRlcmVkJTIwQmFuayUyMFNpZ25pbmclMjBDQSUyMEcxJTIwLSUyMFNIQTIsTz1TdGFuZGFyZCUyMENoYXJ0ZXJlZCUyMEJhbmssQz1HQqJqpGgwZjE1MDMGA1UEAwwsU3RhbmRhcmQgQ2hhcnRlcmVkIEJhbmsgU2lnbmluZyBDQSBHMSAtIFNIQTIxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMQswCQYDVQQGEwJHQjAOBgNVHQ8BAf8EBAMCBsAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4ICAQBtsoRlDHuOTDChcWdfdVUtRgP0U0ijDSeJi8vULN1rgYnqqJc4PdJno50aiu9MGlxY02O7HW7ZVD6QEG\/pqHmZ0sbWpb\/fumMgZSjP65IcGuS53zgcNtLYnyXyEv+v5T\/CK3bk4Li6tUW3ScJPUwVWwP1E0\/u6aBSb5k\/h4lTwS1o88ybS5pJOg6XutXByp991QQrrs7tp7fKNynjNZbFuG3J1e09X+zTfJOpjaDUofQTkt8IyMRI6Cs4wI1eZA+dAIL8B0n8ze1mRl1FOJqgdZrAQjoqZkCTnc0Il5VY\/dUXxGVg6D9e5pfck3FWT107K9\/5EZoxytpqYXFCjMXi5hx4YjK17OUgm82mZhvqkNdzF8Yq2vFuB3LPfyelESq99xFLykvinrVm1NtZKeDTT1Jq\/VvZt6stO\/tovq1RfJJcznpYcwOzxlnhGR6E+hxuBx7aDJzGf0JaoRxQILH1B2XV9WDI3HPYQsP7XtriX+QUJ\/aly28QkV48RmaGYCsly43YZu1MKudSsw+dhnbZzRsg\/aes3dzGW2x137bQPtux7k2LCSpsTXgedhOys28YoGlsoe8kUv0myAU4Stt+I3mrwO3BKUn+tJggvlDiiiyT1tg2HiklyU\/2FxQkZRMeB0eRrXTpg3l9x2mpF+dDFxOMKszxwD2kgoEZgo6o58A=="], + "n":"nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e":"AQAB", + "x5t":"-qC0akuyiHTV5aFsKVWM9da7lzq6DLrj09I", + "alg":"RS256", + "kty":"RSA" + } +]})"; + + std::string token = + "eyJraWQiOiJpbnRlcm5hbC1nYXRld2F5LWp3dC5hcGkuc2MubmV0IiwiYWxnIjoiUlMyNTYiLCJ0eXAiOiJKV1QifQ." + "eyJuYmYiOjE1Mzk3NjcwMTUsImlhdCI6MTUzOTc2Njk5MiwiaXNzIjoia29uZyIsImh0dHA6XC9cL3dzbzIub3JnXC9nYXRld2F5XC9zdWJzY3" + "JpYmVyIjoidXZ0dXNlcjJAY2FyYm9uLnN1cGVyIiwib3JpZ2luYWxfaXNzIjoiaHR0cDpcL1wvd3NvMi5vcmdcL2dhdGV3YXkiLCJzdWIiOiJ1" + "dnR1c2VyMkBjYXJib24uc3VwZXIiLCJodHRwOlwvXC93c28yLm9yZ1wvZ2F0ZXdheVwvZW5kdXNlciI6InV2dHVzZXIyQGNhcmJvbi5zdXBlci" + "IsImp0aSI6IjI0NmJkZTlhLWQ4OGQtNGRlZC1hODhmLTRhMTNhOWJmODQ4ZiIsImh0dHA6XC9cL3dzbzIub3JnXC9nYXRld2F5XC9hcHBsaWNh" + "dGlvbm5hbWUiOiJ1dnR1c2VyMl9hcHBfMSIsImV4cCI6MTUzOTc2NzkxNX0.foxbo6C30yr_wkF-5EkgtYUMG-4SXNfRsmewdT6MbE-" + "RXVkIPkVk8kDP41yRXmnk4OxburCqawiGlzzEhfHoFf0qv0qZEmwEXSdcyRw-czZTs6ACjWYe8kejOCVmpvUrq01NgOhTwgVg6pv93BlcmNY--" + "zytjx_9hlVm5SS1lZ0I21n45BIWu5JvBD51TZXEURb_XhL7RcF9I8mfzrRpB2fSHW38gj-nogsdOPA_y3S-hJKylmmaqmaQgTF-jP-" + "gYr6eqKyGPVwc6fLZ5zqAup59SefdPEY23-WWmHzj968jlsDSEiCp_YiYTnF3tHVLFWDsrprYKwNb0_p95tBmPA"; + + auto decoded_jwt = jwt::decode(token); + auto jwks = jwt::parse_jwks(raw_jwks); + auto jwk = jwks.get_jwk(decoded_jwt.get_key_id()); + + auto issuer = decoded_jwt.get_issuer(); + auto x5c = jwk.get_x5c_key_value(); + + if (!x5c.empty() && !issuer.empty()) { + auto verifier = + jwt::verify() + .allow_algorithm(jwt::algorithm::rs256(jwt::helper::convert_base64_der_to_pem(x5c), "", "", "")) + .with_issuer(issuer) + .leeway(60UL); // value in seconds, add some to compensate timeout + + verifier.verify(decoded_jwt); + } +} diff --git a/dep/jwt-cpp/example/partial-claim-verifier.cpp b/dep/jwt-cpp/example/partial-claim-verifier.cpp new file mode 100644 index 000000000..6093d3be9 --- /dev/null +++ b/dep/jwt-cpp/example/partial-claim-verifier.cpp @@ -0,0 +1,91 @@ +#include "jwt-cpp/traits/nlohmann-json/defaults.h" + +#include + +int main() { + std::string rsa_priv_key = R"(-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4ZtdaIrd1BPIJ +tfnF0TjIK5inQAXZ3XlCrUlJdP+XHwIRxdv1FsN12XyMYO/6ymLmo9ryoQeIrsXB +XYqlET3zfAY+diwCb0HEsVvhisthwMU4gZQu6TYW2s9LnXZB5rVtcBK69hcSlA2k +ZudMZWxZcj0L7KMfO2rIvaHw/qaVOE9j0T257Z8Kp2CLF9MUgX0ObhIsdumFRLaL +DvDUmBPr2zuh/34j2XmWwn1yjN/WvGtdfhXW79Ki1S40HcWnygHgLV8sESFKUxxQ +mKvPUTwDOIwLFL5WtE8Mz7N++kgmDcmWMCHc8kcOIu73Ta/3D4imW7VbKgHZo9+K +3ESFE3RjAgMBAAECggEBAJTEIyjMqUT24G2FKiS1TiHvShBkTlQdoR5xvpZMlYbN +tVWxUmrAGqCQ/TIjYnfpnzCDMLhdwT48Ab6mQJw69MfiXwc1PvwX1e9hRscGul36 +ryGPKIVQEBsQG/zc4/L2tZe8ut+qeaK7XuYrPp8bk/X1e9qK5m7j+JpKosNSLgJj +NIbYsBkG2Mlq671irKYj2hVZeaBQmWmZxK4fw0Istz2WfN5nUKUeJhTwpR+JLUg4 +ELYYoB7EO0Cej9UBG30hbgu4RyXA+VbptJ+H042K5QJROUbtnLWuuWosZ5ATldwO +u03dIXL0SH0ao5NcWBzxU4F2sBXZRGP2x/jiSLHcqoECgYEA4qD7mXQpu1b8XO8U +6abpKloJCatSAHzjgdR2eRDRx5PMvloipfwqA77pnbjTUFajqWQgOXsDTCjcdQui +wf5XAaWu+TeAVTytLQbSiTsBhrnoqVrr3RoyDQmdnwHT8aCMouOgcC5thP9vQ8Us +rVdjvRRbnJpg3BeSNimH+u9AHgsCgYEA0EzcbOltCWPHRAY7B3Ge/AKBjBQr86Kv +TdpTlxePBDVIlH+BM6oct2gaSZZoHbqPjbq5v7yf0fKVcXE4bSVgqfDJ/sZQu9Lp +PTeV7wkk0OsAMKk7QukEpPno5q6tOTNnFecpUhVLLlqbfqkB2baYYwLJR3IRzboJ +FQbLY93E8gkCgYB+zlC5VlQbbNqcLXJoImqItgQkkuW5PCgYdwcrSov2ve5r/Acz +FNt1aRdSlx4176R3nXyibQA1Vw+ztiUFowiP9WLoM3PtPZwwe4bGHmwGNHPIfwVG +m+exf9XgKKespYbLhc45tuC08DATnXoYK7O1EnUINSFJRS8cezSI5eHcbQKBgQDC +PgqHXZ2aVftqCc1eAaxaIRQhRmY+CgUjumaczRFGwVFveP9I6Gdi+Kca3DE3F9Pq +PKgejo0SwP5vDT+rOGHN14bmGJUMsX9i4MTmZUZ5s8s3lXh3ysfT+GAhTd6nKrIE +kM3Nh6HWFhROptfc6BNusRh1kX/cspDplK5x8EpJ0QKBgQDWFg6S2je0KtbV5PYe +RultUEe2C0jYMDQx+JYxbPmtcopvZQrFEur3WKVuLy5UAy7EBvwMnZwIG7OOohJb +vkSpADK6VPn9lbqq7O8cTedEHttm6otmLt8ZyEl3hZMaL3hbuRj6ysjmoFKx6CrX +rK0/Ikt5ybqUzKCMJZg2VKGTxg== +-----END PRIVATE KEY-----)"; + + auto role_claim = nlohmann::json{{"my-service", {{"roles", {"foo", "bar", "baz"}}}}}; + + auto token = jwt::create() + .set_issuer("auth0") + .set_type("JWT") + .set_id("rsa-create-example") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_payload_claim("resource-access", role_claim) + .sign(jwt::algorithm::rs256("", rsa_priv_key, "", "")); + + std::cout << "token: " << token << std::endl; + + std::string rsa_pub_key = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGbXWiK3dQTyCbX5xdE4 +yCuYp0AF2d15Qq1JSXT/lx8CEcXb9RbDddl8jGDv+spi5qPa8qEHiK7FwV2KpRE9 +83wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVs +WXI9C+yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT +69s7of9+I9l5lsJ9cozf1rxrXX4V1u/SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8 +AziMCxS+VrRPDM+zfvpIJg3JljAh3PJHDiLu902v9w+Iplu1WyoB2aPfitxEhRN0 +YwIDAQAB +-----END PUBLIC KEY-----)"; + + auto decoded = jwt::decode(token); + + for (const auto& e : decoded.get_payload_json()) + std::cout << e.first << " = " << e.second << std::endl; + + std::cout << std::endl; + + auto role_verifier = [](const jwt::verify_context& ctx, std::error_code& ec) { + using error = jwt::error::token_verification_error; + + auto c = ctx.get_claim(false, ec); + if (ec) return; + if (c.get_type() == jwt::json::type::object) { + auto obj = c.to_json(); + try { + auto roles = obj["my-service"]["roles"].get(); + if (roles.end() == std::find(roles.begin(), roles.end(), "foo")) ec = error::claim_value_missmatch; + } catch (const std::exception& ex) { ec = error::claim_value_missmatch; } + } else + ec = error::claim_type_missmatch; + }; + + auto verifier = jwt::verify() + .allow_algorithm(jwt::algorithm::rs256(rsa_pub_key, "", "", "")) + .with_issuer("auth0") + .with_claim("resource-access", role_verifier); + + try { + verifier.verify(decoded); + std::cout << "Success!" << std::endl; + } catch (const std::exception& ex) { std::cout << "Error: " << ex.what() << std::endl; } + + return 0; +} diff --git a/dep/jwt-cpp/example/print-claims.cpp b/dep/jwt-cpp/example/print-claims.cpp new file mode 100644 index 000000000..8dd05abba --- /dev/null +++ b/dep/jwt-cpp/example/print-claims.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main() { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + auto decoded = jwt::decode(token); + + for (auto& e : decoded.get_payload_json()) + std::cout << e.first << " = " << e.second << std::endl; +} diff --git a/dep/jwt-cpp/example/private-claims.cpp b/dep/jwt-cpp/example/private-claims.cpp new file mode 100644 index 000000000..97c84ae6c --- /dev/null +++ b/dep/jwt-cpp/example/private-claims.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include + +using sec = std::chrono::seconds; +using min = std::chrono::minutes; + +int main() { + jwt::claim from_raw_json; + std::istringstream iss{R"##({"api":{"array":[1,2,3],"null":null}})##"}; + iss >> from_raw_json; + + jwt::claim::set_t list{"once", "twice"}; + std::vector big_numbers{727663072ULL, 770979831ULL, 427239169ULL, 525936436ULL}; + + const auto time = jwt::date::clock::now(); + const auto token = jwt::create() + .set_type("JWT") + .set_issuer("auth.mydomain.io") + .set_audience("mydomain.io") + .set_issued_at(time) + .set_not_before(time + sec{15}) + .set_expires_at(time + sec{15} + min{2}) + .set_payload_claim("boolean", picojson::value(true)) + .set_payload_claim("integer", picojson::value(int64_t{12345})) + .set_payload_claim("precision", picojson::value(12.345)) + .set_payload_claim("strings", jwt::claim(list)) + .set_payload_claim("array", jwt::claim(big_numbers.begin(), big_numbers.end())) + .set_payload_claim("object", from_raw_json) + .sign(jwt::algorithm::none{}); + + const auto decoded = jwt::decode(token); + + const auto api_array = decoded.get_payload_claim("object").to_json().get("api").get("array"); + std::cout << "api array = " << api_array << std::endl; + + jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth.mydomain.io") + .with_audience("mydomain.io") + .with_claim("object", from_raw_json) + .verify(decoded); + + return 0; +} diff --git a/dep/jwt-cpp/example/rsa-create.cpp b/dep/jwt-cpp/example/rsa-create.cpp new file mode 100644 index 000000000..16ab8f88b --- /dev/null +++ b/dep/jwt-cpp/example/rsa-create.cpp @@ -0,0 +1,44 @@ +#include +#include + +int main() { + std::string rsa_priv_key = R"(-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4ZtdaIrd1BPIJ +tfnF0TjIK5inQAXZ3XlCrUlJdP+XHwIRxdv1FsN12XyMYO/6ymLmo9ryoQeIrsXB +XYqlET3zfAY+diwCb0HEsVvhisthwMU4gZQu6TYW2s9LnXZB5rVtcBK69hcSlA2k +ZudMZWxZcj0L7KMfO2rIvaHw/qaVOE9j0T257Z8Kp2CLF9MUgX0ObhIsdumFRLaL +DvDUmBPr2zuh/34j2XmWwn1yjN/WvGtdfhXW79Ki1S40HcWnygHgLV8sESFKUxxQ +mKvPUTwDOIwLFL5WtE8Mz7N++kgmDcmWMCHc8kcOIu73Ta/3D4imW7VbKgHZo9+K +3ESFE3RjAgMBAAECggEBAJTEIyjMqUT24G2FKiS1TiHvShBkTlQdoR5xvpZMlYbN +tVWxUmrAGqCQ/TIjYnfpnzCDMLhdwT48Ab6mQJw69MfiXwc1PvwX1e9hRscGul36 +ryGPKIVQEBsQG/zc4/L2tZe8ut+qeaK7XuYrPp8bk/X1e9qK5m7j+JpKosNSLgJj +NIbYsBkG2Mlq671irKYj2hVZeaBQmWmZxK4fw0Istz2WfN5nUKUeJhTwpR+JLUg4 +ELYYoB7EO0Cej9UBG30hbgu4RyXA+VbptJ+H042K5QJROUbtnLWuuWosZ5ATldwO +u03dIXL0SH0ao5NcWBzxU4F2sBXZRGP2x/jiSLHcqoECgYEA4qD7mXQpu1b8XO8U +6abpKloJCatSAHzjgdR2eRDRx5PMvloipfwqA77pnbjTUFajqWQgOXsDTCjcdQui +wf5XAaWu+TeAVTytLQbSiTsBhrnoqVrr3RoyDQmdnwHT8aCMouOgcC5thP9vQ8Us +rVdjvRRbnJpg3BeSNimH+u9AHgsCgYEA0EzcbOltCWPHRAY7B3Ge/AKBjBQr86Kv +TdpTlxePBDVIlH+BM6oct2gaSZZoHbqPjbq5v7yf0fKVcXE4bSVgqfDJ/sZQu9Lp +PTeV7wkk0OsAMKk7QukEpPno5q6tOTNnFecpUhVLLlqbfqkB2baYYwLJR3IRzboJ +FQbLY93E8gkCgYB+zlC5VlQbbNqcLXJoImqItgQkkuW5PCgYdwcrSov2ve5r/Acz +FNt1aRdSlx4176R3nXyibQA1Vw+ztiUFowiP9WLoM3PtPZwwe4bGHmwGNHPIfwVG +m+exf9XgKKespYbLhc45tuC08DATnXoYK7O1EnUINSFJRS8cezSI5eHcbQKBgQDC +PgqHXZ2aVftqCc1eAaxaIRQhRmY+CgUjumaczRFGwVFveP9I6Gdi+Kca3DE3F9Pq +PKgejo0SwP5vDT+rOGHN14bmGJUMsX9i4MTmZUZ5s8s3lXh3ysfT+GAhTd6nKrIE +kM3Nh6HWFhROptfc6BNusRh1kX/cspDplK5x8EpJ0QKBgQDWFg6S2je0KtbV5PYe +RultUEe2C0jYMDQx+JYxbPmtcopvZQrFEur3WKVuLy5UAy7EBvwMnZwIG7OOohJb +vkSpADK6VPn9lbqq7O8cTedEHttm6otmLt8ZyEl3hZMaL3hbuRj6ysjmoFKx6CrX +rK0/Ikt5ybqUzKCMJZg2VKGTxg== +-----END PRIVATE KEY-----)"; + + auto token = jwt::create() + .set_issuer("auth0") + .set_type("JWT") + .set_id("rsa-create-example") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{36000}) + .set_payload_claim("sample", jwt::claim(std::string{"test"})) + .sign(jwt::algorithm::rs256("", rsa_priv_key, "", "")); + + std::cout << "token:\n" << token << std::endl; +} diff --git a/dep/jwt-cpp/example/rsa-verify.cpp b/dep/jwt-cpp/example/rsa-verify.cpp new file mode 100644 index 000000000..e2af4095d --- /dev/null +++ b/dep/jwt-cpp/example/rsa-verify.cpp @@ -0,0 +1,34 @@ +#include +#include + +int main() { + std::string rsa_pub_key = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGbXWiK3dQTyCbX5xdE4 +yCuYp0AF2d15Qq1JSXT/lx8CEcXb9RbDddl8jGDv+spi5qPa8qEHiK7FwV2KpRE9 +83wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVs +WXI9C+yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT +69s7of9+I9l5lsJ9cozf1rxrXX4V1u/SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8 +AziMCxS+VrRPDM+zfvpIJg3JljAh3PJHDiLu902v9w+Iplu1WyoB2aPfitxEhRN0 +YwIDAQAB +-----END PUBLIC KEY-----)"; + + std::string token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9." + "VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-" + "GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-" + "IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-" + "uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::rs256(rsa_pub_key, "", "", "")).with_issuer("auth0"); + + auto decoded = jwt::decode(token); + + verify.verify(decoded); + + for (auto& e : decoded.get_header_json()) + std::cout << e.first << " = " << e.second << std::endl; + for (auto& e : decoded.get_payload_json()) + std::cout << e.first << " = " << e.second << std::endl; +} diff --git a/dep/jwt-cpp/example/traits/CMakeLists.txt b/dep/jwt-cpp/example/traits/CMakeLists.txt new file mode 100644 index 000000000..42f88d54f --- /dev/null +++ b/dep/jwt-cpp/example/traits/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.8) +project(jwt-cpp-traits) + +if(NOT TARGET jwt-cpp) + find_package(jwt-cpp CONFIG REQUIRED) +endif() + +find_package(jsoncons CONFIG) +if(TARGET jsoncons) + add_executable(danielaparker-jsoncons danielaparker-jsoncons.cpp) + target_link_libraries(danielaparker-jsoncons jwt-cpp::jwt-cpp jsoncons) +endif() + +include("../../cmake/private-find-boost-json.cmake") +if(TARGET boost_json) + add_executable(boost-json boost-json.cpp) + target_link_libraries(boost-json jwt-cpp::jwt-cpp boost_json) +endif() + +find_package(nlohmann_json CONFIG) +if(TARGET nlohmann_json::nlohmann_json) + add_executable(nlohmann-json nlohmann-json.cpp) + target_link_libraries(nlohmann-json nlohmann_json::nlohmann_json jwt-cpp::jwt-cpp) +endif() + +include("../../cmake/private-find-kazuho-picojson.cmake") +if(TARGET kazuho_picojson) + add_executable(kazuho-picojson kazuho-picojson.cpp) + target_link_libraries(kazuho-picojson jwt-cpp::jwt-cpp kazuho_picojson) +endif() diff --git a/dep/jwt-cpp/example/traits/README.md b/dep/jwt-cpp/example/traits/README.md new file mode 100644 index 000000000..c31464b54 --- /dev/null +++ b/dep/jwt-cpp/example/traits/README.md @@ -0,0 +1,6 @@ +# Traits Examples + +These example require upstream CMake installation to work. There are exceptions: + +- For Boost.JSON headers must be located by custom CMake. +- For PicoJSON headers must be located by custom CMake. diff --git a/dep/jwt-cpp/example/traits/boost-json.cpp b/dep/jwt-cpp/example/traits/boost-json.cpp new file mode 100644 index 000000000..59c585eea --- /dev/null +++ b/dep/jwt-cpp/example/traits/boost-json.cpp @@ -0,0 +1,52 @@ +#include "jwt-cpp/traits/boost-json/traits.h" + +// #include // You may require this if you are not building it elsewhere +#include +#include + +int main() { + using sec = std::chrono::seconds; + using min = std::chrono::minutes; + using traits = jwt::traits::boost_json; + using claim = jwt::basic_claim; + + traits::value_type raw_value; + traits::parse(raw_value, R"##({"api":{"array":[1,2,3],"null":null}})##"); + claim from_raw_json(raw_value); + + claim::set_t list{"once", "twice"}; + std::vector big_numbers{727663072ULL, 770979831ULL, 427239169ULL, 525936436ULL}; + + const auto time = jwt::date::clock::now(); + const auto token = jwt::create() + .set_type("JWT") + .set_issuer("auth.mydomain.io") + .set_audience("mydomain.io") + .set_issued_at(time) + .set_not_before(time) + .set_expires_at(time + min{2} + sec{15}) + .set_payload_claim("boolean", true) + .set_payload_claim("integer", 12345) + .set_payload_claim("precision", 12.3456789) + .set_payload_claim("strings", claim(list)) + .set_payload_claim("array", claim{big_numbers.begin(), big_numbers.end()}) + .set_payload_claim("object", from_raw_json) + .sign(jwt::algorithm::none{}); + const auto decoded = jwt::decode(token); + + for (auto& e : decoded.get_header_json()) + std::cout << e.key() << " = " << e.value() << std::endl; + + const auto array = + traits::as_array(decoded.get_payload_claim("object").to_json().as_object()["api"].as_object()["array"]); + std::cout << "payload /object/api/array = " << array << std::endl; + + jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth.mydomain.io") + .with_audience("mydomain.io") + .with_claim("object", from_raw_json) + .verify(decoded); + + return 0; +} diff --git a/dep/jwt-cpp/example/traits/danielaparker-jsoncons.cpp b/dep/jwt-cpp/example/traits/danielaparker-jsoncons.cpp new file mode 100644 index 000000000..5eac313ce --- /dev/null +++ b/dep/jwt-cpp/example/traits/danielaparker-jsoncons.cpp @@ -0,0 +1,47 @@ +#include "jwt-cpp/traits/danielaparker-jsoncons/traits.h" + +#include +#include + +int main() { + using sec = std::chrono::seconds; + using min = std::chrono::minutes; + using traits = jwt::traits::danielaparker_jsoncons; + using claim = jwt::basic_claim; + + claim from_raw_json; + std::istringstream iss{R"##({"api":{"array":[1,2,3],"null":null}})##"}; + iss >> from_raw_json; + + claim::set_t list{"once", "twice"}; + std::vector big_numbers{727663072ULL, 770979831ULL, 427239169ULL, 525936436ULL}; + + const auto time = jwt::date::clock::now(); + const auto token = jwt::create() + .set_type("JWT") + .set_issuer("auth.mydomain.io") + .set_audience("mydomain.io") + .set_issued_at(time) + .set_not_before(time) + .set_expires_at(time + min{2} + sec{15}) + .set_payload_claim("boolean", true) + .set_payload_claim("integer", 12345) + .set_payload_claim("precision", 12.3456789) + .set_payload_claim("strings", list) + .set_payload_claim("array", {big_numbers.begin(), big_numbers.end()}) + .set_payload_claim("object", from_raw_json) + .sign(jwt::algorithm::none{}); + const auto decoded = jwt::decode(token); + + const auto array = traits::as_array(decoded.get_payload_claim("object").to_json()["api"]["array"]); + std::cout << "payload /object/api/array = " << array << std::endl; + + jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth.mydomain.io") + .with_audience("mydomain.io") + .with_claim("object", from_raw_json) + .verify(decoded); + + return 0; +} diff --git a/dep/jwt-cpp/example/traits/kazuho-picojson.cpp b/dep/jwt-cpp/example/traits/kazuho-picojson.cpp new file mode 100644 index 000000000..16724007b --- /dev/null +++ b/dep/jwt-cpp/example/traits/kazuho-picojson.cpp @@ -0,0 +1,47 @@ +#include "jwt-cpp/traits/kazuho-picojson/traits.h" + +#include +#include + +int main() { + using sec = std::chrono::seconds; + using min = std::chrono::minutes; + using traits = jwt::traits::kazuho_picojson; + using claim = jwt::basic_claim; + + claim from_raw_json; + std::istringstream iss{R"##({"api":{"array":[1,2,3],"null":null}})##"}; + iss >> from_raw_json; + + claim::set_t list{"once", "twice"}; + std::vector big_numbers{727663072ULL, 770979831ULL, 427239169ULL, 525936436ULL}; + + const auto time = jwt::date::clock::now(); + const auto token = jwt::create() + .set_type("JWT") + .set_issuer("auth.mydomain.io") + .set_audience("mydomain.io") + .set_issued_at(time) + .set_not_before(time) + .set_expires_at(time + min{2} + sec{15}) + .set_payload_claim("boolean", picojson::value(true)) + .set_payload_claim("integer", picojson::value(int64_t{12345})) + .set_payload_claim("precision", picojson::value(12.345)) + .set_payload_claim("strings", claim(list)) + .set_payload_claim("array", claim(big_numbers.begin(), big_numbers.end())) + .set_payload_claim("object", from_raw_json) + .sign(jwt::algorithm::none{}); + const auto decoded = jwt::decode(token); + + const auto api_array = decoded.get_payload_claim("object").to_json().get("api").get("array"); + std::cout << "api array = " << api_array << std::endl; + + jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth.mydomain.io") + .with_audience("mydomain.io") + .with_claim("object", from_raw_json) + .verify(decoded); + + return 0; +} diff --git a/dep/jwt-cpp/example/traits/nlohmann-json.cpp b/dep/jwt-cpp/example/traits/nlohmann-json.cpp new file mode 100644 index 000000000..00fa2acd0 --- /dev/null +++ b/dep/jwt-cpp/example/traits/nlohmann-json.cpp @@ -0,0 +1,47 @@ +#include "jwt-cpp/traits/nlohmann-json/traits.h" + +#include +#include + +int main() { + using sec = std::chrono::seconds; + using min = std::chrono::minutes; + using traits = jwt::traits::nlohmann_json; + using claim = jwt::basic_claim; + + claim from_raw_json; + std::istringstream iss{R"##({"api":{"array":[1,2,3],"null":null}})##"}; + iss >> from_raw_json; + + claim::set_t list{"once", "twice"}; + std::vector big_numbers{727663072ULL, 770979831ULL, 427239169ULL, 525936436ULL}; + + const auto time = jwt::date::clock::now(); + const auto token = jwt::create() + .set_type("JWT") + .set_issuer("auth.mydomain.io") + .set_audience("mydomain.io") + .set_issued_at(time) + .set_not_before(time) + .set_expires_at(time + min{2} + sec{15}) + .set_payload_claim("boolean", true) + .set_payload_claim("integer", 12345) + .set_payload_claim("precision", 12.3456789) + .set_payload_claim("strings", list) + .set_payload_claim("array", {big_numbers.begin(), big_numbers.end()}) + .set_payload_claim("object", from_raw_json) + .sign(jwt::algorithm::none{}); + const auto decoded = jwt::decode(token); + + const auto array = traits::as_array(decoded.get_payload_claim("object").to_json()["api"]["array"]); + std::cout << "payload /object/api/array = " << array << std::endl; + + jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth.mydomain.io") + .with_audience("mydomain.io") + .with_claim("object", from_raw_json) + .verify(decoded); + + return 0; +} diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/defaults.h b/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/defaults.h new file mode 100644 index 000000000..affeffe84 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/defaults.h @@ -0,0 +1,88 @@ +#ifndef JWT_CPP_BOOST_JSON_DEFAULTS_H +#define JWT_CPP_BOOST_JSON_DEFAULTS_H + +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif + +#include "traits.h" + +namespace jwt { + /** + * \brief a class to store a generic [Boost.JSON](https://github.com/boostorg/json) value as claim + * + * This type is the specialization of the \ref basic_claim class which + * uses the standard template types. + */ + using claim = basic_claim; + + /** + * Create a verifier using the default clock + * \return verifier instance + */ + inline verifier verify() { + return verify(default_clock{}); + } + + /** + * Return a builder instance to create a new token + */ + inline builder create() { return builder(); } + +#ifndef JWT_DISABLE_BASE64 + /** + * Decode a token + * \param token Token to decode + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); + } +#endif + + /** + * Decode a token + * \tparam Decode is callabled, taking a string_type and returns a string_type. + * It should ensure the padding of the input and then base64url decode and + * return the results. + * \param token Token to decode + * \param decode The token to parse + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + template + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); + } + + /** + * Parse a jwk + * \param token JWK Token to parse + * \return Parsed JWK + * \throw std::runtime_error Token is not in correct format + */ + inline jwk parse_jwk(const traits::boost_json::string_type& token) { + return jwk(token); + } + + /** + * Parse a jwks + * \param token JWKs Token to parse + * \return Parsed JWKs + * \throw std::runtime_error Token is not in correct format + */ + inline jwks parse_jwks(const traits::boost_json::string_type& token) { + return jwks(token); + } + + /** + * This type is the specialization of the \ref verify_ops::verify_context class which + * uses the standard template types. + */ + using verify_context = verify_ops::verify_context; +} // namespace jwt + +#endif // JWT_CPP_BOOST_JSON_DEFAULTS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/traits.h b/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/traits.h new file mode 100644 index 000000000..3b27d5f2f --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/boost-json/traits.h @@ -0,0 +1,80 @@ +#ifndef JWT_CPP_BOOSTJSON_TRAITS_H +#define JWT_CPP_BOOSTJSON_TRAITS_H + +#define JWT_DISABLE_PICOJSON +#include "jwt-cpp/jwt.h" + +#include +// if not boost JSON standalone then error... + +namespace jwt { + namespace traits { + namespace json = boost::json; + struct boost_json { + using value_type = json::value; + using object_type = json::object; + using array_type = json::array; + using string_type = std::string; + using number_type = double; + using integer_type = std::int64_t; + using boolean_type = bool; + + static jwt::json::type get_type(const value_type& val) { + using jwt::json::type; + + if (val.kind() == json::kind::bool_) return type::boolean; + if (val.kind() == json::kind::int64) return type::integer; + if (val.kind() == json::kind::uint64) // boost internally tracks two types of integers + return type::integer; + if (val.kind() == json::kind::double_) return type::number; + if (val.kind() == json::kind::string) return type::string; + if (val.kind() == json::kind::array) return type::array; + if (val.kind() == json::kind::object) return type::object; + + throw std::logic_error("invalid type"); + } + + static object_type as_object(const value_type& val) { + if (val.kind() != json::kind::object) throw std::bad_cast(); + return val.get_object(); + } + + static array_type as_array(const value_type& val) { + if (val.kind() != json::kind::array) throw std::bad_cast(); + return val.get_array(); + } + + static string_type as_string(const value_type& val) { + if (val.kind() != json::kind::string) throw std::bad_cast(); + return string_type{val.get_string()}; + } + + static integer_type as_integer(const value_type& val) { + switch (val.kind()) { + case json::kind::int64: return val.get_int64(); + case json::kind::uint64: return static_cast(val.get_uint64()); + default: throw std::bad_cast(); + } + } + + static boolean_type as_boolean(const value_type& val) { + if (val.kind() != json::kind::bool_) throw std::bad_cast(); + return val.get_bool(); + } + + static number_type as_number(const value_type& val) { + if (val.kind() != json::kind::double_) throw std::bad_cast(); + return val.get_double(); + } + + static bool parse(value_type& val, string_type str) { + val = json::parse(str); + return true; + } + + static std::string serialize(const value_type& val) { return json::serialize(val); } + }; + } // namespace traits +} // namespace jwt + +#endif // JWT_CPP_BOOSTJSON_TRAITS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h b/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h new file mode 100644 index 000000000..47e12f5f0 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/defaults.h @@ -0,0 +1,88 @@ +#ifndef JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H +#define JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H + +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif + +#include "traits.h" + +namespace jwt { + /** + * \brief a class to store a generic [jsoncons](https://github.com/danielaparker/jsoncons) value as claim + * + * This type is the specialization of the \ref basic_claim class which + * uses the standard template types. + */ + using claim = basic_claim; + + /** + * Create a verifier using the default clock + * \return verifier instance + */ + inline verifier verify() { + return verify(default_clock{}); + } + + /** + * Return a builder instance to create a new token + */ + inline builder create() { return builder(); } + +#ifndef JWT_DISABLE_BASE64 + /** + * Decode a token + * \param token Token to decode + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); + } +#endif + + /** + * Decode a token + * \tparam Decode is callabled, taking a string_type and returns a string_type. + * It should ensure the padding of the input and then base64url decode and + * return the results. + * \param token Token to decode + * \param decode The token to parse + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + template + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); + } + + /** + * Parse a jwk + * \param token JWK Token to parse + * \return Parsed JWK + * \throw std::runtime_error Token is not in correct format + */ + inline jwk parse_jwk(const traits::danielaparker_jsoncons::string_type& token) { + return jwk(token); + } + + /** + * Parse a jwks + * \param token JWKs Token to parse + * \return Parsed JWKs + * \throw std::runtime_error Token is not in correct format + */ + inline jwks parse_jwks(const traits::danielaparker_jsoncons::string_type& token) { + return jwks(token); + } + + /** + * This type is the specialization of the \ref verify_ops::verify_context class which + * uses the standard template types. + */ + using verify_context = verify_ops::verify_context; +} // namespace jwt + +#endif // JWT_CPP_DANIELAPARKER_JSONCONS_DEFAULTS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/traits.h b/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/traits.h new file mode 100644 index 000000000..be56740ca --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/danielaparker-jsoncons/traits.h @@ -0,0 +1,123 @@ +#define JWT_DISABLE_PICOJSON +#define JSONCONS_NO_DEPRECATED + +#include "jwt-cpp/jwt.h" + +#include "jsoncons/json.hpp" + +#include + +namespace jwt { + namespace traits { + struct danielaparker_jsoncons { + // Needs at least https://github.com/danielaparker/jsoncons/commit/28c56b90ec7337f98a5b8942574590111a5e5831 + static_assert(jsoncons::version().minor >= 167, "A higher version of jsoncons is required!"); + + using json = jsoncons::json; + using value_type = json; + struct object_type : json::object { + // Add missing C++11 member types + // https://github.com/danielaparker/jsoncons/commit/1b1ceeb572f9a2db6d37cff47ac78a4f14e072e2#commitcomment-45391411 + using value_type = key_value_type; // Enable optional jwt-cpp methods + using mapped_type = key_value_type::value_type; + using size_type = size_t; // for implementing count + + object_type() = default; + object_type(const object_type&) = default; + explicit object_type(const json::object& o) : json::object(o) {} + object_type(object_type&&) = default; + explicit object_type(json::object&& o) : json::object(o) {} + ~object_type() = default; + object_type& operator=(const object_type& o) = default; + object_type& operator=(object_type&& o) noexcept = default; + + // Add missing C++11 subscription operator + mapped_type& operator[](const key_type& key) { + // https://github.com/microsoft/STL/blob/2914b4301c59dc7ffc09d16ac6f7979fde2b7f2c/stl/inc/map#L325 + return try_emplace(key).first->value(); + } + + // Add missing C++11 element access + const mapped_type& at(const key_type& key) const { + auto target = find(key); + if (target != end()) return target->value(); + + throw std::out_of_range("invalid key"); + } + + // Add missing C++11 lookup method + size_type count(const key_type& key) const { + struct compare { + bool operator()(const value_type& val, const key_type& key) const { return val.key() < key; } + bool operator()(const key_type& key, const value_type& val) const { return key < val.key(); } + }; + + // https://en.cppreference.com/w/cpp/algorithm/binary_search#Complexity + if (std::binary_search(this->begin(), this->end(), key, compare{})) return 1; + return 0; + } + }; + using array_type = json::array; + using string_type = std::string; // current limitation of traits implementation + using number_type = double; + using integer_type = int64_t; + using boolean_type = bool; + + static jwt::json::type get_type(const json& val) { + using jwt::json::type; + + if (val.type() == jsoncons::json_type::bool_value) return type::boolean; + if (val.type() == jsoncons::json_type::int64_value) return type::integer; + if (val.type() == jsoncons::json_type::uint64_value) return type::integer; + if (val.type() == jsoncons::json_type::half_value) return type::number; + if (val.type() == jsoncons::json_type::double_value) return type::number; + if (val.type() == jsoncons::json_type::string_value) return type::string; + if (val.type() == jsoncons::json_type::array_value) return type::array; + if (val.type() == jsoncons::json_type::object_value) return type::object; + + throw std::logic_error("invalid type"); + } + + static object_type as_object(const json& val) { + if (val.type() != jsoncons::json_type::object_value) throw std::bad_cast(); + return object_type(val.object_value()); + } + + static array_type as_array(const json& val) { + if (val.type() != jsoncons::json_type::array_value) throw std::bad_cast(); + return val.array_value(); + } + + static string_type as_string(const json& val) { + if (val.type() != jsoncons::json_type::string_value) throw std::bad_cast(); + return val.as_string(); + } + + static number_type as_number(const json& val) { + if (get_type(val) != jwt::json::type::number) throw std::bad_cast(); + return val.as_double(); + } + + static integer_type as_integer(const json& val) { + if (get_type(val) != jwt::json::type::integer) throw std::bad_cast(); + return val.as(); + } + + static boolean_type as_boolean(const json& val) { + if (val.type() != jsoncons::json_type::bool_value) throw std::bad_cast(); + return val.as_bool(); + } + + static bool parse(json& val, const std::string& str) { + val = json::parse(str); + return true; + } + + static std::string serialize(const json& val) { + std::ostringstream os; + os << jsoncons::print(val); + return os.str(); + } + }; + } // namespace traits +} // namespace jwt diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/defaults.h.mustache b/dep/jwt-cpp/include/jwt-cpp/traits/defaults.h.mustache new file mode 100644 index 000000000..ab2a84721 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/defaults.h.mustache @@ -0,0 +1,90 @@ +#ifndef JWT_CPP_{{traits_name_upper}}_DEFAULTS_H +#define JWT_CPP_{{traits_name_upper}}_DEFAULTS_H +{{#disable_default_traits}} + +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif +{{/disable_default_traits}} + +#include "traits.h" + +namespace jwt { + /** + * \brief a class to store a generic [{{library_name}}]({{{library_url}}}) value as claim + * + * This type is the specialization of the \ref basic_claim class which + * uses the standard template types. + */ + using claim = basic_claim; + + /** + * Create a verifier using the default clock + * \return verifier instance + */ + inline verifier verify() { + return verify(default_clock{}); + } + + /** + * Return a builder instance to create a new token + */ + inline builder create() { return builder(); } + +#ifndef JWT_DISABLE_BASE64 + /** + * Decode a token + * \param token Token to decode + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); + } +#endif + + /** + * Decode a token + * \tparam Decode is callabled, taking a string_type and returns a string_type. + * It should ensure the padding of the input and then base64url decode and + * return the results. + * \param token Token to decode + * \param decode The token to parse + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + template + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); + } + + /** + * Parse a jwk + * \param token JWK Token to parse + * \return Parsed JWK + * \throw std::runtime_error Token is not in correct format + */ + inline jwk parse_jwk(const traits::{{traits_name}}::string_type& token) { + return jwk(token); + } + + /** + * Parse a jwks + * \param token JWKs Token to parse + * \return Parsed JWKs + * \throw std::runtime_error Token is not in correct format + */ + inline jwks parse_jwks(const traits::{{traits_name}}::string_type& token) { + return jwks(token); + } + + /** + * This type is the specialization of the \ref verify_ops::verify_context class which + * uses the standard template types. + */ + using verify_context = verify_ops::verify_context; +} // namespace jwt + +#endif // JWT_CPP_{{traits_name_upper}}_DEFAULTS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/defaults.h b/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/defaults.h new file mode 100644 index 000000000..0c82133a6 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/defaults.h @@ -0,0 +1,84 @@ +#ifndef JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H +#define JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H + +#include "traits.h" + +namespace jwt { + /** + * \brief a class to store a generic [picojson](https://github.com/kazuho/picojson) value as claim + * + * This type is the specialization of the \ref basic_claim class which + * uses the standard template types. + */ + using claim = basic_claim; + + /** + * Create a verifier using the default clock + * \return verifier instance + */ + inline verifier verify() { + return verify(default_clock{}); + } + + /** + * Return a builder instance to create a new token + */ + inline builder create() { return builder(); } + +#ifndef JWT_DISABLE_BASE64 + /** + * Decode a token + * \param token Token to decode + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); + } +#endif + + /** + * Decode a token + * \tparam Decode is callabled, taking a string_type and returns a string_type. + * It should ensure the padding of the input and then base64url decode and + * return the results. + * \param token Token to decode + * \param decode The token to parse + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + template + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); + } + + /** + * Parse a jwk + * \param token JWK Token to parse + * \return Parsed JWK + * \throw std::runtime_error Token is not in correct format + */ + inline jwk parse_jwk(const traits::kazuho_picojson::string_type& token) { + return jwk(token); + } + + /** + * Parse a jwks + * \param token JWKs Token to parse + * \return Parsed JWKs + * \throw std::runtime_error Token is not in correct format + */ + inline jwks parse_jwks(const traits::kazuho_picojson::string_type& token) { + return jwks(token); + } + + /** + * This type is the specialization of the \ref verify_ops::verify_context class which + * uses the standard template types. + */ + using verify_context = verify_ops::verify_context; +} // namespace jwt + +#endif // JWT_CPP_KAZUHO_PICOJSON_DEFAULTS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/traits.h b/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/traits.h new file mode 100644 index 000000000..2f96bfc01 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/kazuho-picojson/traits.h @@ -0,0 +1,76 @@ +#ifndef JWT_CPP_PICOJSON_TRAITS_H +#define JWT_CPP_PICOJSON_TRAITS_H + +#ifndef PICOJSON_USE_INT64 +#define PICOJSON_USE_INT64 +#endif +#include "picojson/picojson.h" + +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif +#include "jwt-cpp/jwt.h" + +namespace jwt { + namespace traits { + struct kazuho_picojson { + using value_type = picojson::value; + using object_type = picojson::object; + using array_type = picojson::array; + using string_type = std::string; + using number_type = double; + using integer_type = int64_t; + using boolean_type = bool; + + static json::type get_type(const picojson::value& val) { + using json::type; + if (val.is()) return type::boolean; + if (val.is()) return type::integer; + if (val.is()) return type::number; + if (val.is()) return type::string; + if (val.is()) return type::array; + if (val.is()) return type::object; + + throw std::logic_error("invalid type"); + } + + static picojson::object as_object(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static std::string as_string(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static picojson::array as_array(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static int64_t as_integer(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static bool as_boolean(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static double as_number(const picojson::value& val) { + if (!val.is()) throw std::bad_cast(); + return val.get(); + } + + static bool parse(picojson::value& val, const std::string& str) { + return picojson::parse(val, str).empty(); + } + + static std::string serialize(const picojson::value& val) { return val.serialize(); } + }; + } // namespace traits +} // namespace jwt + +#endif diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/defaults.h b/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/defaults.h new file mode 100644 index 000000000..c324075f8 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/defaults.h @@ -0,0 +1,88 @@ +#ifndef JWT_CPP_NLOHMANN_JSON_DEFAULTS_H +#define JWT_CPP_NLOHMANN_JSON_DEFAULTS_H + +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif + +#include "traits.h" + +namespace jwt { + /** + * \brief a class to store a generic [JSON for Modern C++](https://github.com/nlohmann/json) value as claim + * + * This type is the specialization of the \ref basic_claim class which + * uses the standard template types. + */ + using claim = basic_claim; + + /** + * Create a verifier using the default clock + * \return verifier instance + */ + inline verifier verify() { + return verify(default_clock{}); + } + + /** + * Return a builder instance to create a new token + */ + inline builder create() { return builder(); } + +#ifndef JWT_DISABLE_BASE64 + /** + * Decode a token + * \param token Token to decode + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); + } +#endif + + /** + * Decode a token + * \tparam Decode is callabled, taking a string_type and returns a string_type. + * It should ensure the padding of the input and then base64url decode and + * return the results. + * \param token Token to decode + * \param decode The token to parse + * \return Decoded token + * \throw std::invalid_argument Token is not in correct format + * \throw std::runtime_error Base64 decoding failed or invalid json + */ + template + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); + } + + /** + * Parse a jwk + * \param token JWK Token to parse + * \return Parsed JWK + * \throw std::runtime_error Token is not in correct format + */ + inline jwk parse_jwk(const traits::nlohmann_json::string_type& token) { + return jwk(token); + } + + /** + * Parse a jwks + * \param token JWKs Token to parse + * \return Parsed JWKs + * \throw std::runtime_error Token is not in correct format + */ + inline jwks parse_jwks(const traits::nlohmann_json::string_type& token) { + return jwks(token); + } + + /** + * This type is the specialization of the \ref verify_ops::verify_context class which + * uses the standard template types. + */ + using verify_context = verify_ops::verify_context; +} // namespace jwt + +#endif // JWT_CPP_NLOHMANN_JSON_DEFAULTS_H diff --git a/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/traits.h b/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/traits.h new file mode 100644 index 000000000..7cf486902 --- /dev/null +++ b/dep/jwt-cpp/include/jwt-cpp/traits/nlohmann-json/traits.h @@ -0,0 +1,77 @@ +#ifndef JWT_CPP_NLOHMANN_JSON_TRAITS_H +#define JWT_CPP_NLOHMANN_JSON_TRAITS_H + +#include "jwt-cpp/jwt.h" +#include "nlohmann/json.hpp" + +namespace jwt { + namespace traits { + struct nlohmann_json { + using json = nlohmann::json; + using value_type = json; + using object_type = json::object_t; + using array_type = json::array_t; + using string_type = std::string; // current limitation of traits implementation + using number_type = json::number_float_t; + using integer_type = json::number_integer_t; + using boolean_type = json::boolean_t; + + static jwt::json::type get_type(const json& val) { + using jwt::json::type; + + if (val.type() == json::value_t::boolean) return type::boolean; + // nlohmann internally tracks two types of integers + if (val.type() == json::value_t::number_integer) return type::integer; + if (val.type() == json::value_t::number_unsigned) return type::integer; + if (val.type() == json::value_t::number_float) return type::number; + if (val.type() == json::value_t::string) return type::string; + if (val.type() == json::value_t::array) return type::array; + if (val.type() == json::value_t::object) return type::object; + + throw std::logic_error("invalid type"); + } + + static json::object_t as_object(const json& val) { + if (val.type() != json::value_t::object) throw std::bad_cast(); + return val.get(); + } + + static std::string as_string(const json& val) { + if (val.type() != json::value_t::string) throw std::bad_cast(); + return val.get(); + } + + static json::array_t as_array(const json& val) { + if (val.type() != json::value_t::array) throw std::bad_cast(); + return val.get(); + } + + static int64_t as_integer(const json& val) { + switch (val.type()) { + case json::value_t::number_integer: + case json::value_t::number_unsigned: return val.get(); + default: throw std::bad_cast(); + } + } + + static bool as_boolean(const json& val) { + if (val.type() != json::value_t::boolean) throw std::bad_cast(); + return val.get(); + } + + static double as_number(const json& val) { + if (val.type() != json::value_t::number_float) throw std::bad_cast(); + return val.get(); + } + + static bool parse(json& val, std::string str) { + val = json::parse(str.begin(), str.end()); + return true; + } + + static std::string serialize(const json& val) { return val.dump(); } + }; + } // namespace traits +} // namespace jwt + +#endif diff --git a/dep/jwt-cpp/nuget/jwt-cpp.nuspec b/dep/jwt-cpp/nuget/jwt-cpp.nuspec new file mode 100644 index 000000000..26957cb65 --- /dev/null +++ b/dep/jwt-cpp/nuget/jwt-cpp.nuspec @@ -0,0 +1,29 @@ + + + + jwt-cpp + 0.6.0-nuget.3 + Thalhammer; prince-chrismc + Thalhammer; prince-chrismc + https://github.com/Thalhammer/jwt-cpp + JWT++ is a header only library for creating and validating JSON Web Tokens in C++11. This library supports all the algorithms defined by the JWT specifications, and the modular design allows to easily add additional algorithms without any problems. In the name of flexibility and extensibility, jwt-cpp supports OpenSSL, LibreSSL, and wolfSSL. And there is no hard dependency on a JSON library. + + Supporting OpenSSL 3.0.0, WolfSSL, Hunter CMake, Boost.JSON, JWKs, ES256K. + MIT + Copyright (c) 2018 Dominik Thalhammer + JWT++: JSON Web Tokens in C++11 + JWT++; a header only library for creating and validating JSON Web Tokens in C++11. + JWT, json, web, token, C++, header-only + + + + + + + + + + + + + diff --git a/dep/jwt-cpp/nuget/jwt-cpp.targets b/dep/jwt-cpp/nuget/jwt-cpp.targets new file mode 100644 index 000000000..a40f2b306 --- /dev/null +++ b/dep/jwt-cpp/nuget/jwt-cpp.targets @@ -0,0 +1,8 @@ + + + + + $(MSBuildThisFileDirectory)..\..\lib\native\include\;%(AdditionalIncludeDirectories) + + + \ No newline at end of file diff --git a/dep/jwt-cpp/tests/BaseTest.cpp b/dep/jwt-cpp/tests/BaseTest.cpp new file mode 100644 index 000000000..210798afc --- /dev/null +++ b/dep/jwt-cpp/tests/BaseTest.cpp @@ -0,0 +1,110 @@ +#include "jwt-cpp/base.h" +#include + +TEST(BaseTest, Base64Index) { + ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64::data(), 'A')); + ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64::data(), 'g')); + ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64::data(), '+')); +} + +TEST(BaseTest, Base64URLIndex) { + ASSERT_EQ(0, jwt::alphabet::index(jwt::alphabet::base64url::data(), 'A')); + ASSERT_EQ(32, jwt::alphabet::index(jwt::alphabet::base64url::data(), 'g')); + ASSERT_EQ(62, jwt::alphabet::index(jwt::alphabet::base64url::data(), '-')); +} + +TEST(BaseTest, BaseDetailsCountPadding) { + using jwt::base::details::padding; + ASSERT_EQ(padding{}, jwt::base::details::count_padding("ABC", {"~"})); + ASSERT_EQ((padding{3, 3}), jwt::base::details::count_padding("ABC~~~", {"~"})); + ASSERT_EQ((padding{5, 5}), jwt::base::details::count_padding("ABC~~~~~", {"~"})); + + ASSERT_EQ(padding{}, jwt::base::details::count_padding("ABC", {"~", "!"})); + ASSERT_EQ((padding{1, 1}), jwt::base::details::count_padding("ABC!", {"~", "!"})); + ASSERT_EQ((padding{1, 1}), jwt::base::details::count_padding("ABC~", {"~", "!"})); + ASSERT_EQ((padding{3, 3}), jwt::base::details::count_padding("ABC~~!", {"~", "!"})); + ASSERT_EQ((padding{3, 3}), jwt::base::details::count_padding("ABC!~~", {"~", "!"})); + ASSERT_EQ((padding{5, 5}), jwt::base::details::count_padding("ABC~~!~~", {"~", "!"})); + + ASSERT_EQ((padding{2, 6}), jwt::base::details::count_padding("MTIzNA%3d%3d", {"%3d", "%3D"})); + ASSERT_EQ((padding{2, 6}), jwt::base::details::count_padding("MTIzNA%3d%3D", {"%3d", "%3D"})); + ASSERT_EQ((padding{2, 6}), jwt::base::details::count_padding("MTIzNA%3D%3d", {"%3d", "%3D"})); + ASSERT_EQ((padding{2, 6}), jwt::base::details::count_padding("MTIzNA%3D%3D", {"%3d", "%3D"})); + + // Some fake scenarios + + ASSERT_EQ(padding{}, jwt::base::details::count_padding("", {"~"})); + ASSERT_EQ(padding{}, jwt::base::details::count_padding("ABC", {"~", "~~!"})); + ASSERT_EQ(padding{}, jwt::base::details::count_padding("ABC!", {"~", "~~!"})); + ASSERT_EQ((padding{1, 1}), jwt::base::details::count_padding("ABC~", {"~", "~~!"})); + ASSERT_EQ((padding{1, 3}), jwt::base::details::count_padding("ABC~~!", {"~", "~~!"})); + ASSERT_EQ((padding{2, 2}), jwt::base::details::count_padding("ABC!~~", {"~", "~~!"})); + ASSERT_EQ((padding{3, 5}), jwt::base::details::count_padding("ABC~~!~~", {"~", "~~!"})); + ASSERT_EQ(padding{}, jwt::base::details::count_padding("ABC~~!~~", {})); +} + +TEST(BaseTest, Base64Decode) { + ASSERT_EQ("1", jwt::base::decode("MQ==")); + ASSERT_EQ("12", jwt::base::decode("MTI=")); + ASSERT_EQ("123", jwt::base::decode("MTIz")); + ASSERT_EQ("1234", jwt::base::decode("MTIzNA==")); +} + +TEST(BaseTest, Base64DecodeURL) { + ASSERT_EQ("1", jwt::base::decode("MQ%3d%3d")); + ASSERT_EQ("12", jwt::base::decode("MTI%3d")); + ASSERT_EQ("123", jwt::base::decode("MTIz")); + ASSERT_EQ("1234", jwt::base::decode("MTIzNA%3d%3d")); +} + +TEST(BaseTest, Base64DecodeURLCaseInsensitive) { + ASSERT_EQ("1", jwt::base::decode("MQ%3d%3d")); + ASSERT_EQ("1", jwt::base::decode("MQ%3D%3d")); + ASSERT_EQ("1", jwt::base::decode("MQ%3d%3D")); + ASSERT_EQ("12", jwt::base::decode("MTI%3d")); + ASSERT_EQ("123", jwt::base::decode("MTIz")); + ASSERT_EQ("1234", jwt::base::decode("MTIzNA%3d%3d")); + ASSERT_EQ("1234", jwt::base::decode("MTIzNA%3D%3D")); +} + +TEST(BaseTest, Base64Encode) { + ASSERT_EQ("MQ==", jwt::base::encode("1")); + ASSERT_EQ("MTI=", jwt::base::encode("12")); + ASSERT_EQ("MTIz", jwt::base::encode("123")); + ASSERT_EQ("MTIzNA==", jwt::base::encode("1234")); +} + +TEST(BaseTest, Base64EncodeURL) { + ASSERT_EQ("MQ%3d%3d", jwt::base::encode("1")); + ASSERT_EQ("MTI%3d", jwt::base::encode("12")); + ASSERT_EQ("MTIz", jwt::base::encode("123")); + ASSERT_EQ("MTIzNA%3d%3d", jwt::base::encode("1234")); +} + +TEST(BaseTest, Base64Pad) { + ASSERT_EQ("MQ==", jwt::base::pad("MQ")); + ASSERT_EQ("MTI=", jwt::base::pad("MTI")); + ASSERT_EQ("MTIz", jwt::base::pad("MTIz")); + ASSERT_EQ("MTIzNA==", jwt::base::pad("MTIzNA")); +} + +TEST(BaseTest, Base64PadURL) { + ASSERT_EQ("MQ%3d%3d", jwt::base::pad("MQ")); + ASSERT_EQ("MTI%3d", jwt::base::pad("MTI")); + ASSERT_EQ("MTIz", jwt::base::pad("MTIz")); + ASSERT_EQ("MTIzNA%3d%3d", jwt::base::pad("MTIzNA")); +} + +TEST(BaseTest, Base64Trim) { + ASSERT_EQ("MQ", jwt::base::trim("MQ==")); + ASSERT_EQ("MTI", jwt::base::trim("MTI=")); + ASSERT_EQ("MTIz", jwt::base::trim("MTIz")); + ASSERT_EQ("MTIzNA", jwt::base::trim("MTIzNA==")); +} + +TEST(BaseTest, Base64TrimURL) { + ASSERT_EQ("MQ", jwt::base::trim("MQ%3d%3d")); + ASSERT_EQ("MTI", jwt::base::trim("MTI%3d")); + ASSERT_EQ("MTIz", jwt::base::trim("MTIz")); + ASSERT_EQ("MTIzNA", jwt::base::trim("MTIzNA%3d%3d")); +} diff --git a/dep/jwt-cpp/tests/CMakeLists.txt b/dep/jwt-cpp/tests/CMakeLists.txt new file mode 100644 index 000000000..cb7eaddc8 --- /dev/null +++ b/dep/jwt-cpp/tests/CMakeLists.txt @@ -0,0 +1,66 @@ +if(JWT_DISABLE_BASE64) + message(FATAL_ERROR "Tests requires the base64 support to be enabled!") +endif() + +if(JWT_DISABLE_PICOJSON) + message(FATAL_ERROR "Tests requires the picojson support to be enabled!") +endif() + +enable_testing() +include(GoogleTest) +if(HUNTER_ENABLED) + hunter_add_package(GTest) +endif() +find_package(GTest REQUIRED) + +set(TEST_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/BaseTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ClaimTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Keys.cpp ${CMAKE_CURRENT_SOURCE_DIR}/HelperTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMain.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TokenFormatTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TokenTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/JwksTest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/OpenSSLErrorTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/traits/NlohmannTest.cpp) + +find_package(jsoncons CONFIG) +if(TARGET jsoncons) + list(APPEND TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/traits/JsonconsTest.cpp) +endif() + +include("private-find-boost-json") +if(TARGET boost_json) + list(APPEND TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/traits/BoostJsonTest.cpp) +endif() + +add_executable(jwt-cpp-test ${TEST_SOURCES}) + +# NOTE: Don't use space inside a generator expression here, because the function prematurely breaks the expression into +# multiple lines. https://cmake.org/pipermail/cmake/2018-April/067422.html +set(JWT_TESTER_GCC_FLAGS -Wall -Wextra -Wpedantic) +set(JWT_TESTER_CLANG_FLAGS -Weverything -Wno-c++98-compat -Wno-global-constructors -Wno-weak-vtables) +target_compile_options( + jwt-cpp-test PRIVATE $<$:/W4> $<$:${JWT_TESTER_GCC_FLAGS}> + $<$:${JWT_TESTER_CLANG_FLAGS}>) +if(HUNTER_ENABLED) + target_link_libraries(jwt-cpp-test PRIVATE GTest::gtest GTest::gtest_main) + # Define a compile define to bypass openssl error tests + target_compile_definitions(jwt-cpp-test PRIVATE HUNTER_ENABLED=1) +else() + target_link_libraries(jwt-cpp-test PRIVATE GTest::GTest GTest::Main) + if(TARGET jsoncons) + target_link_libraries(jwt-cpp-test PRIVATE jsoncons) + endif() + if(TARGET boost_json) + target_link_libraries(jwt-cpp-test PRIVATE boost_json) + endif() +endif() +target_link_libraries(jwt-cpp-test PRIVATE jwt-cpp nlohmann_json::nlohmann_json + $<$>:${CMAKE_DL_LIBS}>) + +gtest_add_tests(TARGET jwt-cpp-test) + +if(JWT_ENABLE_COVERAGE) + include("code-coverage") + setup_coverage(jwt-cpp-test) + set(COVERAGE_EXCLUDES "/usr/**" "/home/*/.conan/**" "*test*" "*build*" "**/nlohmann/json.hpp" + "**/picojson/picojson.h" "*boost*" "*jsoncons*") + setup_target_for_coverage_lcov(NAME coverage EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-test) +endif() diff --git a/dep/jwt-cpp/tests/ClaimTest.cpp b/dep/jwt-cpp/tests/ClaimTest.cpp new file mode 100644 index 000000000..e7cccc3b5 --- /dev/null +++ b/dep/jwt-cpp/tests/ClaimTest.cpp @@ -0,0 +1,141 @@ +#include "jwt-cpp/jwt.h" +#include + +TEST(ClaimTest, AudienceAsString) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.WZnM3SIiSRHsbO3O7Z2bmIzTJ4EC32HRBKfLznHhrh4"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(1, aud.size()); + ASSERT_EQ("test", *aud.begin()); +} + +TEST(ClaimTest, SetAudienceAsString) { + auto token = jwt::create().set_type("JWT").set_audience("test").sign(jwt::algorithm::hs256("test")); + ASSERT_EQ("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.ny5Fa0vzAg7tNL95KWg_ecBNd3XP3tdAzq0SFA6diY4", + token); +} + +TEST(ClaimTest, AudienceAsSet) { + std::string token = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJhdWQiOlsidGVzdCIsInRlc3QyIl19."; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("none", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(2, aud.size()); + ASSERT_TRUE(aud.count("test") > 0); + ASSERT_TRUE(aud.count("test2") > 0); +} + +TEST(ClaimTest, SetAudienceAsSet) { + auto token = jwt::create() + .set_type("JWT") + .set_audience({{picojson::value("test"), picojson::value("test2")}}) + .sign(jwt::algorithm::none{}); + ASSERT_EQ("eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJhdWQiOlsidGVzdCIsInRlc3QyIl19.", token); +} + +TEST(ClaimTest, SetArray) { + std::vector vect = {100, 20, 10}; + auto token = + jwt::create().set_payload_claim("test", jwt::claim(vect.begin(), vect.end())).sign(jwt::algorithm::none{}); + ASSERT_EQ(token, "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."); +} + +TEST(ClaimTest, SetObject) { + std::istringstream iss{"{\"api-x\": [1]}"}; + jwt::claim object; + iss >> object; + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto token = jwt::create().set_payload_claim("namespace", object).sign(jwt::algorithm::hs256("test")); + ASSERT_EQ(token, + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"); +} + +TEST(ClaimTest, SetAlgorithm) { + auto token = jwt::create().set_algorithm("test").sign(jwt::algorithm::none{}); + + auto decoded_token = jwt::decode(token); + ASSERT_EQ(decoded_token.get_algorithm(), "test"); +} + +TEST(ClaimTest, AsInt) { + jwt::claim c(picojson::value(static_cast(10))); + ASSERT_EQ(c.as_integer(), 10); +} + +TEST(ClaimTest, AsDate) { + jwt::claim c(picojson::value(static_cast(10))); + ASSERT_EQ(c.as_date(), std::chrono::system_clock::from_time_t(10)); +} + +TEST(ClaimTest, PicoJSONTraitsAccessorsThrow) { + jwt::traits::kazuho_picojson::value_type val; + ASSERT_THROW(jwt::traits::kazuho_picojson::as_array(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::as_boolean(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::as_integer(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::as_number(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::as_object(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::as_string(val), std::bad_cast); + ASSERT_THROW(jwt::traits::kazuho_picojson::get_type(val), std::logic_error); +} + +TEST(ClaimTest, PicoJSONTraitsAsBool) { + jwt::traits::kazuho_picojson::value_type val(true); + ASSERT_EQ(jwt::traits::kazuho_picojson::as_boolean(val), true); + ASSERT_EQ(jwt::traits::kazuho_picojson::get_type(val), jwt::json::type::boolean); +} + +TEST(ClaimTest, PicoJSONTraitsAsDouble) { + jwt::traits::kazuho_picojson::value_type val(10.0); + ASSERT_EQ(jwt::traits::kazuho_picojson::as_number(val), (int)10); + ASSERT_EQ(jwt::traits::kazuho_picojson::get_type(val), jwt::json::type::number); +} + +TEST(ClaimTest, MapOfClaim) { + using map = jwt::details::map_of_claims; + ASSERT_THROW(map::parse_claims(R"##(__ not json __)##"), jwt::error::invalid_json_exception); + const map claims{ + map::parse_claims(R"##({ "array": [1], "string" : "hello world", "number": 9.9, "bool": true})##")}; + + ASSERT_TRUE(claims.has_claim("array")); + ASSERT_TRUE(claims.has_claim("string")); + ASSERT_TRUE(claims.has_claim("number")); + ASSERT_TRUE(claims.has_claim("bool")); + ASSERT_FALSE(claims.has_claim("__missing__")); + + ASSERT_EQ(map::basic_claim_t{claims.get_claim("array").as_array().at(0)}.as_integer(), (int)1); + ASSERT_EQ(claims.get_claim("string").as_string(), "hello world"); + ASSERT_EQ(claims.get_claim("number").as_number(), 9.9); + ASSERT_EQ(claims.get_claim("bool").as_boolean(), true); + ASSERT_THROW(claims.get_claim("__missing__"), jwt::error::claim_not_present_exception); +} diff --git a/dep/jwt-cpp/tests/HelperTest.cpp b/dep/jwt-cpp/tests/HelperTest.cpp new file mode 100644 index 000000000..558ca90bb --- /dev/null +++ b/dep/jwt-cpp/tests/HelperTest.cpp @@ -0,0 +1,205 @@ +#include "jwt-cpp/jwt.h" +#include + +namespace { + extern std::string google_cert; + extern std::string google_cert_base64_der; + extern std::string google_public_key; +} // namespace + +TEST(HelperTest, Cert2Pubkey) { + auto key = jwt::helper::extract_pubkey_from_cert(google_cert); + ASSERT_EQ(google_public_key, key); +} + +TEST(HelperTest, Base64DER2PemCert) { + auto cert_pem = jwt::helper::convert_base64_der_to_pem(google_cert_base64_der); + ASSERT_EQ(google_cert, cert_pem); +} + +TEST(HelperTest, DER2PemCert) { + auto decoded = + jwt::base::decode(jwt::base::pad(google_cert_base64_der)); + auto cert_pem = jwt::helper::convert_der_to_pem(decoded); + ASSERT_EQ(google_cert, cert_pem); +} + +TEST(HelperTest, ErrorCodeMessages) { + ASSERT_EQ(std::error_code(jwt::error::rsa_error::ok).message(), "no error"); + ASSERT_EQ(std::error_code(static_cast(-1)).message(), "unknown RSA error"); + ASSERT_EQ(std::error_code(jwt::error::rsa_error::ok).category().name(), std::string("rsa_error")); + + ASSERT_EQ(std::error_code(jwt::error::ecdsa_error::ok).message(), "no error"); + ASSERT_EQ(std::error_code(static_cast(-1)).message(), "unknown ECDSA error"); + ASSERT_EQ(std::error_code(jwt::error::ecdsa_error::ok).category().name(), std::string("ecdsa_error")); + + ASSERT_EQ(std::error_code(jwt::error::signature_verification_error::ok).message(), "no error"); + ASSERT_EQ(std::error_code(static_cast(-1)).message(), + "unknown signature verification error"); + ASSERT_EQ(std::error_code(jwt::error::signature_verification_error::ok).category().name(), + std::string("signature_verification_error")); + + ASSERT_EQ(std::error_code(jwt::error::signature_generation_error::ok).message(), "no error"); + ASSERT_EQ(std::error_code(static_cast(-1)).message(), + "unknown signature generation error"); + ASSERT_EQ(std::error_code(jwt::error::signature_generation_error::ok).category().name(), + std::string("signature_generation_error")); + + ASSERT_EQ(std::error_code(jwt::error::token_verification_error::ok).message(), "no error"); + ASSERT_EQ(std::error_code(static_cast(-1)).message(), + "unknown token verification error"); + ASSERT_EQ(std::error_code(jwt::error::token_verification_error::ok).category().name(), + std::string("token_verification_error")); + + int i = 10; + for (i = 10; i < 19; i++) { + ASSERT_NE(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + } + ASSERT_EQ(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + + for (i = 10; i < 17; i++) { + ASSERT_NE(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + } + ASSERT_EQ(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + + for (i = 10; i < 18; i++) { + ASSERT_NE(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + } + ASSERT_EQ(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + + for (i = 10; i < 24; i++) { + ASSERT_NE(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + } + ASSERT_EQ(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + + for (i = 10; i < 16; i++) { + ASSERT_NE(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); + } + ASSERT_EQ(std::error_code(static_cast(i)).message(), + std::error_code(static_cast(-1)).message()); +} + +namespace { + std::string google_cert = +// This is to handle the different subject alternate name ordering +// see https://github.com/wolfSSL/wolfssl/issues/4397 +#ifdef LIBWOLFSSL_VERSION_HEX + R"(-----BEGIN CERTIFICATE----- +MIIFfTCCBOagAwIBAgIKYFOB9QABAACIvTANBgkqhkiG9w0BAQUFADBGMQswCQYD +VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu +dGVybmV0IEF1dGhvcml0eTAeFw0xMzA1MjIxNTQ5MDRaFw0xMzEwMzEyMzU5NTla +MGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N +b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRUwEwYDVQQDDAwqLmdv +b2dsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARmSpIUbCqhUBq1UwnR +Ai7/TNSk6W8JmasR+I0r/NLDYv5yApbAz8HXXN8hDdurMRP6Jy1Q0UIKmyls8HPH +exoCo4IDlzCCA5MwggLDBgNVHREEggK6MIICtoIMKi5nb29nbGUuY29tgg0qLmFu +ZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tghIqLmNsb3VkLmdvb2ds +ZS5jb22CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNhggsqLmdv +b2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4qLmdvb2ds +ZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWCDyouZ29v +Z2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20ubXiCDyou +Z29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5kZYILKi5n +b29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29nbGUuaXSC +CyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCDyouZ29vZ2xl +YXBpcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CDSouZ3N0YXRpYy5jb22CDCou +dXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2ll +LmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0dWJlZWR1Y2F0aW9uLmNvbYILKi55 +dGltZy5jb22CC2FuZHJvaWQuY29tggRnLmNvggZnb28uZ2yCFGdvb2dsZS1hbmFs +eXRpY3MuY29tggpnb29nbGUuY29tghJnb29nbGVjb21tZXJjZS5jb22CCnVyY2hp +bi5jb22CCHlvdXR1LmJlggt5b3V0dWJlLmNvbYIUeW91dHViZWVkdWNhdGlvbi5j +b20wHQYDVR0OBBYEFFN409DVTUYFOWYp0Rxq5cqBhJ6GMB8GA1UdIwQYMBaAFL/A +MOv1QxE+Z7qekfv8atrjaxIkMFsGA1UdHwRUMFIwUKBOoEyGSmh0dHA6Ly93d3cu +Z3N0YXRpYy5jb20vR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkvR29vZ2xlSW50ZXJu +ZXRBdXRob3JpdHkuY3JsMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAAyfQrePfKEL5f67KHp4A +FrYSrvGJjn+ZQHzzoivX2/GW5Iw0oPqf+Jjy8eO2ufQGG5bz++YnK50WQhwQNRgT +iK9AyWx8gvtI4bDo569UuabTZqJEdaPlPbQOz5I6m55hQbc0Fwc//kjOFRghAlsb +OVBpRpkExpB4LxmyUw0tYjY= +-----END CERTIFICATE----- +)"; +#else + R"(-----BEGIN CERTIFICATE----- +MIIF8DCCBVmgAwIBAgIKYFOB9QABAACIvTANBgkqhkiG9w0BAQUFADBGMQswCQYD +VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu +dGVybmV0IEF1dGhvcml0eTAeFw0xMzA1MjIxNTQ5MDRaFw0xMzEwMzEyMzU5NTla +MGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N +b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRUwEwYDVQQDFAwqLmdv +b2dsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARmSpIUbCqhUBq1UwnR +Ai7/TNSk6W8JmasR+I0r/NLDYv5yApbAz8HXXN8hDdurMRP6Jy1Q0UIKmyls8HPH +exoCo4IECjCCBAYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAsGA1Ud +DwQEAwIHgDAdBgNVHQ4EFgQUU3jT0NVNRgU5ZinRHGrlyoGEnoYwHwYDVR0jBBgw +FoAUv8Aw6/VDET5nup6R+/xq2uNrEiQwWwYDVR0fBFQwUjBQoE6gTIZKaHR0cDov +L3d3dy5nc3RhdGljLmNvbS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS9Hb29nbGVJ +bnRlcm5ldEF1dGhvcml0eS5jcmwwZgYIKwYBBQUHAQEEWjBYMFYGCCsGAQUFBzAC +hkpodHRwOi8vd3d3LmdzdGF0aWMuY29tL0dvb2dsZUludGVybmV0QXV0aG9yaXR5 +L0dvb2dsZUludGVybmV0QXV0aG9yaXR5LmNydDAMBgNVHRMBAf8EAjAAMIICwwYD +VR0RBIICujCCAraCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lkLmNvbYIWKi5hcHBl +bmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29tghYqLmdvb2dsZS1h +bmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xl +LmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xl +LmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29v +Z2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyou +Z29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2ds +ZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5n +b29nbGUucGyCCyouZ29vZ2xlLnB0gg8qLmdvb2dsZWFwaXMuY26CFCouZ29vZ2xl +Y29tbWVyY2UuY29tgg0qLmdzdGF0aWMuY29tggwqLnVyY2hpbi5jb22CECoudXJs +Lmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5jb22CDSoueW91dHViZS5j +b22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRpbWcuY29tggthbmRyb2lk +LmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xl +LmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4uY29tggh5b3V0dS5iZYIL +eW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29tMA0GCSqGSIb3DQEBBQUA +A4GBAAMn0K3j3yhC+X+uyh6eABa2Eq7xiY5/mUB886Ir19vxluSMNKD6n/iY8vHj +trn0BhuW8/vmJyudFkIcEDUYE4ivQMlsfIL7SOGw6OevVLmm02aiRHWj5T20Ds+S +OpueYUG3NBcHP/5IzhUYIQJbGzlQaUaZBMaQeC8ZslMNLWI2 +-----END CERTIFICATE----- +)"; +#endif + + std::string google_cert_base64_der = "MIIF8DCCBVmgAwIBAgIKYFOB9QABAACIvTANBgkqhkiG9w0BAQUFADBGMQswCQYD" + "VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu" + "dGVybmV0IEF1dGhvcml0eTAeFw0xMzA1MjIxNTQ5MDRaFw0xMzEwMzEyMzU5NTla" + "MGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N" + "b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRUwEwYDVQQDFAwqLmdv" + "b2dsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARmSpIUbCqhUBq1UwnR" + "Ai7/TNSk6W8JmasR+I0r/NLDYv5yApbAz8HXXN8hDdurMRP6Jy1Q0UIKmyls8HPH" + "exoCo4IECjCCBAYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAsGA1Ud" + "DwQEAwIHgDAdBgNVHQ4EFgQUU3jT0NVNRgU5ZinRHGrlyoGEnoYwHwYDVR0jBBgw" + "FoAUv8Aw6/VDET5nup6R+/xq2uNrEiQwWwYDVR0fBFQwUjBQoE6gTIZKaHR0cDov" + "L3d3dy5nc3RhdGljLmNvbS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS9Hb29nbGVJ" + "bnRlcm5ldEF1dGhvcml0eS5jcmwwZgYIKwYBBQUHAQEEWjBYMFYGCCsGAQUFBzAC" + "hkpodHRwOi8vd3d3LmdzdGF0aWMuY29tL0dvb2dsZUludGVybmV0QXV0aG9yaXR5" + "L0dvb2dsZUludGVybmV0QXV0aG9yaXR5LmNydDAMBgNVHRMBAf8EAjAAMIICwwYD" + "VR0RBIICujCCAraCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lkLmNvbYIWKi5hcHBl" + "bmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29tghYqLmdvb2dsZS1h" + "bmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xl" + "LmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xl" + "LmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29v" + "Z2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyou" + "Z29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2ds" + "ZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5n" + "b29nbGUucGyCCyouZ29vZ2xlLnB0gg8qLmdvb2dsZWFwaXMuY26CFCouZ29vZ2xl" + "Y29tbWVyY2UuY29tgg0qLmdzdGF0aWMuY29tggwqLnVyY2hpbi5jb22CECoudXJs" + "Lmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5jb22CDSoueW91dHViZS5j" + "b22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRpbWcuY29tggthbmRyb2lk" + "LmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xl" + "LmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4uY29tggh5b3V0dS5iZYIL" + "eW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29tMA0GCSqGSIb3DQEBBQUA" + "A4GBAAMn0K3j3yhC+X+uyh6eABa2Eq7xiY5/mUB886Ir19vxluSMNKD6n/iY8vHj" + "trn0BhuW8/vmJyudFkIcEDUYE4ivQMlsfIL7SOGw6OevVLmm02aiRHWj5T20Ds+S" + "OpueYUG3NBcHP/5IzhUYIQJbGzlQaUaZBMaQeC8ZslMNLWI2"; + + std::string google_public_key = R"(-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZkqSFGwqoVAatVMJ0QIu/0zUpOlv +CZmrEfiNK/zSw2L+cgKWwM/B11zfIQ3bqzET+ictUNFCCpspbPBzx3saAg== +-----END PUBLIC KEY----- +)"; +} // namespace diff --git a/dep/jwt-cpp/tests/JwksTest.cpp b/dep/jwt-cpp/tests/JwksTest.cpp new file mode 100644 index 000000000..92cb15a2d --- /dev/null +++ b/dep/jwt-cpp/tests/JwksTest.cpp @@ -0,0 +1,118 @@ +#include "jwt-cpp/jwt.h" +#include + +TEST(JwksTest, OneKeyParse) { + std::string public_key = R"({ + "alg": "RS256", + "kty": "RSA", + "use": "sig", + "x5c": [ + "MIIC+DCCAeCgAwIBAgIJBIGjYW6hFpn2MA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTAeFw0xNjExMjIyMjIyMDVaFw0zMDA4MDEyMjIyMDVaMCMxITAfBgNVBAMTGGN1c3RvbWVyLWRlbW9zLmF1dGgwLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnjZc5bm/eGIHq09N9HKHahM7Y31P0ul+A2wwP4lSpIwFrWHzxw88/7Dwk9QMc+orGXX95R6av4GF+Es/nG3uK45ooMVMa/hYCh0Mtx3gnSuoTavQEkLzCvSwTqVwzZ+5noukWVqJuMKNwjL77GNcPLY7Xy2/skMCT5bR8UoWaufooQvYq6SyPcRAU4BtdquZRiBT4U5f+4pwNTxSvey7ki50yc1tG49Per/0zA4O6Tlpv8x7Red6m1bCNHt7+Z5nSl3RX/QYyAEUX1a28VcYmR41Osy+o2OUCXYdUAphDaHo4/8rbKTJhlu8jEcc1KoMXAKjgaVZtG/v5ltx6AXY0CAwEAAaMvMC0wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUQxFG602h1cG+pnyvJoy9pGJJoCswDQYJKoZIhvcNAQEFBQADggEBAGvtCbzGNBUJPLICth3mLsX0Z4z8T8iu4tyoiuAshP/Ry/ZBnFnXmhD8vwgMZ2lTgUWwlrvlgN+fAtYKnwFO2G3BOCFw96Nm8So9sjTda9CCZ3dhoH57F/hVMBB0K6xhklAc0b5ZxUpCIN92v/w+xZoz1XQBHe8ZbRHaP1HpRM4M7DJk2G5cgUCyu3UBvYS41sHvzrxQ3z7vIePRA4WF4bEkfX12gvny0RsPkrbVMXX1Rj9t6V7QXrbPYBAO+43JvDGYawxYVvLhz+BJ45x50GFQmHszfY3BR9TPK8xmMmQwtIvLu1PMttNCs7niCYkSiUv2sc2mlq1i3IashGkkgmo=" + ], + "n": "yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz-cbe4rjmigxUxr-FgKHQy3HeCdK6hNq9ASQvMK9LBOpXDNn7mei6RZWom4wo3CMvvsY1w8tjtfLb-yQwJPltHxShZq5-ihC9irpLI9xEBTgG12q5lGIFPhTl_7inA1PFK97LuSLnTJzW0bj096v_TMDg7pOWm_zHtF53qbVsI0e3v5nmdKXdFf9BjIARRfVrbxVxiZHjU6zL6jY5QJdh1QCmENoejj_ytspMmGW7yMRxzUqgxcAqOBpVm0b-_mW3HoBdjQ", + "e": "AQAB", + "kid": "123456789", + "x5t": "NjVBRjY5MDlCMUIwNzU4RTA2QzZFMDQ4QzQ2MDAyQjVDNjk1RTM2Qg" + })"; + ASSERT_THROW(jwt::parse_jwk("__not_json__"), jwt::error::invalid_json_exception); + ASSERT_THROW(jwt::parse_jwk(R"##(["not","an","object"])##"), std::bad_cast); + + auto jwk = jwt::parse_jwk(public_key); + + ASSERT_TRUE(jwk.has_algorithm()); + ASSERT_TRUE(jwk.has_key_id()); + ASSERT_TRUE(jwk.has_x5c()); + ASSERT_FALSE(jwk.has_jwk_claim("foo")); + + ASSERT_EQ("RS256", jwk.get_algorithm()); + ASSERT_EQ("123456789", jwk.get_key_id()); +} + +TEST(JwksTest, MultiKeysParse) { + std::string public_key = R"({ + "keys": [{ + "kid": "internal-gateway-jwt", + "use": "sig", + "x5c": ["MIIG1TCCBL2gAwIBAgIIFvMVGp6t\/cMwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0IxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMTUwMwYDVQQDDCxTdGFuZGFyZCBDaGFydGVyZWQgQmFuayBTaWduaW5nIENBIEcxIC0gU0hBMjAeFw0xODEwMTAxMTI2MzVaFw0yMjEwMTAxMTI2MzVaMIG9MQswCQYDVQQGEwJTRzESMBAGA1UECAwJU2luZ2Fwb3JlMRIwEAYDVQQHDAlTaW5nYXBvcmUxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMRwwGgYDVQQLDBNGb3VuZGF0aW9uIFNlcnZpY2VzMSgwJgYDVQQDDB9pbnRlcm5hbC1nYXRld2F5LWp3dC5hcGkuc2MubmV0MRwwGgYJKoZIhvcNAQkBFg1BUElQU1NAc2MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVWBoIi3IJ4nOWXu7\/SDxczqMou1B+c4c2FdQrOXrK31HxAaz4WEtma9BLXFdFHJ5mCCPIvdUcVxxnCynqhMOkZ\/a7acQbUD9cDzI8isMB9JL7VooDw0CctxHxffjqQQVIEhC2Q7zsM1pQayR7cl+pbBlvHIoRxq2n1B0fFvfoiosjf4kDiCpgHdM+v5Hw9aVYmUbroHxmQWqhB0iRTJQPPLZqqQVC50A1Q\/96gkwoODyotc46Uy9wYEpdGrtDG\/thWay3fmMsjpWR0U25xFIrxTrfCGBblYpD7juukWWml2E9rtE2rHgUxbymxXjEw7xrMwcGrhOGyqwoBqJy1JVwIDAQABo4ICLTCCAikwZAYIKwYBBQUHAQEEWDBWMFQGCCsGAQUFBzABhkhodHRwOi8vY29yZW9jc3AuZ2xvYmFsLnN0YW5kYXJkY2hhcnRlcmVkLmNvbS9lamJjYS9wdWJsaWN3ZWIvc3RhdHVzL29jc3AwHQYDVR0OBBYEFIinW4BNDeVEFcuLf8YjZjtySoW9MAwGA1UdEwEB\/wQCMAAwHwYDVR0jBBgwFoAUfNZMoZi33nKrcmVU3TFVQnuEi\/4wggFCBgNVHR8EggE5MIIBNTCCATGggcKggb+GgbxodHRwOi8vY29yZWNybC5nbG9iYWwuc3RhbmRhcmRjaGFydGVyZWQuY29tL2VqYmNhL3B1YmxpY3dlYi93ZWJkaXN0L2NlcnRkaXN0P2NtZD1jcmwmaXNzdWVyPUNOPVN0YW5kYXJkJTIwQ2hhcnRlcmVkJTIwQmFuayUyMFNpZ25pbmclMjBDQSUyMEcxJTIwLSUyMFNIQTIsTz1TdGFuZGFyZCUyMENoYXJ0ZXJlZCUyMEJhbmssQz1HQqJqpGgwZjE1MDMGA1UEAwwsU3RhbmRhcmQgQ2hhcnRlcmVkIEJhbmsgU2lnbmluZyBDQSBHMSAtIFNIQTIxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMQswCQYDVQQGEwJHQjAOBgNVHQ8BAf8EBAMCBsAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4ICAQBtsoRlDHuOTDChcWdfdVUtRgP0U0ijDSeJi8vULN1rgYnqqJc4PdJno50aiu9MGlxY02O7HW7ZVD6QEG\/pqHmZ0sbWpb\/fumMgZSjP65IcGuS53zgcNtLYnyXyEv+v5T\/CK3bk4Li6tUW3ScJPUwVWwP1E0\/u6aBSb5k\/h4lTwS1o88ybS5pJOg6XutXByp991QQrrs7tp7fKNynjNZbFuG3J1e09X+zTfJOpjaDUofQTkt8IyMRI6Cs4wI1eZA+dAIL8B0n8ze1mRl1FOJqgdZrAQjoqZkCTnc0Il5VY\/dUXxGVg6D9e5pfck3FWT107K9\/5EZoxytpqYXFCjMXi5hx4YjK17OUgm82mZhvqkNdzF8Yq2vFuB3LPfyelESq99xFLykvinrVm1NtZKeDTT1Jq\/VvZt6stO\/tovq1RfJJcznpYcwOzxlnhGR6E+hxuBx7aDJzGf0JaoRxQILH1B2XV9WDI3HPYQsP7XtriX+QUJ\/aly28QkV48RmaGYCsly43YZu1MKudSsw+dhnbZzRsg\/aes3dzGW2x137bQPtux7k2LCSpsTXgedhOys28YoGlsoe8kUv0myAU4Stt+I3mrwO3BKUn+tJggvlDiiiyT1tg2HiklyU\/2FxQkZRMeB0eRrXTpg3l9x2mpF+dDFxOMKszxwD2kgoEZgo6o58A=="], + "n": "nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e": "AQAB", + "x5t": "-qC0akuyiHT7GcV5a8O5nrFsKVWM9da7lzq6DLrj09I", + "alg": "RS256", + "kty": "RSA" + }, + { + "kid": "internal-0", + "use": "sig", + "x5c": ["MIIG1TCCBL2gAwIBAgIIFvMVGp6t\/cMwDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCR0IxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMTUwMwYDVQQDDCxTdGFuZGFyZCBDaGFydGVyZWQgQmFuayBTaWduaW5nIENBIEcxIC0gU0hBMjAeFw0xODEwMTAxMTI2MzVaFw0yMjEwMTAxMTI2MzVaMIG9MQswCQYDVQQGEwJTRzESMBAGA1UECAwJU2luZ2Fwb3JlMRIwEAYDVQQHDAlTaW5nYXBvcmUxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMRwwGgYDVQQLDBNGb3VuZGF0aW9uIFNlcnZpY2VzMSgwJgYDVQQDDB9pbnRlcm5hbC1nYXRld2F5LWp3dC5hcGkuc2MubmV0MRwwGgYJKoZIhvcNAQkBFg1BUElQU1NAc2MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVWBoIi3IJ4nOWXu7\/SDxczqMou1B+c4c2FdQrOXrK31HxAaz4WEtma9BLXFdFHJ5mCCPIvdUcVxxnCynqhMOkZ\/a7acQbUD9cDzI8isMB9JL7VooDw0CctxHxffjqQQVIEhC2Q7zsM1pQayR7cl+pbBlvHIoRxq2n1B0fFvfoiosjf4kDiCpgHdM+v5Hw9aVYmUbroHxmQWqhB0iRTJQPPLZqqQVC50A1Q\/96gkwoODyotc46Uy9wYEpdGrtDG\/thWay3fmMsjpWR0U25xFIrxTrfCGBblYpD7juukWWml2E9rtE2rHgUxbymxXjEw7xrMwcGrhOGyqwoBqJy1JVwIDAQABo4ICLTCCAikwZAYIKwYBBQUHAQEEWDBWMFQGCCsGAQUFBzABhkhodHRwOi8vY29yZW9jc3AuZ2xvYmFsLnN0YW5kYXJkY2hhcnRlcmVkLmNvbS9lamJjYS9wdWJsaWN3ZWIvc3RhdHVzL29jc3AwHQYDVR0OBBYEFIinW4BNDeVEFcuLf8YjZjtySoW9MAwGA1UdEwEB\/wQCMAAwHwYDVR0jBBgwFoAUfNZMoZi33nKrcmVU3TFVQnuEi\/4wggFCBgNVHR8EggE5MIIBNTCCATGggcKggb+GgbxodHRwOi8vY29yZWNybC5nbG9iYWwuc3RhbmRhcmRjaGFydGVyZWQuY29tL2VqYmNhL3B1YmxpY3dlYi93ZWJkaXN0L2NlcnRkaXN0P2NtZD1jcmwmaXNzdWVyPUNOPVN0YW5kYXJkJTIwQ2hhcnRlcmVkJTIwQmFuayUyMFNpZ25pbmclMjBDQSUyMEcxJTIwLSUyMFNIQTIsTz1TdGFuZGFyZCUyMENoYXJ0ZXJlZCUyMEJhbmssQz1HQqJqpGgwZjE1MDMGA1UEAwwsU3RhbmRhcmQgQ2hhcnRlcmVkIEJhbmsgU2lnbmluZyBDQSBHMSAtIFNIQTIxIDAeBgNVBAoMF1N0YW5kYXJkIENoYXJ0ZXJlZCBCYW5rMQswCQYDVQQGEwJHQjAOBgNVHQ8BAf8EBAMCBsAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4ICAQBtsoRlDHuOTDChcWdfdVUtRgP0U0ijDSeJi8vULN1rgYnqqJc4PdJno50aiu9MGlxY02O7HW7ZVD6QEG\/pqHmZ0sbWpb\/fumMgZSjP65IcGuS53zgcNtLYnyXyEv+v5T\/CK3bk4Li6tUW3ScJPUwVWwP1E0\/u6aBSb5k\/h4lTwS1o88ybS5pJOg6XutXByp991QQrrs7tp7fKNynjNZbFuG3J1e09X+zTfJOpjaDUofQTkt8IyMRI6Cs4wI1eZA+dAIL8B0n8ze1mRl1FOJqgdZrAQjoqZkCTnc0Il5VY\/dUXxGVg6D9e5pfck3FWT107K9\/5EZoxytpqYXFCjMXi5hx4YjK17OUgm82mZhvqkNdzF8Yq2vFuB3LPfyelESq99xFLykvinrVm1NtZKeDTT1Jq\/VvZt6stO\/tovq1RfJJcznpYcwOzxlnhGR6E+hxuBx7aDJzGf0JaoRxQILH1B2XV9WDI3HPYQsP7XtriX+QUJ\/aly28QkV48RmaGYCsly43YZu1MKudSsw+dhnbZzRsg\/aes3dzGW2x137bQPtux7k2LCSpsTXgedhOys28YoGlsoe8kUv0myAU4Stt+I3mrwO3BKUn+tJggvlDiiiyT1tg2HiklyU\/2FxQkZRMeB0eRrXTpg3l9x2mpF+dDFxOMKszxwD2kgoEZgo6o58A=="], + "n": "nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e": "AQAB", + "x5t": "-qC0akuyiHT7GcV5a8O5nrFsKVWM9da7lzq6DLrj09I", + "alg": "RS256", + "kty": "RSA" + } + ] +})"; + auto jwks = jwt::parse_jwks(public_key); + auto jwk = jwks.get_jwk("internal-gateway-jwt"); + + ASSERT_TRUE(jwk.has_algorithm()); + ASSERT_TRUE(jwk.has_key_id()); + ASSERT_TRUE(jwk.has_x5c()); + ASSERT_FALSE(jwk.has_jwk_claim("foo")); + + ASSERT_EQ("RS256", jwk.get_algorithm()); + ASSERT_EQ("internal-gateway-jwt", jwk.get_key_id()); + + ASSERT_THROW(jwks.get_jwk("123456"), jwt::error::claim_not_present_exception); +} + +TEST(JwksTest, Missingx5c) { + std::string public_key = R"({ + "keys": [{ + "kid": "internal-gateway-jwt", + "use": "sig", + "n": "nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e": "AQAB", + "x5t": "-qC0akuyiHT7GcV5a8O5nrFsKVWM9da7lzq6DLrj09I", + "alg": "RS256", + "kty": "RSA" + }, + { + "kid": "internal-0", + "use": "sig", + "x5c": [], + "n": "nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e": "AQAB", + "x5t": "-qC0akuyiHT7GcV5a8O5nrFsKVWM9da7lzq6DLrj09I", + "alg": "RS256", + "kty": "RSA" + }, + { + "kid": "internal-1", + "x5c": ["1","2","3"], + "n": "nr9UsxnPVd21iuiGcIJ_Qli2XVlAZe5VbELA1hO2-L4k5gI4fjHZ3ysUcautLpbOYogOQgsnlpsLrCmvNDvBDVzVp2nMbpguJlt12vHSP1fRJJpipGQ8qU-VaXsC4OjOQf3H9ojAU5Vfnl5gZ7kVCd8g4M29l-IRyNpxE-Ccxc2Y7molsCHT6GHLMMBVsd11JIOXMICJf4hz2YYkQ1t7C8SaB2RFRPuGO5Mn6mfAnwdmRera4TBz6_pIPPCgCbN8KOdJItWkr9F7Tjv_0nhh-ZVlQvbQ9PXHyKTj00g3IYUlbZIWHm0Ley__fzNZk2dyAAVjNA2QSzTZJc33MQx1pQ", + "e": "AQAB", + "x5t": "-qC0akuyiHT7GcV5a8O5nrFsKVWM9da7lzq6DLrj09I", + "alg": "RS256", + "kty": "RSA" + } + ] +})"; + + auto jwks = jwt::parse_jwks(public_key); + ASSERT_TRUE(jwks.has_jwk("internal-gateway-jwt")); + ASSERT_FALSE(jwks.has_jwk("random-jwt")); + auto jwk = jwks.get_jwk("internal-gateway-jwt"); + + ASSERT_TRUE(jwk.has_algorithm()); + ASSERT_THROW(jwk.get_x5c(), jwt::error::claim_not_present_exception); + + auto jwk2 = jwks.get_jwk("internal-0"); + + ASSERT_EQ(jwk2.get_x5c().size(), 0); + ASSERT_THROW(jwk2.get_x5c_key_value(), jwt::error::claim_not_present_exception); + + auto jwk3 = jwks.get_jwk("internal-1"); + ASSERT_EQ(jwk3.get_x5c().size(), 3); + ASSERT_EQ(jwk3.get_x5c_key_value(), "1"); +} diff --git a/dep/jwt-cpp/tests/Keys.cpp b/dep/jwt-cpp/tests/Keys.cpp new file mode 100644 index 000000000..60abdd251 --- /dev/null +++ b/dep/jwt-cpp/tests/Keys.cpp @@ -0,0 +1,220 @@ +#include + +namespace test_keys { + std::string rsa_priv_key = R"(-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4ZtdaIrd1BPIJ +tfnF0TjIK5inQAXZ3XlCrUlJdP+XHwIRxdv1FsN12XyMYO/6ymLmo9ryoQeIrsXB +XYqlET3zfAY+diwCb0HEsVvhisthwMU4gZQu6TYW2s9LnXZB5rVtcBK69hcSlA2k +ZudMZWxZcj0L7KMfO2rIvaHw/qaVOE9j0T257Z8Kp2CLF9MUgX0ObhIsdumFRLaL +DvDUmBPr2zuh/34j2XmWwn1yjN/WvGtdfhXW79Ki1S40HcWnygHgLV8sESFKUxxQ +mKvPUTwDOIwLFL5WtE8Mz7N++kgmDcmWMCHc8kcOIu73Ta/3D4imW7VbKgHZo9+K +3ESFE3RjAgMBAAECggEBAJTEIyjMqUT24G2FKiS1TiHvShBkTlQdoR5xvpZMlYbN +tVWxUmrAGqCQ/TIjYnfpnzCDMLhdwT48Ab6mQJw69MfiXwc1PvwX1e9hRscGul36 +ryGPKIVQEBsQG/zc4/L2tZe8ut+qeaK7XuYrPp8bk/X1e9qK5m7j+JpKosNSLgJj +NIbYsBkG2Mlq671irKYj2hVZeaBQmWmZxK4fw0Istz2WfN5nUKUeJhTwpR+JLUg4 +ELYYoB7EO0Cej9UBG30hbgu4RyXA+VbptJ+H042K5QJROUbtnLWuuWosZ5ATldwO +u03dIXL0SH0ao5NcWBzxU4F2sBXZRGP2x/jiSLHcqoECgYEA4qD7mXQpu1b8XO8U +6abpKloJCatSAHzjgdR2eRDRx5PMvloipfwqA77pnbjTUFajqWQgOXsDTCjcdQui +wf5XAaWu+TeAVTytLQbSiTsBhrnoqVrr3RoyDQmdnwHT8aCMouOgcC5thP9vQ8Us +rVdjvRRbnJpg3BeSNimH+u9AHgsCgYEA0EzcbOltCWPHRAY7B3Ge/AKBjBQr86Kv +TdpTlxePBDVIlH+BM6oct2gaSZZoHbqPjbq5v7yf0fKVcXE4bSVgqfDJ/sZQu9Lp +PTeV7wkk0OsAMKk7QukEpPno5q6tOTNnFecpUhVLLlqbfqkB2baYYwLJR3IRzboJ +FQbLY93E8gkCgYB+zlC5VlQbbNqcLXJoImqItgQkkuW5PCgYdwcrSov2ve5r/Acz +FNt1aRdSlx4176R3nXyibQA1Vw+ztiUFowiP9WLoM3PtPZwwe4bGHmwGNHPIfwVG +m+exf9XgKKespYbLhc45tuC08DATnXoYK7O1EnUINSFJRS8cezSI5eHcbQKBgQDC +PgqHXZ2aVftqCc1eAaxaIRQhRmY+CgUjumaczRFGwVFveP9I6Gdi+Kca3DE3F9Pq +PKgejo0SwP5vDT+rOGHN14bmGJUMsX9i4MTmZUZ5s8s3lXh3ysfT+GAhTd6nKrIE +kM3Nh6HWFhROptfc6BNusRh1kX/cspDplK5x8EpJ0QKBgQDWFg6S2je0KtbV5PYe +RultUEe2C0jYMDQx+JYxbPmtcopvZQrFEur3WKVuLy5UAy7EBvwMnZwIG7OOohJb +vkSpADK6VPn9lbqq7O8cTedEHttm6otmLt8ZyEl3hZMaL3hbuRj6ysjmoFKx6CrX +rK0/Ikt5ybqUzKCMJZg2VKGTxg== +-----END PRIVATE KEY-----)"; + std::string rsa_pub_key = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGbXWiK3dQTyCbX5xdE4 +yCuYp0AF2d15Qq1JSXT/lx8CEcXb9RbDddl8jGDv+spi5qPa8qEHiK7FwV2KpRE9 +83wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVs +WXI9C+yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT +69s7of9+I9l5lsJ9cozf1rxrXX4V1u/SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8 +AziMCxS+VrRPDM+zfvpIJg3JljAh3PJHDiLu902v9w+Iplu1WyoB2aPfitxEhRN0 +YwIDAQAB +-----END PUBLIC KEY-----)"; + std::string rsa_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzYuc22QSst/dS7geYYK +5l5kLxU0tayNdixkEQ17ix+CUcUbKIsnyftZxaCYT46rQtXgCaYRdJcbB3hmyrOa +vkhTpX79xJZnQmfuamMbZBqitvscxW9zRR9tBUL6vdi/0rpoUwPMEh8+Bw7CgYR0 +FK0DhWYBNDfe9HKcyZEv3max8Cdq18htxjEsdYO0iwzhtKRXomBWTdhD5ykd/fAC +VTr4+KEY+IeLvubHVmLUhbE5NgWXxrRpGasDqzKhCTmsa2Ysf712rl57SlH0Wz/M +r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s +YwIDAQAB +-----END PUBLIC KEY-----)"; + std::string rsa512_priv_key = R"(-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw +33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW ++jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB +AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS +3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp +uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE +2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0 +GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K +Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY +6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5 +fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523 +Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP +FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw== +-----END RSA PRIVATE KEY-----)"; + std::string rsa512_pub_key = R"(-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd +UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs +HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D +o2kQ+X5xK9cipRgEKwIDAQAB +-----END PUBLIC KEY-----)"; + std::string rsa512_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxzYuc22QSst/dS7geYYK +5l5kLxU0tayNdixkEQ17ix+CUcUbKIsnyftZxaCYT46rQtXgCaYRdJcbB3hmyrOa +vkhTpX79xJZnQmfuamMbZBqitvscxW9zRR9tBUL6vdi/0rpoUwPMEh8+Bw7CgYR0 +FK0DhWYBNDfe9HKcyZEv3max8Cdq18htxjEsdYO0iwzhtKRXomBWTdhD5ykd/fAC +VTr4+KEY+IeLvubHVmLUhbE5NgWXxrRpGasDqzKhCTmsa2Ysf712rl57SlH0Wz/M +r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s +YwIDAQAB +-----END PUBLIC KEY-----)"; + std::string ecdsa521_priv_key = R"(-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIAuZxTZjLIZM5hxgZX+JRrqt5FKpAEg/meZ7m9aSE3XbRITqtfz1Uy +h2Srn7o8+4j/jQpwHTTHZThy10u5jMjaR+mgBwYFK4EEACOhgYkDgYYABAFFah0k +6m4ddp/tUN/ObrKKwSCp4QUZdiAMaC9eY1HyNBPuuEsH5qCfeY5lmeJwSUpzCosn +rgW8M2hQ4Kr5V9OXrgHLA5WVtH6//sSkUY2/xYuqc7/Ln8gI5ddtr1qG64Xtgs05 +/CNajSjFZeLm76llakvYiBTTH/ii8hIfrwukW9IP7Q== +-----END EC PRIVATE KEY-----)"; + std::string ecdsa521_pub_key = R"(-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBRWodJOpuHXaf7VDfzm6yisEgqeEF +GXYgDGgvXmNR8jQT7rhLB+agn3mOZZnicElKcwqLJ64FvDNoUOCq+VfTl64BywOV +lbR+v/7EpFGNv8WLqnO/y5/ICOXXba9ahuuF7YLNOfwjWo0oxWXi5u+pZWpL2IgU +0x/4ovISH68LpFvSD+0= +-----END PUBLIC KEY-----)"; + std::string ecdsa521_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB3l84szH3VOII+Qp4TGgRqCps1q7N +/41ucX90sVKT+6Z2FgYqGsfDcViWBdcjRQLL69LGApcvGGSa1MiYXmLWBYAAKriR +7S63iNLzarnq1WnCH+GowDMl127CPoSW4LmMqV5rJLJQNwfiy+N0wph/Adnqqb+6 +w1N7aVXutqCx02T/jrQ= +-----END PUBLIC KEY-----)"; + std::string ecdsa384_priv_key = R"(-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCrPXJDgQDtNRpM0qNUW/zN1vrCvOVH1CsItVZ+1NeGB+w/2whnIXJQ +K7U5C1ETPHagBwYFK4EEACKhZANiAAR0JjvVJXc3u1I/7vt5mxzPtAIi1VIqxCwN +wgISZVySTYZQzyicW2GfhMlFCow28LzqTwH/eCymAvnTAmpK/P1hXhNcnxDBZNOU +WMbMLFcQrg2wwpIb/k/IXobNwjNPRBo= +-----END EC PRIVATE KEY-----)"; + std::string ecdsa384_pub_key = R"(-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEdCY71SV3N7tSP+77eZscz7QCItVSKsQs +DcICEmVckk2GUM8onFthn4TJRQqMNvC86k8B/3gspgL50wJqSvz9YV4TXJ8QwWTT +lFjGzCxXEK4NsMKSG/5PyF6GzcIzT0Qa +-----END PUBLIC KEY-----)"; + std::string ecdsa384_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7TAJMuqdY9JYXrv2p06bXhLmRddkCQZ6 +4BJeTNGz59QqbHk5+6avGj2lXK+c9rr0vejbts5A50WF1E4b7ItLxEIONfSbF74Q +sQ4dg7kzXiz+XX/aEVqH1HlIa9YAJPaH +-----END PUBLIC KEY-----)"; + std::string ecdsa256_priv_key = R"(-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPGJGAm4X1fvBuC1z +SpO/4Izx6PXfNMaiKaS5RUkFqEGhRANCAARCBvmeksd3QGTrVs2eMrrfa7CYF+sX +sjyGg+Bo5mPKGH4Gs8M7oIvoP9pb/I85tdebtKlmiCZHAZE5w4DfJSV6 +-----END PRIVATE KEY-----)"; + std::string ecdsa256_pub_key = R"(-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQgb5npLHd0Bk61bNnjK632uwmBfr +F7I8hoPgaOZjyhh+BrPDO6CL6D/aW/yPObXXm7SpZogmRwGROcOA3yUleg== +-----END PUBLIC KEY-----)"; + std::string ecdsa256_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjT +CLQeb042TjiMJxG+9DLFmRSMlBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ== +-----END PUBLIC KEY-----)"; + std::string ecdsa256_certificate = R"(-----BEGIN CERTIFICATE----- +MIIB3zCCAYWgAwIBAgIUXns6sbspahSWU4TRQssO3NLmDr0wCgYIKoZIzj0EAwIw +RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu +dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA3MjAyMTA4NTlaFw0yMTA3MjAy +MTA4NTlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD +VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjO +PQMBBwNCAASa+WuX0TojwP3IFXEKO/9vHM+h1YBqTFY1wVGitOZewLxgXgCA8Mlu +yubQaTjyu/2XMAUmcbPwddiUidU4P5OJo1MwUTAdBgNVHQ4EFgQUz9J272oD2ple +bwxJWJ5IFTxFfTowHwYDVR0jBBgwFoAUz9J272oD2plebwxJWJ5IFTxFfTowDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAv2rcDBD4p/UeJIEFOK9j +o4XKKbXs6oqMpkEDUinf6DACIGPcShH4m5haelZleORWM068C3BSVToRMSAivE79 +8ZhX +-----END CERTIFICATE-----)"; + std::string ed25519_priv_key = R"(-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIP7pYCi8Xipwjttw6ehj0PNrsg3K1Vc5RBqAG5JePqsm +-----END PRIVATE KEY-----)"; + std::string ed25519_pub_key = R"(-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAJHsGwkQLdwqaqp2Ar39YtLCVHiWgUPcGwQfes2cUOEc= +-----END PUBLIC KEY-----)"; + std::string ed25519_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEAJHsGwkQLdwqaqp2Ar39YtLCVHIwGupcGwQfes2cUOEc= +-----END PUBLIC KEY-----)"; + std::string ed25519_certificate = R"(-----BEGIN CERTIFICATE----- +MIIBjzCCAUECFCQlWQxMEMe4c3OOimH4/y+o/HpfMAUGAytlcDBqMQswCQYDVQQG +EwJDQTEPMA0GA1UECAwGUXVlYmVjMREwDwYDVQQHDAhNb250cmVhbDEQMA4GA1UE +CgwHand0LWNwcDEPMA0GA1UECwwGZ2l0aHViMRQwEgYDVQQDDAtleGFtcGxlLmNv +bTAeFw0yMDA3MzAyMTIwMDBaFw0yMjA2MzAyMTIwMDBaMGoxCzAJBgNVBAYTAkNB +MQ8wDQYDVQQIDAZRdWViZWMxETAPBgNVBAcMCE1vbnRyZWFsMRAwDgYDVQQKDAdq +d3QtY3BwMQ8wDQYDVQQLDAZnaXRodWIxFDASBgNVBAMMC2V4YW1wbGUuY29tMCow +BQYDK2VwAyEAUdLe1SUWxc/95f39pfmuwe1SLHpFXf5gcRQlMH2sjgwwBQYDK2Vw +A0EAezYcLIUnyy86uUnAZdAMPn7wTruNKtG36GrTF3PF4dtdoGF1OV5DLnNK0Hbs +3GyYtaZs6AEHwDXl/INXu2zoCQ== +-----END CERTIFICATE-----)"; + std::string ed448_priv_key = R"(-----BEGIN PRIVATE KEY----- +MEcCAQAwBQYDK2VxBDsEOZNyV4kIWehIWSsPCnDEZbBF+g2WoUgUwox8eQJTq8Hz +y4okU+JZAV8RqQ270fJL/Safvvc1SbbF1A== +-----END PRIVATE KEY-----)"; + std::string ed448_pub_key = R"(-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAQomzAH8FXc0rhznaLR9DYwe5+DNhP0UwpZzS5y6iJ/iirrzI +9/Fjbc/UvFxwFKFw8IJ9QUwFsE8A +-----END PUBLIC KEY-----)"; + std::string ed448_pub_key_invalid = R"(-----BEGIN PUBLIC KEY----- +MEMwBQYDK2VxAzoAQomzAH8FXc0rhznaLR9DYwe5+DNhP0UwpZzS5y6iJ/iirrzI +9/Fjbc/UvFxwFKFW7ij8QUwFsE8A +-----END PUBLIC KEY-----)"; + std::string sample_cert = R"(-----BEGIN CERTIFICATE----- +MIIDHDCCAgSgAwIBAgIIGlbUz5cvweUwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE +AxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTkw +NDEwMjEyMDUxWhcNMTkwNDI3MDkzNTUxWjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl +bi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALRPFSsUi/bGcMVkD+XjJ6z/71u+7Wn1C1bRnM9sU3q7+Ere +DV6an+z+YsjblskBX73h1GyYvmtkyuL7Uq0N+y+RTOmd2fwDw48gM5FEq6DNpVVW +ZRIzzoMSLZCB+tg1eQZdGKtmctdd5Jjhwihf9Aa759fcj60GDG39G6A/w4Jok+J6 +7sRabxxontJ4Kpo6zmwUKbWF8naJeCRTO0VAYLkJqEWO4VJTIHJeu2WpxM0qzvY9 +IY5Yd7Njegu64FoHU55dSfee2KwDa0/bajrknJfxWBN4hk/rqgGjxQmzAYMCB7/p +/9Snfg4NmfX5cJJ01SNzY6Q/mJRjB3iX2PBz+GsCAwEAAaM4MDYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ +KoZIhvcNAQEFBQADggEBAKCSq0D+NIAsGULZrhXouurxInxDyq03xLNcxvKDQchc +XfGA1r3eltmlyKQb5TmAsuKwS/LAQ5z8SlRTOmDGVEtDwnw3S83C4ufXbP0eMB6H +eKf2XCA00T3odUfXmQZme8hG6z7GKVOdn/0oY+vaX38brlCpRXDTm1WldyddUpMz +ftcs6dibdnbQtbX6o9E+KuvGHoNW5xcSjX8lwXTpopfvufPOLPcnFXi4UoYZ8NZ2 +2mRG78LkOA+SkOMutbt6w7TBDvADmFzuzvAULy4gsfcamOYcQ7uiHnnD+PoNiNbw +flE/m/0zymX8I/Xu3+KKLhUnUROGC6zO3OnLHXCnEns= +-----END CERTIFICATE----- +)"; + std::string sample_cert_base64_der = "MIIDHDCCAgSgAwIBAgIIGlbUz5cvweUwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE" + "AxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMTkw" + "NDEwMjEyMDUxWhcNMTkwNDI3MDkzNTUxWjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl" + "bi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD" + "ggEPADCCAQoCggEBALRPFSsUi/bGcMVkD+XjJ6z/71u+7Wn1C1bRnM9sU3q7+Ere" + "DV6an+z+YsjblskBX73h1GyYvmtkyuL7Uq0N+y+RTOmd2fwDw48gM5FEq6DNpVVW" + "ZRIzzoMSLZCB+tg1eQZdGKtmctdd5Jjhwihf9Aa759fcj60GDG39G6A/w4Jok+J6" + "7sRabxxontJ4Kpo6zmwUKbWF8naJeCRTO0VAYLkJqEWO4VJTIHJeu2WpxM0qzvY9" + "IY5Yd7Njegu64FoHU55dSfee2KwDa0/bajrknJfxWBN4hk/rqgGjxQmzAYMCB7/p" + "/9Snfg4NmfX5cJJ01SNzY6Q/mJRjB3iX2PBz+GsCAwEAAaM4MDYwDAYDVR0TAQH/" + "BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ" + "KoZIhvcNAQEFBQADggEBAKCSq0D+NIAsGULZrhXouurxInxDyq03xLNcxvKDQchc" + "XfGA1r3eltmlyKQb5TmAsuKwS/LAQ5z8SlRTOmDGVEtDwnw3S83C4ufXbP0eMB6H" + "eKf2XCA00T3odUfXmQZme8hG6z7GKVOdn/0oY+vaX38brlCpRXDTm1WldyddUpMz" + "ftcs6dibdnbQtbX6o9E+KuvGHoNW5xcSjX8lwXTpopfvufPOLPcnFXi4UoYZ8NZ2" + "2mRG78LkOA+SkOMutbt6w7TBDvADmFzuzvAULy4gsfcamOYcQ7uiHnnD+PoNiNbw" + "flE/m/0zymX8I/Xu3+KKLhUnUROGC6zO3OnLHXCnEns="; + std::string sample_cert_pubkey = R"(-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtE8VKxSL9sZwxWQP5eMn +rP/vW77tafULVtGcz2xTerv4St4NXpqf7P5iyNuWyQFfveHUbJi+a2TK4vtSrQ37 +L5FM6Z3Z/APDjyAzkUSroM2lVVZlEjPOgxItkIH62DV5Bl0Yq2Zy113kmOHCKF/0 +Brvn19yPrQYMbf0boD/DgmiT4nruxFpvHGie0ngqmjrObBQptYXydol4JFM7RUBg +uQmoRY7hUlMgcl67ZanEzSrO9j0hjlh3s2N6C7rgWgdTnl1J957YrANrT9tqOuSc +l/FYE3iGT+uqAaPFCbMBgwIHv+n/1Kd+Dg2Z9flwknTVI3NjpD+YlGMHeJfY8HP4 +awIDAQAB +-----END PUBLIC KEY----- +)"; +} // namespace test_keys diff --git a/dep/jwt-cpp/tests/OpenSSLErrorTest.cpp b/dep/jwt-cpp/tests/OpenSSLErrorTest.cpp new file mode 100644 index 000000000..45ada667b --- /dev/null +++ b/dep/jwt-cpp/tests/OpenSSLErrorTest.cpp @@ -0,0 +1,931 @@ +#ifdef __linux__ // None of this stuff is going to work outside of linux! + +#ifndef HUNTER_ENABLED // Static linking (which hunter always? does) breaks the tests (duplicate definition), so skip them + +#include "jwt-cpp/jwt.h" +#include + +#include +// TODO: Figure out why the tests fail on older openssl versions +#ifndef JWT_OPENSSL_1_0_0 // It fails on < 1.1 but no idea why. +// LibreSSL has different return codes but was already outside of the effective scope + +/** + * ============ Beginning of black magic =============== + * We mock out a couple of openssl functions. + * We can do this because the current executable take precedence while linking. + * Once it is running and we want normal behaviour, we query the original method using dlsym. + */ +static uint64_t fail_BIO_new = 0; +static uint64_t fail_PEM_read_bio_X509 = 0; +static uint64_t fail_X509_get_pubkey = 0; +static uint64_t fail_PEM_write_bio_PUBKEY = 0; +static uint64_t fail_PEM_write_bio_cert = 0; +static uint64_t fail_BIO_ctrl = 0; +static uint64_t fail_BIO_write = 0; +static uint64_t fail_PEM_read_bio_PUBKEY = 0; +static uint64_t fail_PEM_read_bio_PrivateKey = 0; +static uint64_t fail_HMAC = 0; +static uint64_t fail_EVP_MD_CTX_new = 0; +static uint64_t fail_EVP_DigestInit = 0; +static uint64_t fail_EVP_DigestUpdate = 0; +static uint64_t fail_EVP_DigestFinal = 0; +static uint64_t fail_EVP_SignFinal = 0; +static uint64_t fail_EVP_VerifyFinal = 0; +#ifdef JWT_OPENSSL_3_0 +static uint64_t fail_EVP_PKEY_public_check = 0; +static uint64_t fail_EVP_PKEY_private_check = 0; +static uint64_t fail_EVP_PKEY_CTX_new_from_pkey = 0; +#else +static uint64_t fail_EC_KEY_check_key = 0; +static uint64_t fail_EVP_PKEY_get1_EC_KEY = 0; +#endif +static uint64_t fail_ECDSA_SIG_new = 0; +static uint64_t fail_EVP_PKEY_get1_RSA = 0; +static uint64_t fail_EVP_DigestSignInit = 0; +static uint64_t fail_EVP_DigestSign = 0; +static uint64_t fail_EVP_DigestVerifyInit = 0; +static uint64_t fail_EVP_DigestVerify = 0; +static uint64_t fail_EVP_DigestSignFinal = 0; +static uint64_t fail_EVP_DigestVerifyFinal = 0; +static uint64_t fail_d2i_ECDSA_SIG = 0; +static uint64_t fail_i2d_ECDSA_SIG = 0; + +BIO* BIO_new(const BIO_METHOD* type) { + static BIO* (*origMethod)(const BIO_METHOD*) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "BIO_new"); + bool fail = fail_BIO_new & 1; + fail_BIO_new = fail_BIO_new >> 1; + if (fail) + return nullptr; + else + return origMethod(type); +} + +X509* PEM_read_bio_X509(BIO* bp, X509** x, pem_password_cb* cb, void* u) { + static X509* (*origMethod)(BIO * bp, X509 * *x, pem_password_cb * cb, void* u) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "PEM_read_bio_X509"); + bool fail = fail_PEM_read_bio_X509 & 1; + fail_PEM_read_bio_X509 = fail_PEM_read_bio_X509 >> 1; + if (fail) + return nullptr; + else + return origMethod(bp, x, cb, u); +} + +EVP_PKEY* X509_get_pubkey(X509* x) { + static EVP_PKEY* (*origMethod)(X509*) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "X509_get_pubkey"); + bool fail = fail_X509_get_pubkey & 1; + fail_X509_get_pubkey = fail_X509_get_pubkey >> 1; + if (fail) + return nullptr; + else + return origMethod(x); +} + +#ifdef JWT_OPENSSL_3_0 +#define OPENSSL_CONST const +#else +#define OPENSSL_CONST +#endif + +int PEM_write_bio_PUBKEY(BIO* bp, OPENSSL_CONST EVP_PKEY* x) { + static int (*origMethod)(BIO * bp, OPENSSL_CONST EVP_PKEY * x) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "PEM_write_bio_PUBKEY"); + bool fail = fail_PEM_write_bio_PUBKEY & 1; + fail_PEM_write_bio_PUBKEY = fail_PEM_write_bio_PUBKEY >> 1; + if (fail) + return 0; + else + return origMethod(bp, x); +} + +int PEM_write_bio_X509(BIO* bp, OPENSSL_CONST X509* x) { + static int (*origMethod)(BIO * bp, OPENSSL_CONST X509 * x) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "PEM_write_bio_X509"); + bool fail = fail_PEM_write_bio_cert & 1; + fail_PEM_write_bio_cert = fail_PEM_write_bio_cert >> 1; + if (fail) + return 0; + else + return origMethod(bp, x); +} + +long BIO_ctrl(BIO* bp, int cmd, long larg, void* parg) { + static long (*origMethod)(BIO * bp, int cmd, long larg, void* parg) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "BIO_ctrl"); + bool fail = fail_BIO_ctrl & 1; + fail_BIO_ctrl = fail_BIO_ctrl >> 1; + if (fail) + return 0; + else + return origMethod(bp, cmd, larg, parg); +} + +int BIO_write(BIO* b, const void* data, int dlen) { + static int (*origMethod)(BIO * b, const void* data, int dlen) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "BIO_write"); + bool fail = fail_BIO_write & 1; + fail_BIO_write = fail_BIO_write >> 1; + if (fail) + return 0; + else + return origMethod(b, data, dlen); +} + +EVP_PKEY* PEM_read_bio_PUBKEY(BIO* bp, EVP_PKEY** x, pem_password_cb* cb, void* u) { + static EVP_PKEY* (*origMethod)(BIO * bp, EVP_PKEY * *x, pem_password_cb * cb, void* u) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "PEM_read_bio_PUBKEY"); + bool fail = fail_PEM_read_bio_PUBKEY & 1; + fail_PEM_read_bio_PUBKEY = fail_PEM_read_bio_PUBKEY >> 1; + if (fail) + return nullptr; + else + return origMethod(bp, x, cb, u); +} + +EVP_PKEY* PEM_read_bio_PrivateKey(BIO* bp, EVP_PKEY** x, pem_password_cb* cb, void* u) { + static EVP_PKEY* (*origMethod)(BIO * bp, EVP_PKEY * *x, pem_password_cb * cb, void* u) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "PEM_read_bio_PrivateKey"); + bool fail = fail_PEM_read_bio_PrivateKey & 1; + fail_PEM_read_bio_PrivateKey = fail_PEM_read_bio_PrivateKey >> 1; + if (fail) + return nullptr; + else + return origMethod(bp, x, cb, u); +} + +unsigned char* HMAC(const EVP_MD* evp_md, const void* key, int key_len, const unsigned char* d, size_t n, + unsigned char* md, unsigned int* md_len) { + static unsigned char* (*origMethod)(const EVP_MD* evp_md, const void* key, int key_len, const unsigned char* d, + size_t n, unsigned char* md, unsigned int* md_len) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "HMAC"); + bool fail = fail_HMAC & 1; + fail_HMAC = fail_HMAC >> 1; + if (fail) + return nullptr; + else + return origMethod(evp_md, key, key_len, d, n, md, md_len); +} + +EVP_MD_CTX* EVP_MD_CTX_new(void) { + static EVP_MD_CTX* (*origMethod)(void) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_MD_CTX_new"); + bool fail = fail_EVP_MD_CTX_new & 1; + fail_EVP_MD_CTX_new = fail_EVP_MD_CTX_new >> 1; + if (fail) + return nullptr; + else + return origMethod(); +} + +int EVP_DigestSignFinal(EVP_MD_CTX* ctx, unsigned char* sigret, size_t* siglen) { + static int (*origMethod)(EVP_MD_CTX * ctx, unsigned char* sigret, size_t* siglen) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestSignFinal"); + bool fail = fail_EVP_DigestSignFinal & 1; + fail_EVP_DigestSignFinal = fail_EVP_DigestSignFinal >> 1; + if (fail) + return 0; + else + return origMethod(ctx, sigret, siglen); +} + +int EVP_DigestInit(EVP_MD_CTX* ctx, const EVP_MD* type) { + static int (*origMethod)(EVP_MD_CTX * ctx, const EVP_MD* type) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestInit"); + bool fail = fail_EVP_DigestInit & 1; + fail_EVP_DigestInit = fail_EVP_DigestInit >> 1; + if (fail) + return 0; + else + return origMethod(ctx, type); +} + +int EVP_DigestUpdate(EVP_MD_CTX* ctx, const void* d, size_t cnt) { + static int (*origMethod)(EVP_MD_CTX * ctx, const void* d, size_t cnt) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestUpdate"); + bool fail = fail_EVP_DigestUpdate & 1; + fail_EVP_DigestUpdate = fail_EVP_DigestUpdate >> 1; + if (fail) + return 0; + else + return origMethod(ctx, d, cnt); +} + +int EVP_DigestFinal(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s) { + static int (*origMethod)(EVP_MD_CTX * ctx, unsigned char* md, unsigned int* s) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestFinal"); + bool fail = fail_EVP_DigestFinal & 1; + fail_EVP_DigestFinal = fail_EVP_DigestFinal >> 1; + if (fail) + return 0; + else + return origMethod(ctx, md, s); +} + +int EVP_SignFinal(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s, EVP_PKEY* pkey) { + static int (*origMethod)(EVP_MD_CTX * ctx, unsigned char* md, unsigned int* s, EVP_PKEY* pkey) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_SignFinal"); + bool fail = fail_EVP_SignFinal & 1; + fail_EVP_SignFinal = fail_EVP_SignFinal >> 1; + if (fail) + return 0; + else + return origMethod(ctx, md, s, pkey); +} + +int EVP_VerifyFinal(EVP_MD_CTX* ctx, const unsigned char* sigbuf, unsigned int siglen, EVP_PKEY* pkey) { + static int (*origMethod)(EVP_MD_CTX * ctx, const unsigned char* sigbuf, unsigned int siglen, EVP_PKEY* pkey) = + nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_VerifyFinal"); + bool fail = fail_EVP_VerifyFinal & 1; + fail_EVP_VerifyFinal = fail_EVP_VerifyFinal >> 1; + if (fail) + return 0; + else + return origMethod(ctx, sigbuf, siglen, pkey); +} + +#ifdef JWT_OPENSSL_3_0 +int EVP_PKEY_public_check(EVP_PKEY_CTX* ctx) { + static int (*origMethod)(EVP_PKEY_CTX * ctx) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_PKEY_public_check"); + bool fail = fail_EVP_PKEY_public_check & 1; + fail_EVP_PKEY_public_check = fail_EVP_PKEY_public_check >> 1; + if (fail) + return 0; + else + return origMethod(ctx); +} + +int EVP_PKEY_private_check(EVP_PKEY_CTX* ctx) { + static int (*origMethod)(EVP_PKEY_CTX * ctx) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_PKEY_private_check"); + bool fail = fail_EVP_PKEY_private_check & 1; + fail_EVP_PKEY_private_check = fail_EVP_PKEY_private_check >> 1; + if (fail) + return 0; + else + return origMethod(ctx); +} + +EVP_PKEY_CTX* EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX* libctx, EVP_PKEY* pkey, const char* propquery) { + static EVP_PKEY_CTX* (*origMethod)(OSSL_LIB_CTX * libctx, EVP_PKEY * pkey, const char* propquery) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_PKEY_CTX_new_from_pkey"); + bool fail = fail_EVP_PKEY_CTX_new_from_pkey & 1; + fail_EVP_PKEY_CTX_new_from_pkey = fail_EVP_PKEY_CTX_new_from_pkey >> 1; + if (fail) + return nullptr; + else + return origMethod(libctx, pkey, propquery); +} + +#else +int EC_KEY_check_key(const EC_KEY* key) { + static int (*origMethod)(const EC_KEY* key) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EC_KEY_check_key"); + bool fail = fail_EC_KEY_check_key & 1; + fail_EC_KEY_check_key = fail_EC_KEY_check_key >> 1; + if (fail) + return 0; + else + return origMethod(key); +} + +EC_KEY* EVP_PKEY_get1_EC_KEY(EVP_PKEY* pkey) { + static EC_KEY* (*origMethod)(EVP_PKEY * pkey) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_PKEY_get1_EC_KEY"); + bool fail = fail_EVP_PKEY_get1_EC_KEY & 1; + fail_EVP_PKEY_get1_EC_KEY = fail_EVP_PKEY_get1_EC_KEY >> 1; + if (fail) + return nullptr; + else + return origMethod(pkey); +} +#endif + +ECDSA_SIG* ECDSA_SIG_new(void) { + static ECDSA_SIG* (*origMethod)() = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "ECDSA_SIG_new"); + bool fail = fail_ECDSA_SIG_new & 1; + fail_ECDSA_SIG_new = fail_ECDSA_SIG_new >> 1; + if (fail) + return nullptr; + else + return origMethod(); +} + +struct rsa_st* EVP_PKEY_get1_RSA(EVP_PKEY* pkey) { + static struct rsa_st* (*origMethod)(EVP_PKEY * pkey) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_PKEY_get1_RSA"); + bool fail = fail_EVP_PKEY_get1_RSA & 1; + fail_EVP_PKEY_get1_RSA = fail_EVP_PKEY_get1_RSA >> 1; + if (fail) + return nullptr; + else + return origMethod(pkey); +} + +int EVP_DigestSignInit(EVP_MD_CTX* ctx, EVP_PKEY_CTX** pctx, const EVP_MD* type, ENGINE* e, EVP_PKEY* pkey) { + static int (*origMethod)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD* type, ENGINE* e, EVP_PKEY* pkey) = + nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestSignInit"); + bool fail = fail_EVP_DigestSignInit & 1; + fail_EVP_DigestSignInit = fail_EVP_DigestSignInit >> 1; + if (fail) + return 0; + else + return origMethod(ctx, pctx, type, e, pkey); +} + +int EVP_DigestSign(EVP_MD_CTX* ctx, unsigned char* sigret, size_t* siglen, const unsigned char* tbs, size_t tbslen) { + static int (*origMethod)(EVP_MD_CTX * ctx, unsigned char* sigret, size_t* siglen, const unsigned char* tbs, + size_t tbslen) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestSign"); + bool fail = fail_EVP_DigestSign & 1; + fail_EVP_DigestSign = fail_EVP_DigestSign >> 1; + if (fail) + return 0; + else + return origMethod(ctx, sigret, siglen, tbs, tbslen); +} + +int EVP_DigestVerifyInit(EVP_MD_CTX* ctx, EVP_PKEY_CTX** pctx, const EVP_MD* type, ENGINE* e, EVP_PKEY* pkey) { + static int (*origMethod)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD* type, ENGINE* e, EVP_PKEY* pkey) = + nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestVerifyInit"); + bool fail = fail_EVP_DigestVerifyInit & 1; + fail_EVP_DigestVerifyInit = fail_EVP_DigestVerifyInit >> 1; + if (fail) + return 0; + else + return origMethod(ctx, pctx, type, e, pkey); +} + +int EVP_DigestVerify(EVP_MD_CTX* ctx, unsigned char* sigret, size_t* siglen, const unsigned char* tbs, size_t tbslen) { + static int (*origMethod)(EVP_MD_CTX * ctx, unsigned char* sigret, size_t* siglen, const unsigned char* tbs, + size_t tbslen) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestVerify"); + bool fail = fail_EVP_DigestVerify & 1; + fail_EVP_DigestVerify = fail_EVP_DigestVerify >> 1; + if (fail) + return 0; + else + return origMethod(ctx, sigret, siglen, tbs, tbslen); +} + +int EVP_DigestVerifyFinal(EVP_MD_CTX* ctx, const unsigned char* sigret, size_t siglen) { + static int (*origMethod)(EVP_MD_CTX * ctx, const unsigned char* sigret, size_t siglen) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "EVP_DigestVerifyFinal"); + bool fail = fail_EVP_DigestVerifyFinal & 1; + fail_EVP_DigestVerifyFinal = fail_EVP_DigestVerifyFinal >> 1; + if (fail) + return 0; + else + return origMethod(ctx, sigret, siglen); +} + +int i2d_ECDSA_SIG(const ECDSA_SIG* sig, unsigned char** ppout) { + static int (*origMethod)(const ECDSA_SIG* sig, unsigned char** ppout) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "i2d_ECDSA_SIG"); + bool fail = fail_i2d_ECDSA_SIG & 1; + fail_i2d_ECDSA_SIG = fail_i2d_ECDSA_SIG >> 1; + if (fail) + return -1; + else + return origMethod(sig, ppout); +} + +ECDSA_SIG* d2i_ECDSA_SIG(ECDSA_SIG** psig, const unsigned char** ppin, long len) { + static ECDSA_SIG* (*origMethod)(ECDSA_SIG * *psig, const unsigned char** ppin, long len) = nullptr; + if (origMethod == nullptr) origMethod = (decltype(origMethod))dlsym(RTLD_NEXT, "d2i_ECDSA_SIG"); + bool fail = fail_d2i_ECDSA_SIG & 1; + fail_d2i_ECDSA_SIG = fail_d2i_ECDSA_SIG >> 1; + if (fail) + return nullptr; + else + return origMethod(psig, ppin, len); +} + +/** + * =========== End of black magic ============ + */ + +inline namespace test_keys { + extern std::string rsa_priv_key; + extern std::string rsa_pub_key; + extern std::string rsa_pub_key_invalid; + extern std::string rsa512_priv_key; + extern std::string rsa512_pub_key; + extern std::string rsa512_pub_key_invalid; + extern std::string ecdsa256_certificate; + extern std::string ecdsa256_priv_key; + extern std::string ecdsa256_pub_key; + extern std::string ecdsa256_pub_key_invalid; + extern std::string ecdsa384_priv_key; + extern std::string ecdsa384_pub_key; + extern std::string ecdsa384_pub_key_invalid; + extern std::string ecdsa521_priv_key; + extern std::string ecdsa521_pub_key; + extern std::string ecdsa521_pub_key_invalid; + extern std::string sample_cert; + extern std::string sample_cert_base64_der; + extern std::string sample_cert_pubkey; + extern std::string ed25519_priv_key; + extern std::string ed25519_pub_key; + extern std::string ed25519_pub_key_invalid; + extern std::string ed25519_certificate; + extern std::string ed448_priv_key; + extern std::string ed448_pub_key; + extern std::string ed448_pub_key_invalid; +} // namespace test_keys + +TEST(OpenSSLErrorTest, ExtractPubkeyFromCertReference) { + std::error_code ec; + auto res = jwt::helper::extract_pubkey_from_cert(sample_cert, "", ec); + ASSERT_EQ(res, sample_cert_pubkey); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +TEST(OpenSSLErrorTest, ConvertCertBase64DerToPemReference) { + std::error_code ec; + auto res = jwt::helper::convert_base64_der_to_pem(sample_cert_base64_der, ec); + ASSERT_EQ(res, sample_cert); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +struct multitest_entry { + uint64_t* fail_mask_ptr; + uint64_t fail_bitmask; + std::error_code expected_ec; +}; + +template +void run_multitest(const std::vector& mapping, Func fn) { + for (auto& e : mapping) { + std::error_code ec; + *e.fail_mask_ptr = e.fail_bitmask; + try { + fn(ec); + } catch (...) { + *e.fail_mask_ptr = 0; + throw; + } + *e.fail_mask_ptr = 0; + ASSERT_EQ(ec, e.expected_ec); + } +} + +TEST(OpenSSLErrorTest, ExtractPubkeyFromCert) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_read_bio_X509, 1, jwt::error::rsa_error::cert_load_failed}, + {&fail_X509_get_pubkey, 1, jwt::error::rsa_error::get_key_failed}, + {&fail_PEM_write_bio_PUBKEY, 1, jwt::error::rsa_error::write_key_failed}, + {&fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed}}; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::helper::extract_pubkey_from_cert(sample_cert, ""); + FAIL(); // Should never reach this + } catch (const jwt::error::rsa_exception& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, ExtractPubkeyFromCertErrorCode) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_read_bio_X509, 1, jwt::error::rsa_error::cert_load_failed}, + {&fail_X509_get_pubkey, 1, jwt::error::rsa_error::get_key_failed}, + {&fail_PEM_write_bio_PUBKEY, 1, jwt::error::rsa_error::write_key_failed}, + {&fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed}}; + + run_multitest(mapping, [](std::error_code& ec) { + auto res = jwt::helper::extract_pubkey_from_cert(sample_cert, "", ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, ConvertCertBase64DerToPem) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_write_bio_cert, 1, jwt::error::rsa_error::write_cert_failed}, + {&fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed}}; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::helper::convert_base64_der_to_pem(sample_cert_base64_der); + FAIL(); // Should never reach this + } catch (const jwt::error::rsa_exception& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, ConvertCertBase64DerToPemErrorCode) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_write_bio_cert, 1, jwt::error::rsa_error::write_cert_failed}, + {&fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed}}; + + run_multitest(mapping, [](std::error_code& ec) { + auto res = jwt::helper::convert_base64_der_to_pem(sample_cert_base64_der, ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyFromStringReference) { + auto res = jwt::helper::load_public_key_from_string(rsa_pub_key, ""); + ASSERT_TRUE(res); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyFromString) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read}}; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::helper::load_public_key_from_string(rsa_pub_key, ""); + FAIL(); // Should never reach this + } catch (const jwt::error::rsa_exception& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyFromStringErrorCode) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read}}; + + run_multitest(mapping, [](std::error_code& ec) { + auto res = jwt::helper::load_public_key_from_string(rsa_pub_key, "", ec); + ASSERT_FALSE(res); + }); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyCertFromStringReference) { + auto res = jwt::helper::load_public_key_from_string(sample_cert, ""); + ASSERT_TRUE(res); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyCertFromString) { + std::vector mapping { + {&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, +#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x3050300fL + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, +#else + {&fail_BIO_write, 1, jwt::error::rsa_error::write_key_failed}, +#endif + { + &fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read + } + }; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::helper::load_public_key_from_string(sample_cert, ""); + FAIL(); // Should never reach this + } catch (const jwt::error::rsa_exception& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, LoadPublicKeyCertFromStringErrorCode) { + std::vector mapping { + {&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, +#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x3050300fL + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, +#else + {&fail_BIO_write, 1, jwt::error::rsa_error::write_key_failed}, +#endif + { + &fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read + } + }; + + run_multitest(mapping, [](std::error_code& ec) { + auto res = jwt::helper::load_public_key_from_string(sample_cert, "", ec); + ASSERT_FALSE(res); + }); +} + +TEST(OpenSSLErrorTest, LoadPrivateKeyFromStringReference) { + auto res = jwt::helper::load_private_key_from_string(rsa_priv_key, ""); + ASSERT_TRUE(res); +} + +TEST(OpenSSLErrorTest, LoadPrivateKeyFromString) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PrivateKey, 1, jwt::error::rsa_error::load_key_bio_read}}; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::helper::load_private_key_from_string(rsa_priv_key, ""); + FAIL(); // Should never reach this + } catch (const jwt::error::rsa_exception& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, LoadPrivateKeyFromStringErrorCode) { + std::vector mapping{{&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PrivateKey, 1, jwt::error::rsa_error::load_key_bio_read}}; + + run_multitest(mapping, [](std::error_code& ec) { + auto res = jwt::helper::load_private_key_from_string(rsa_priv_key, "", ec); + ASSERT_FALSE(res); + }); +} + +TEST(OpenSSLErrorTest, HMACSign) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + std::vector mapping{{&fail_HMAC, 1, jwt::error::signature_generation_error::hmac_failed}}; + + run_multitest(mapping, [&](std::error_code& ec) { verify.verify(decoded_token, ec); }); +} + +TEST(OpenSSLErrorTest, RS256Reference) { + jwt::algorithm::rs256 alg{rsa_pub_key, rsa_priv_key}; + std::error_code ec; + auto res = alg.sign("testdata", ec); + ASSERT_EQ(jwt::base::encode(res), + "oCJUeLmIKKVVE/UWhEL/Malx0l9TCoXWNAS2z9o8ZYNaS4POIeadZWeUbLdICx3SCJCnGRwL8JkAmYx1wexT2QGuVXXAtZvRu8ceyuQy" + "AhzGkI9HdADu5YAJsUaLknDUV5hmundXQY8lhwQnKFXW0rl0H8DoFiPQErFmcKI6PA9NVGK/LSiqHqesNeg0wqCTxMmeT6pqI7FH9fDO" + "CaBpwUJ4t5aKoytQ75t13OfUM7tfLlVkFZtI3RndhivxLA5d4Elt/Gv3RhDu6Eiom5NZ/pwRvP26Sox+FWapz3DGCil70H1iGSYu8ENa" + "afUBCGGhT4sk7kl7zS6XiEpMobLq3A=="); + ASSERT_FALSE(!(!ec)); + + alg.verify("testdata", res, ec); + ASSERT_FALSE(!(!ec)); +} + +TEST(OpenSSLErrorTest, RS256SignErrorCode) { + jwt::algorithm::rs256 alg{rsa_pub_key, rsa_priv_key}; + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_generation_error::create_context_failed}, + {&fail_EVP_DigestInit, 1, jwt::error::signature_generation_error::signinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_generation_error::signupdate_failed}, + {&fail_EVP_SignFinal, 1, jwt::error::signature_generation_error::signfinal_failed}}; + + run_multitest(mapping, [&alg](std::error_code& ec) { + auto res = alg.sign("testdata", ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, RS256VerifyErrorCode) { + jwt::algorithm::rs256 alg{rsa_pub_key, rsa_priv_key}; + auto signature = jwt::base::decode( + "oCJUeLmIKKVVE/UWhEL/Malx0l9TCoXWNAS2z9o8ZYNaS4POIeadZWeUbLdICx3SCJCnGRwL8JkAmYx1wexT2QGuVXXAtZvRu8ceyuQy" + "AhzGkI9HdADu5YAJsUaLknDUV5hmundXQY8lhwQnKFXW0rl0H8DoFiPQErFmcKI6PA9NVGK/LSiqHqesNeg0wqCTxMmeT6pqI7FH9fDO" + "CaBpwUJ4t5aKoytQ75t13OfUM7tfLlVkFZtI3RndhivxLA5d4Elt/Gv3RhDu6Eiom5NZ/pwRvP26Sox+FWapz3DGCil70H1iGSYu8ENa" + "afUBCGGhT4sk7kl7zS6XiEpMobLq3A=="); + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_verification_error::create_context_failed}, + {&fail_EVP_DigestInit, 1, jwt::error::signature_verification_error::verifyinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_verification_error::verifyupdate_failed}, + {&fail_EVP_VerifyFinal, 1, jwt::error::signature_verification_error::verifyfinal_failed}}; + + run_multitest(mapping, [&alg, &signature](std::error_code& ec) { alg.verify("testdata", signature, ec); }); +} + +TEST(OpenSSLErrorTest, LoadECDSAPrivateKeyFromString) { + std::vector mapping{ + {&fail_BIO_new, 1, jwt::error::ecdsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::ecdsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PrivateKey, 1, jwt::error::ecdsa_error::load_key_bio_read}, +#ifdef JWT_OPENSSL_3_0 + {&fail_EVP_PKEY_private_check, 1, jwt::error::ecdsa_error::invalid_key}, + {&fail_EVP_PKEY_CTX_new_from_pkey, 1, jwt::error::ecdsa_error::create_context_failed}, +#else + {&fail_EC_KEY_check_key, 1, jwt::error::ecdsa_error::invalid_key}, + {&fail_EVP_PKEY_get1_EC_KEY, 1, jwt::error::ecdsa_error::invalid_key}, +#endif + }; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::algorithm::es256 alg{"", ecdsa256_priv_key}; + FAIL(); // Should never reach this + } catch (const std::system_error& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, LoadECDSAPublicKeyFromString) { + std::vector mapping{ + {&fail_BIO_new, 1, jwt::error::ecdsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::ecdsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PUBKEY, 1, jwt::error::ecdsa_error::load_key_bio_read}, +#ifdef JWT_OPENSSL_3_0 + {&fail_EVP_PKEY_public_check, 1, jwt::error::ecdsa_error::invalid_key}, + {&fail_EVP_PKEY_CTX_new_from_pkey, 1, jwt::error::ecdsa_error::create_context_failed}, +#else + {&fail_EC_KEY_check_key, 1, jwt::error::ecdsa_error::invalid_key}, + {&fail_EVP_PKEY_get1_EC_KEY, 1, jwt::error::ecdsa_error::invalid_key}, +#endif + }; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::algorithm::es256 alg{ecdsa256_pub_key, ""}; + FAIL(); // Should never reach this + } catch (const std::system_error& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, ECDSACertificate) { + std::vector mapping { + {&fail_BIO_new, 1, jwt::error::ecdsa_error::create_mem_bio_failed}, +#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x3050300fL + {&fail_BIO_write, 1, jwt::error::ecdsa_error::load_key_bio_write}, +#else + {&fail_BIO_write, 1, jwt::error::rsa_error::write_key_failed}, +#endif + {&fail_PEM_read_bio_PUBKEY, 1, jwt::error::ecdsa_error::load_key_bio_read}, + // extract_pubkey_from_cert + {&fail_BIO_new, 2, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_read_bio_X509, 1, jwt::error::rsa_error::cert_load_failed}, + {&fail_X509_get_pubkey, 1, jwt::error::rsa_error::get_key_failed}, + {&fail_PEM_write_bio_PUBKEY, 1, jwt::error::rsa_error::write_key_failed}, { + &fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed + } + }; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::algorithm::es256 alg{ecdsa256_certificate}; + FAIL(); // Should never reach this + } catch (const std::system_error& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, ES256Reference) { + jwt::algorithm::es256 alg{ecdsa256_pub_key, ecdsa256_priv_key}; + std::error_code ec; + auto res = alg.sign("testdata", ec); + ASSERT_FALSE(!(!ec)); + + alg.verify("testdata", res, ec); + ASSERT_FALSE(!(!ec)); +} + +TEST(OpenSSLErrorTest, ES256SignErrorCode) { + jwt::algorithm::es256 alg{ecdsa256_pub_key, ecdsa256_priv_key}; + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_generation_error::create_context_failed}, + {&fail_EVP_DigestSignInit, 1, jwt::error::signature_generation_error::signinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_generation_error::digestupdate_failed}, + {&fail_EVP_DigestSignFinal, 1, jwt::error::signature_generation_error::signfinal_failed}, + {&fail_EVP_DigestSignFinal, 2, jwt::error::signature_generation_error::signfinal_failed}, + {&fail_d2i_ECDSA_SIG, 1, jwt::error::signature_generation_error::signature_decoding_failed}, + }; + + run_multitest(mapping, [&alg](std::error_code& ec) { + auto res = alg.sign("testdata", ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, ES256VerifyErrorCode) { + jwt::algorithm::es256 alg{ecdsa256_pub_key, ecdsa256_priv_key}; + auto signature = jwt::base::decode( + "aC/NqyHfPw5FDA0yRAnrbkrAlXjsr0obRkCg/HgP+77QYJrAg6YKkKoJwMXjUX8fQrxXKTN7em5L9dtmOep37Q=="); + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_verification_error::create_context_failed}, + {&fail_EVP_DigestVerifyInit, 1, jwt::error::signature_verification_error::verifyinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_verification_error::verifyupdate_failed}, + {&fail_EVP_DigestVerifyFinal, 1, jwt::error::signature_verification_error::invalid_signature}, + {&fail_ECDSA_SIG_new, 1, jwt::error::signature_verification_error::create_context_failed}, + {&fail_i2d_ECDSA_SIG, 1, jwt::error::signature_verification_error::signature_encoding_failed}, + {&fail_i2d_ECDSA_SIG, 2, jwt::error::signature_verification_error::signature_encoding_failed}, + }; + + run_multitest(mapping, [&alg, &signature](std::error_code& ec) { alg.verify("testdata", signature, ec); }); +} + +TEST(OpenSSLErrorTest, PS256Reference) { + jwt::algorithm::ps256 alg{rsa_pub_key, rsa_priv_key}; + std::error_code ec; + auto res = alg.sign("testdata", ec); + ASSERT_FALSE(!(!ec)); + + alg.verify("testdata", res, ec); + ASSERT_FALSE(!(!ec)); +} + +TEST(OpenSSLErrorTest, PS256SignErrorCode) { + jwt::algorithm::ps256 alg{rsa_pub_key, rsa_priv_key}; + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_generation_error::create_context_failed}, + {&fail_EVP_DigestSignInit, 1, jwt::error::signature_generation_error::signinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_generation_error::digestupdate_failed}, + {&fail_EVP_DigestSignFinal, 1, jwt::error::signature_generation_error::signfinal_failed}, + //TODO: EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_CTX_set_rsa_pss_saltlen + }; + + run_multitest(mapping, [&alg](std::error_code& ec) { + auto res = alg.sign("testdata", ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, PS256VerifyErrorCode) { + jwt::algorithm::ps256 alg{rsa_pub_key, rsa_priv_key}; + std::string signature = + "LMiWCiW0a/" + "mbU6LK8EZaDQ6TGisqfD+LF46zUbzjhFt02J9yVuf3ZDNTdRgLKKP8nCJUx0SN+5CS2YD268Ioxau5bWs49RVCxtID5DcRpJlSo+Vk+" + "dCmwxhQWHX8HNh3o7kBK5H8fLeTeupuSov+0hH3+" + "GRrYJqZvCdbcadi6amNKCfeIl6a5mp2VCM55NsPoRxsmSzc1G7AHWb1ckOCsm3KY5BL6B074bHgoqO3yaLlKWLAcy4OYyRpJ/wnZQ9PPrhwdq/" + "B59uW3x1QUCKYKgZeqZOoqIP1YgLwvEpPtXYutQCFr4eBKgV7vdtE0wgHR43ka16fi5L4SyaZv53NCg=="; + signature = jwt::base::decode(signature); + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_verification_error::create_context_failed}, + {&fail_EVP_DigestVerifyInit, 1, jwt::error::signature_verification_error::verifyinit_failed}, + {&fail_EVP_DigestUpdate, 1, jwt::error::signature_verification_error::verifyupdate_failed}, + {&fail_EVP_DigestVerifyFinal, 1, jwt::error::signature_verification_error::verifyfinal_failed}, + }; + + run_multitest(mapping, [&alg, &signature](std::error_code& ec) { alg.verify("testdata", signature, ec); }); +} + +#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0) +TEST(OpenSSLErrorTest, EdDSAKey) { + std::vector mapping{ + // load_private_key_from_string + {&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PrivateKey, 1, jwt::error::rsa_error::load_key_bio_read}, + // load_public_key_from_string + {&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + // { &fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read } + }; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::algorithm::ed25519 alg{ed25519_pub_key, ed25519_priv_key}; + FAIL(); // Should never reach this + } catch (const std::system_error& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, EdDSACertificate) { + std::vector mapping{// load_public_key_from_string + {&fail_BIO_new, 1, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_BIO_write, 1, jwt::error::rsa_error::load_key_bio_write}, + {&fail_PEM_read_bio_PUBKEY, 1, jwt::error::rsa_error::load_key_bio_read}, + // extract_pubkey_from_cert + {&fail_BIO_new, 2, jwt::error::rsa_error::create_mem_bio_failed}, + {&fail_PEM_read_bio_X509, 1, jwt::error::rsa_error::cert_load_failed}, + {&fail_X509_get_pubkey, 1, jwt::error::rsa_error::get_key_failed}, + {&fail_PEM_write_bio_PUBKEY, 1, jwt::error::rsa_error::write_key_failed}, + {&fail_BIO_ctrl, 1, jwt::error::rsa_error::convert_to_pem_failed}}; + + run_multitest(mapping, [](std::error_code& ec) { + try { + jwt::algorithm::ed25519 alg{ed25519_certificate}; + FAIL(); // Should never reach this + } catch (const std::system_error& e) { ec = e.code(); } + }); +} + +TEST(OpenSSLErrorTest, Ed25519Reference) { + jwt::algorithm::ed25519 alg{ed25519_pub_key, ed25519_priv_key}; + std::error_code ec; + auto res = alg.sign("testdata", ec); + ASSERT_FALSE(!(!ec)); + + alg.verify("testdata", res, ec); + ASSERT_FALSE(!(!ec)); +} + +TEST(OpenSSLErrorTest, Ed25519SignErrorCode) { + jwt::algorithm::ed25519 alg{ed25519_pub_key, ed25519_priv_key}; + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_generation_error::create_context_failed}, + {&fail_EVP_DigestSignInit, 1, jwt::error::signature_generation_error::signinit_failed}, + {&fail_EVP_DigestSign, 1, jwt::error::signature_generation_error::signfinal_failed}}; + + run_multitest(mapping, [&alg](std::error_code& ec) { + auto res = alg.sign("testdata", ec); + ASSERT_EQ(res, ""); + }); +} + +TEST(OpenSSLErrorTest, Ed25519VerifyErrorCode) { + jwt::algorithm::ed25519 alg{ed25519_pub_key, ed25519_priv_key}; + auto signature = jwt::base::decode( + "aC/NqyHfPw5FDA0yRAnrbkrAlXjsr0obRkCg/HgP+77QYJrAg6YKkKoJwMXjUX8fQrxXKTN7em5L9dtmOep37Q=="); + std::vector mapping{ + {&fail_EVP_MD_CTX_new, 1, jwt::error::signature_verification_error::create_context_failed}, + {&fail_EVP_DigestVerifyInit, 1, jwt::error::signature_verification_error::verifyinit_failed}, + {&fail_EVP_DigestVerify, 1, jwt::error::signature_verification_error::verifyfinal_failed}}; + + run_multitest(mapping, [&alg, &signature](std::error_code& ec) { alg.verify("testdata", signature, ec); }); +} +#endif +#endif +#endif +#endif diff --git a/dep/jwt-cpp/tests/TestMain.cpp b/dep/jwt-cpp/tests/TestMain.cpp new file mode 100644 index 000000000..8f1c9c1b5 --- /dev/null +++ b/dep/jwt-cpp/tests/TestMain.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/dep/jwt-cpp/tests/TokenFormatTest.cpp b/dep/jwt-cpp/tests/TokenFormatTest.cpp new file mode 100644 index 000000000..688c6e509 --- /dev/null +++ b/dep/jwt-cpp/tests/TokenFormatTest.cpp @@ -0,0 +1,16 @@ +#include "jwt-cpp/jwt.h" +#include + +TEST(TokenFormatTest, MissingDot) { + ASSERT_THROW(jwt::decode("eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0.eyJpc3MiOiJhdXRoMCJ9"), std::invalid_argument); + ASSERT_THROW(jwt::decode("eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0eyJpc3MiOiJhdXRoMCJ9."), std::invalid_argument); + ASSERT_THROW(jwt::decode("eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0eyJpc3MiOiJhdXRoMCJ9"), std::invalid_argument); +} + +TEST(TokenFormatTest, InvalidChar) { + ASSERT_THROW(jwt::decode("eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0().eyJpc3MiOiJhdXRoMCJ9."), std::runtime_error); +} + +TEST(TokenFormatTest, InvalidJSON) { + ASSERT_THROW(jwt::decode("YXsiYWxnIjoibm9uZSIsInR5cCI6IkpXUyJ9YQ.eyJpc3MiOiJhdXRoMCJ9."), std::runtime_error); +} diff --git a/dep/jwt-cpp/tests/TokenTest.cpp b/dep/jwt-cpp/tests/TokenTest.cpp new file mode 100644 index 000000000..a64e0d11c --- /dev/null +++ b/dep/jwt-cpp/tests/TokenTest.cpp @@ -0,0 +1,801 @@ +#include "jwt-cpp/jwt.h" +#include + +inline namespace test_keys { + extern std::string rsa_priv_key; + extern std::string rsa_pub_key; + extern std::string rsa_pub_key_invalid; + extern std::string rsa512_priv_key; + extern std::string rsa512_pub_key; + extern std::string rsa512_pub_key_invalid; + extern std::string ecdsa256_certificate; + extern std::string ecdsa256_priv_key; + extern std::string ecdsa256_pub_key; + extern std::string ecdsa256_pub_key_invalid; + extern std::string ecdsa384_priv_key; + extern std::string ecdsa384_pub_key; + extern std::string ecdsa384_pub_key_invalid; + extern std::string ecdsa521_priv_key; + extern std::string ecdsa521_pub_key; + extern std::string ecdsa521_pub_key_invalid; + extern std::string ed25519_priv_key; + extern std::string ed25519_pub_key; + extern std::string ed25519_pub_key_invalid; + extern std::string ed448_priv_key; + extern std::string ed448_pub_key; + extern std::string ed448_pub_key_invalid; +} // namespace test_keys + +TEST(TokenTest, DecodeToken) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_TRUE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_FALSE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWS", decoded.get_type()); + ASSERT_EQ("auth0", decoded.get_issuer()); +} + +TEST(TokenTest, CreateToken) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::none{}); + ASSERT_EQ("eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0.eyJpc3MiOiJhdXRoMCJ9.", token); +} + +TEST(TokenTest, CreateTokenHS256) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::hs256{"secret"}); + ASSERT_EQ("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE", + token); +} + +TEST(TokenTest, CreateTokenRS256) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::rs256(rsa_pub_key, rsa_priv_key, "", "")); + + ASSERT_EQ( + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ", + token); +} + +TEST(TokenTest, CreateTokenRS512) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::rs512(rsa512_pub_key, rsa512_priv_key, "", "")); + + ASSERT_EQ("eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.GZhnjtsvBl2_KDSxg4JW6xnmNjr2mWhYSZSSQyLKvI0" + "TK86sJKchkt_HDy2IC5l5BGRhq_Xv9pHdA1umidQZG3a7gWvHsujqybCBgBraMTd1wJrCl4QxFg2RYHhHbRqb9BnPJgFD_vryd4GB" + "hfGgejPBCBlGrQtqFGFdHHOjNHY", + token); +} + +TEST(TokenTest, CreateTokenPS256) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::ps256(rsa_pub_key, rsa_priv_key, "", "")); + + // TODO: Find a better way to check if generated signature is valid + // Can't do simple check for equal since pss adds random salt. +} + +TEST(TokenTest, CreateTokenPS384) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::ps384(rsa_pub_key, rsa_priv_key, "", "")); + + // TODO: Find a better way to check if generated signature is valid + // Can't do simple check for equal since pss adds random salt. +} + +TEST(TokenTest, CreateTokenPS512) { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::ps512(rsa_pub_key, rsa_priv_key, "", "")); + + // TODO: Find a better way to check if generated signature is valid + // Can't do simple check for equal since pss adds random salt. +} + +TEST(TokenTest, CreateTokenES256) { + + auto token = + jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::es256("", ecdsa256_priv_key, "", "")); + + auto decoded = jwt::decode(token); + + ASSERT_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::es256(ecdsa256_pub_key_invalid, "", "", "")).verify(decoded), + jwt::error::signature_verification_exception); + ASSERT_NO_THROW(jwt::verify().allow_algorithm(jwt::algorithm::es256(ecdsa256_pub_key, "", "", "")).verify(decoded)); +} + +TEST(TokenTest, CreateTokenES256NoPrivate) { + ASSERT_THROW( + []() { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::es256(ecdsa256_pub_key, "", "", "")); + }(), + jwt::error::signature_generation_exception); +} + +TEST(TokenTest, CreateTokenES384) { + + auto token = + jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::es384("", ecdsa384_priv_key, "", "")); + + auto decoded = jwt::decode(token); + + ASSERT_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::es384(ecdsa384_pub_key_invalid, "", "", "")).verify(decoded), + jwt::error::signature_verification_exception); + ASSERT_NO_THROW(jwt::verify().allow_algorithm(jwt::algorithm::es384(ecdsa384_pub_key, "", "", "")).verify(decoded)); +} + +TEST(TokenTest, CreateTokenES384NoPrivate) { + + ASSERT_THROW( + []() { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::es384(ecdsa384_pub_key, "", "", "")); + }(), + jwt::error::signature_generation_exception); +} + +TEST(TokenTest, CreateTokenES512) { + + auto token = + jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::es512("", ecdsa521_priv_key, "", "")); + + auto decoded = jwt::decode(token); + + ASSERT_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::es512(ecdsa521_pub_key_invalid, "", "", "")).verify(decoded), + jwt::error::signature_verification_exception); + ASSERT_NO_THROW(jwt::verify().allow_algorithm(jwt::algorithm::es512(ecdsa521_pub_key, "", "", "")).verify(decoded)); +} + +TEST(TokenTest, CreateTokenES512NoPrivate) { + + ASSERT_THROW( + []() { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign( + jwt::algorithm::es512(ecdsa521_pub_key, "", "", "")); + }(), + jwt::error::signature_generation_exception); +} + +#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0) +TEST(TokenTest, CreateTokenEd25519) { + + auto token = + jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::ed25519("", ed25519_priv_key, "", "")); + + auto decoded = jwt::decode(token); + + ASSERT_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::ed25519(ed25519_pub_key_invalid, "", "", "")).verify(decoded), + jwt::error::signature_verification_exception); + ASSERT_NO_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::ed25519(ed25519_pub_key, "", "", "")).verify(decoded)); +} + +TEST(TokenTest, CreateTokenEd448) { + + auto token = + jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::ed448("", ed448_priv_key, "", "")); + + auto decoded = jwt::decode(token); + + ASSERT_THROW( + jwt::verify().allow_algorithm(jwt::algorithm::ed448(ed448_pub_key_invalid, "", "", "")).verify(decoded), + jwt::error::signature_verification_exception); + ASSERT_NO_THROW(jwt::verify().allow_algorithm(jwt::algorithm::ed448(ed448_pub_key, "", "", "")).verify(decoded)); +} +#endif + +TEST(TokenTest, VerifyTokenWrongAlgorithm) { + std::string token = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); +} + +TEST(TokenTest, VerifyTokenNoneFail) { + // None algorithm should not have a signature + std::string token = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpYXQiOjE1OTUyNjc1MTZ9.cmFuZG9tc2ln"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::none{}); + + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenRS256FailNoKey) { + ASSERT_THROW( + []() { + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::rs256("", "", "", "")).with_issuer("auth0"); + }(), + jwt::error::rsa_exception); +} + +TEST(TokenTest, VerifyTokenRS256) { + std::string token = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::rs256(rsa_pub_key, rsa_priv_key, "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS256PublicOnly) { + std::string token = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::rs256(rsa_pub_key, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS256PrivateOnly) { + std::string token = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::rs256("", rsa_priv_key, "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS256Fail) { + std::string token = + "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.VA2i1ui1cnoD6I3wnji1WAVCf29EekysvevGrT2GXqK1dDMc8" + "HAZCTQxa1Q8NppnpYV-hlqxh-X3Bb0JOePTGzjynpNZoJh2aHZD-GKpZt7OO1Zp8AFWPZ3p8Cahq8536fD8RiBES9jRsvChZvOqA7gMcFc4" + "YD0iZhNIcI7a654u5yPYyTlf5kjR97prCf_OXWRn-bYY74zna4p_bP9oWCL4BkaoRcMxi-IR7kmVcCnvbYqyIrKloXP2qPO442RBGqU7Ov9" + "sGQxiVqtRHKXZR9RbfvjrErY1KGiCp9M5i2bsUHadZEY44FE2jiOmx-uc2z5c05CCXqVSpfCjWbh9gQ"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::rs256(rsa_pub_key_invalid, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenRS512) { + std::string token = + "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.GZhnjtsvBl2_KDSxg4JW6xnmNjr2mWhYSZ" + "SSQyLKvI0TK86sJKchkt_HDy2IC5l5BGRhq_Xv9pHdA1umidQZG3a7gWvHsujqybCBgBraMTd1wJrCl4QxFg2RYHhHbRqb9BnPJgFD_vryd4" + "GBhfGgejPBCBlGrQtqFGFdHHOjNHY"; + + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::rs512(rsa512_pub_key, rsa512_priv_key, "", "")) + .with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS512PublicOnly) { + std::string token = + "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.GZhnjtsvBl2_KDSxg4JW6xnmNjr2mWhYSZ" + "SSQyLKvI0TK86sJKchkt_HDy2IC5l5BGRhq_Xv9pHdA1umidQZG3a7gWvHsujqybCBgBraMTd1wJrCl4QxFg2RYHhHbRqb9BnPJgFD_vryd4" + "GBhfGgejPBCBlGrQtqFGFdHHOjNHY"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::rs512(rsa512_pub_key, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS512PrivateOnly) { + std::string token = + "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.GZhnjtsvBl2_KDSxg4JW6xnmNjr2mWhYSZ" + "SSQyLKvI0TK86sJKchkt_HDy2IC5l5BGRhq_Xv9pHdA1umidQZG3a7gWvHsujqybCBgBraMTd1wJrCl4QxFg2RYHhHbRqb9BnPJgFD_vryd4" + "GBhfGgejPBCBlGrQtqFGFdHHOjNHY"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::rs512("", rsa512_priv_key, "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenRS512Fail) { + std::string token = + "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.GZhnjtsvBl2_KDSxg4JW6xnmNjr2mWhYSZ" + "SSQyLKvI0TK86sJKchkt_HDy2IC5l5BGRhq_Xv9pHdA1umidQZG3a7gWvHsujqybCBgBraMTd1wJrCl4QxFg2RYHhHbRqb9BnPJgFD_vryd4" + "GBhfGgejPBCBlGrQtqFGFdHHOjNHY"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::rs512(rsa_pub_key_invalid, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenHS256) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenHS256Fail) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::hs256{"wrongsecret"}).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenHS256FailSignatureLength) { + std::string token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkA"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyFail) { + { + auto token = jwt::create() + .set_issuer("auth0") + .set_type("JWS") + .set_audience("random") + .set_payload_claim("typetest", picojson::value(10.0)) + .sign(jwt::algorithm::none{}); + + auto decoded_token = jwt::decode(token); + + { + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_issuer("auth"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_type("JWT"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth0") + .with_audience(std::set{"test"}); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_issuer("auth0").with_audience("test"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_issuer("auth0").with_subject("test"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth0") + .with_claim("myclaim", jwt::claim(std::string("test"))); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth0") + .with_claim("typetest", jwt::claim(picojson::value(true))); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + { + jwt::claim object; + std::istringstream iss{R"({ "test": null })"}; + iss >> object; + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_issuer("auth0") + .with_claim("myclaim", object); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + } + { + auto token = jwt::create().set_issuer("auth0").set_type("JWS").sign(jwt::algorithm::none{}); + + auto decoded_token = jwt::decode(token); + + { + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_issuer("auth0").with_audience("test"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + } + } +} + +TEST(TokenTest, VerifyTokenES256FailNoKey) { + ASSERT_THROW( + []() { + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es256("", "", "", "")).with_issuer("auth0"); + }(), + jwt::error::ecdsa_exception); +} + +TEST(TokenTest, VerifyTokenES256) { + const std::string token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_" + "4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es256(ecdsa256_pub_key, "", "", "")); + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenES256Fail) { + const std::string token = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.4iVk3-Y0v4RT4_9IaQlp-8dZ_" + "4fsTzIylgrPTDLrEvTHBTyVS3tgPbr2_IZfLETtiKRqCg0aQ5sh9eIsTTwB1g"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es256(ecdsa256_pub_key_invalid, "", "", "")); + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenES384) { + const std::string token = + "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.nTUwWanmj_K1VZM5it1ES-1FbnmRDL-lH3V_Fem-" + "AhMur9Q61yZfKIydrpdavkm_SMxEsUGPVoqkpoEsjFjrtzMDs5s9yaFYD_ydiy1dsn9VbcI55voA3XwEcWFiPHri"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es384(ecdsa384_pub_key, "", "", "")); + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenES384Fail) { + const std::string token = + "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.nTUwWanmj_K1VZM5it1ES-1FbnmRDL-lH3V_Fem-" + "AhMur9Q61yZfKIydrpdavkm_SMxEsUGPVoqkpoEsjFjrtzMDs5s9yaFYD_ydiy1dsn9VbcI55voA3XwEcWFiPHri"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es384(ecdsa384_pub_key_invalid, "", "", "")); + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenES521) { + const std::string token = + "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.ASF5hh9_Jyujzm3GRBttoth-3I6lCcwqun9Tt7Ekz9_23BN6-" + "BFgwKidECWCNc4VINEqFEFdApC2y3YRdkpKX2etAWI7yYudAlxJ7Z17m6GwAoLOGaeNonsaKOe1UnC5W86eoXrCoPRgzsFTpKIb8NiolcYWjIY" + "-r8gQd7BZ7whaj9Ft"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es512(ecdsa521_pub_key, "", "", "")); + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenES521Fail) { + const std::string token = + "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.ASF5hh9_Jyujzm3GRBttoth-3I6lCcwqun9Tt7Ekz9_23BN6-" + "BFgwKidECWCNc4VINEqFEFdApC2y3YRdkpKX2etAWI7yYudAlxJ7Z17m6GwAoLOGaeNonsaKOe1UnC5W86eoXrCoPRgzsFTpKIb8NiolcYWjIY" + "-r8gQd7BZ7whaj9Ft"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::es512(ecdsa521_pub_key_invalid, "", "", "")); + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenPS256) { + std::string token = + "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.CJ4XjVWdbV6vXGZkD4GdJbtYc80SN9cmPOqRhZBRzOyDRqTFE" + "4MsbdKyQuhAWcvuMOjn-24qOTjVMR_P_uTC1uG6WPLcucxZyLnbb56zbKnEklW2SX0mQnCGewr-93a_vDaFT6Cp45MsF_OwFPRCMaS5CJg-" + "N5KY67UrVSr3s9nkuK9ZTQkyODHfyEUh9F_FhRCATGrb5G7_qHqBYvTvaPUXqzhhpCjN855Tocg7A24Hl0yMwM-XdasucW5xNdKjG_YCkis" + "HX7ax--JiF5GNYCO61eLFteO4THUg-3Z0r4OlGqlppyWo5X5tjcxOZCvBh7WDWfkxA48KFZPRv0nlKA"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::ps256(rsa_pub_key, rsa_priv_key, "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenPS256PublicOnly) { + std::string token = + "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.CJ4XjVWdbV6vXGZkD4GdJbtYc80SN9cmPOqRhZBRzOyDRqTFE" + "4MsbdKyQuhAWcvuMOjn-24qOTjVMR_P_uTC1uG6WPLcucxZyLnbb56zbKnEklW2SX0mQnCGewr-93a_vDaFT6Cp45MsF_OwFPRCMaS5CJg-" + "N5KY67UrVSr3s9nkuK9ZTQkyODHfyEUh9F_FhRCATGrb5G7_qHqBYvTvaPUXqzhhpCjN855Tocg7A24Hl0yMwM-XdasucW5xNdKjG_YCkis" + "HX7ax--JiF5GNYCO61eLFteO4THUg-3Z0r4OlGqlppyWo5X5tjcxOZCvBh7WDWfkxA48KFZPRv0nlKA"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ps256(rsa_pub_key, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenPS256Fail) { + std::string token = + "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.CJ4XjVWdbV6vXGZkD4GdJbtYc80SN9cmPOqRhZBRzOyDRqTFE" + "4MsbdKyQuhAWcvuMOjn-24qOTjVMR_P_uTC1uG6WPLcucxZyLnbb56zbKnEklW2SX0mQnCGewr-93a_vDaFT6Cp45MsF_OwFPRCMaS5CJg-" + "N5KY67UrVSr3s9nkuK9ZTQkyODHfyEUh9F_FhRCATGrb5G7_qHqBYvTvaPUXqzhhpCjN855Tocg7A24Hl0yMwM-XdasucW5xNdKjG_YCkis" + "HX7ax--JiF5GNYCO61eLFteO4THUg-3Z0r4OlGqlppyWo5X5tjcxOZCvBh7WDWfkxA48KFZPRv0nlKA"; + + auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::ps256(rsa_pub_key_invalid, "", "", "")).with_issuer("auth0"); + + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenPS256FailNoKey) { + ASSERT_THROW( + []() { + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ps256("", "", "", "")).with_issuer("auth0"); + }(), + jwt::error::rsa_exception); +} + +#if !defined(JWT_OPENSSL_1_0_0) && !defined(JWT_OPENSSL_1_1_0) +TEST(TokenTest, VerifyTokenEd25519) { + const std::string token = + "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.OujgVcO8xQx5xLcAYWENCRU1SCGH5HcX4MX4o6wU3M4" + "DOnKiNmc0O2AnvQlzr-9cgI4QGQzeC6gz_fgLoesADg"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ed25519(ed25519_pub_key, "", "", "")); + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenEd25519Fail) { + const std::string token = + "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.OujgVcO8xQx5xLcAYWENCRU1SCGH5HcX4MX4o6wU3M4" + "DOnKiNmc0O2AnvQlzr-9cgI4QGQzeC6gz_fgLoesADg"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ed25519(ed25519_pub_key_invalid, "", "", "")); + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} + +TEST(TokenTest, VerifyTokenEd448) { + const std::string token = + "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.Aldes9jrXZXxfNjuovqmIZ3r2WF4yVXVr2Q8B8SkAmv" + "Bsw_3MHs8HtgKeXbqKFYWpHOCtmZJcH-AWMvoY6FCNdQqbESGTkv58O6tFbXDD_nLejWNAOuvcO2LPMySmkVNQUopmQf_HO62Mug1ngepUDE" + "A"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ed448(ed448_pub_key, "", "", "")); + auto decoded_token = jwt::decode(token); + + verify.verify(decoded_token); +} + +TEST(TokenTest, VerifyTokenEd448Fail) { + const std::string token = + "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.Aldes9jrXZXxfNjuovqmIZ3r2WF4yVXVr2Q8B8SkAmv" + "Bsw_3MHs8HtgKeXbqKFYWpHOCtmZJcH-AWMvoY6FCNdQqbESGTkv58O6tFbXDD_nLejWNAOuvcO2LPMySmkVNQUopmQf_HO62Mug1ngepUDE" + "A"; + + auto verify = jwt::verify().allow_algorithm(jwt::algorithm::ed448(ed448_pub_key_invalid, "", "", "")); + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(verify.verify(decoded_token), jwt::error::signature_verification_exception); +} +#endif + +struct test_clock { + jwt::date n; + jwt::date now() const { return n; } +}; + +TEST(TokenTest, VerifyTokenExpireFail) { + auto token = jwt::create().set_expires_at(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(110)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(TokenTest, VerifyTokenExpire) { + auto token = jwt::create().set_expires_at(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(90)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_NO_THROW(verify.verify(decoded_token)); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +TEST(TokenTest, VerifyTokenNBFFail) { + auto token = jwt::create().set_not_before(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(90)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(TokenTest, VerifyTokenNBF) { + auto token = jwt::create().set_not_before(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(110)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_NO_THROW(verify.verify(decoded_token)); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +TEST(TokenTest, VerifyTokenIATFail) { + auto token = jwt::create().set_issued_at(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(90)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(TokenTest, VerifyTokenIAT) { + auto token = jwt::create().set_issued_at(std::chrono::system_clock::from_time_t(100)).sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify({std::chrono::system_clock::from_time_t(110)}) + .allow_algorithm(jwt::algorithm::none{}); + ASSERT_NO_THROW(verify.verify(decoded_token)); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +TEST(TokenTest, VerifyTokenType) { + auto token = jwt::create().set_type("JWS").sign(jwt::algorithm::none{}); + auto decoded_token = jwt::decode(token); + + auto verify = jwt::verify().with_type("jws").allow_algorithm(jwt::algorithm::none{}); + ASSERT_NO_THROW(verify.verify(decoded_token)); + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_FALSE(!(!ec)); + ASSERT_EQ(ec.value(), 0); +} + +TEST(TokenTest, GetClaimThrows) { + auto token = "eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0.eyJpc3MiOiJhdXRoMCJ9."; + auto decoded_token = jwt::decode(token); + + ASSERT_THROW(decoded_token.get_header_claim("test"), jwt::error::claim_not_present_exception); + ASSERT_THROW(decoded_token.get_payload_claim("test"), jwt::error::claim_not_present_exception); +} + +TEST(TokenTest, ThrowInvalidKeyLength) { + // We should throw if passed the wrong size + ASSERT_THROW(jwt::algorithm::es256(ecdsa384_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256("", ecdsa384_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256(ecdsa384_pub_key, ecdsa384_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256(ecdsa521_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256("", ecdsa521_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256(ecdsa521_pub_key, ecdsa521_priv_key), jwt::error::ecdsa_exception); + + // But also if only one cert has the wrong size + ASSERT_THROW(jwt::algorithm::es256(ecdsa256_pub_key, ecdsa384_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es256(ecdsa256_pub_key, ecdsa521_priv_key), jwt::error::ecdsa_exception); + + ASSERT_THROW(jwt::algorithm::es384(ecdsa256_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384("", ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384(ecdsa256_pub_key, ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384(ecdsa521_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384("", ecdsa521_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384(ecdsa521_pub_key, ecdsa521_priv_key), jwt::error::ecdsa_exception); + + ASSERT_THROW(jwt::algorithm::es384(ecdsa384_pub_key, ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es384(ecdsa384_pub_key, ecdsa521_priv_key), jwt::error::ecdsa_exception); + + ASSERT_THROW(jwt::algorithm::es512(ecdsa256_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512("", ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512(ecdsa256_pub_key, ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512(ecdsa384_pub_key, ""), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512("", ecdsa384_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512(ecdsa384_pub_key, ecdsa384_priv_key), jwt::error::ecdsa_exception); + + ASSERT_THROW(jwt::algorithm::es512(ecdsa521_pub_key, ecdsa256_priv_key), jwt::error::ecdsa_exception); + ASSERT_THROW(jwt::algorithm::es512(ecdsa521_pub_key, ecdsa384_priv_key), jwt::error::ecdsa_exception); + + // Make sure we do not throw if the correct params are passed + ASSERT_NO_THROW(jwt::algorithm::es256(ecdsa256_pub_key, ecdsa256_priv_key)); + ASSERT_NO_THROW(jwt::algorithm::es384(ecdsa384_pub_key, ecdsa384_priv_key)); + ASSERT_NO_THROW(jwt::algorithm::es512(ecdsa521_pub_key, ecdsa521_priv_key)); +} + +TEST(TokenTest, MoveDecodedToken) { + std::string token0 = "eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0.eyJpc3MiOiJhdXRoMCJ9."; + std::string token1 = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + auto decoded_token0 = jwt::decode(token0); + auto decoded_token1 = jwt::decode(token1); + decoded_token0 = std::move(decoded_token1); + ASSERT_EQ(token1, decoded_token0.get_token()); + + ASSERT_TRUE(decoded_token0.has_algorithm()); + ASSERT_TRUE(decoded_token0.has_type()); + ASSERT_FALSE(decoded_token0.has_content_type()); + ASSERT_FALSE(decoded_token0.has_key_id()); + ASSERT_TRUE(decoded_token0.has_issuer()); + ASSERT_FALSE(decoded_token0.has_subject()); + ASSERT_FALSE(decoded_token0.has_audience()); + ASSERT_FALSE(decoded_token0.has_expires_at()); + ASSERT_FALSE(decoded_token0.has_not_before()); + ASSERT_FALSE(decoded_token0.has_issued_at()); + ASSERT_FALSE(decoded_token0.has_id()); + + ASSERT_EQ("HS256", decoded_token0.get_algorithm()); + ASSERT_EQ("JWS", decoded_token0.get_type()); + ASSERT_EQ("auth0", decoded_token0.get_issuer()); +} diff --git a/dep/jwt-cpp/tests/cmake/CMakeLists.txt b/dep/jwt-cpp/tests/cmake/CMakeLists.txt new file mode 100644 index 000000000..56acedc39 --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.8) +project(jwt-cpp-installation-tests) + +set(TEST CACHE STRING "The test source file to be used") + +find_package(jwt-cpp 0.6.0 EXACT REQUIRED CONFIG) + +add_executable(test-project ${TEST}.cpp) +target_link_libraries(test-project jwt-cpp::jwt-cpp) diff --git a/dep/jwt-cpp/tests/cmake/base64-is-disabled.cpp b/dep/jwt-cpp/tests/cmake/base64-is-disabled.cpp new file mode 100644 index 000000000..3f3ac5620 --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/base64-is-disabled.cpp @@ -0,0 +1,10 @@ +#ifndef JWT_DISABLE_BASE64 +#error "This test expects 'JWT_DISABLE_BASE64' to be defined!" +#endif + +#include "jwt-cpp/jwt.h" + +int main() { + jwt::date date; + return 0; +} diff --git a/dep/jwt-cpp/tests/cmake/defaults-enabled.cpp b/dep/jwt-cpp/tests/cmake/defaults-enabled.cpp new file mode 100644 index 000000000..9699c30de --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/defaults-enabled.cpp @@ -0,0 +1,6 @@ +#include "jwt-cpp/jwt.h" + +int main() { + jwt::claim claim; + return 0; +} diff --git a/dep/jwt-cpp/tests/cmake/libressl-is-used.cpp b/dep/jwt-cpp/tests/cmake/libressl-is-used.cpp new file mode 100644 index 000000000..7305a3f7e --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/libressl-is-used.cpp @@ -0,0 +1,13 @@ +#if !__has_include() +#error "missing LibreSSL's TLS header!" +#endif + +#include + +#include "jwt-cpp/jwt.h" + +int main() { + tls_init(); + jwt::date date; + return 0; +} diff --git a/dep/jwt-cpp/tests/cmake/picojson-is-disabled.cpp b/dep/jwt-cpp/tests/cmake/picojson-is-disabled.cpp new file mode 100644 index 000000000..a6baf37c4 --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/picojson-is-disabled.cpp @@ -0,0 +1,10 @@ +#ifndef JWT_DISABLE_PICOJSON +#error "This test expects 'JWT_DISABLE_PICOJSON' to be defined!" +#endif + +#include "jwt-cpp/jwt.h" + +int main() { + jwt::date date; + return 0; +} diff --git a/dep/jwt-cpp/tests/cmake/wolfssl-is-used.cpp b/dep/jwt-cpp/tests/cmake/wolfssl-is-used.cpp new file mode 100644 index 000000000..ca05316a9 --- /dev/null +++ b/dep/jwt-cpp/tests/cmake/wolfssl-is-used.cpp @@ -0,0 +1,21 @@ +#if !__has_include() +#error "missing wolfSSL's SSL header!" +#endif + +#ifndef OPENSSL_EXTRA +#error "missing wolfSSL's OPENSSL_EXTRA macro!" +#endif + +#ifndef OPENSSL_ALL +#error "missing wolfSSL's OPENSSL_ALL macro!" +#endif + +#include "jwt-cpp/jwt.h" + +#include + +int main() { + wolfSSL_library_init(); + jwt::date date; + return 0; +} diff --git a/dep/jwt-cpp/tests/fuzz/BaseDecodeFuzz.cpp b/dep/jwt-cpp/tests/fuzz/BaseDecodeFuzz.cpp new file mode 100644 index 000000000..5dc4f003b --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/BaseDecodeFuzz.cpp @@ -0,0 +1,13 @@ +#include + +extern "C" { + +int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { + try { + const auto bin = jwt::base::decode(std::string{(char*)Data, Size}); + } catch (const std::runtime_error&) { + // parse errors are ok, because input may be random bytes + } + return 0; // Non-zero return values are reserved for future use. +} +} diff --git a/dep/jwt-cpp/tests/fuzz/BaseEncodeFuzz.cpp b/dep/jwt-cpp/tests/fuzz/BaseEncodeFuzz.cpp new file mode 100644 index 000000000..9ac80252d --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/BaseEncodeFuzz.cpp @@ -0,0 +1,9 @@ +#include + +extern "C" { + +int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { + jwt::base::encode(std::string{(char*)Data, Size}); + return 0; // Non-zero return values are reserved for future use. +} +} diff --git a/dep/jwt-cpp/tests/fuzz/CMakeLists.txt b/dep/jwt-cpp/tests/fuzz/CMakeLists.txt new file mode 100644 index 000000000..1860731fe --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/CMakeLists.txt @@ -0,0 +1,20 @@ +if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) + message(FATAL_ERROR "Fuzzing is only available on Clang") +endif() + +function(ADD_FUZZING_EXECUTABLE TARGET) + add_executable(jwt-cpp-fuzz-${TARGET} "${TARGET}.cpp") + target_compile_options( + jwt-cpp-fuzz-${TARGET} + PRIVATE -g -O1 -fsanitize=fuzzer,address,signed-integer-overflow,undefined + -fno-omit-frame-pointer) + target_link_options( + jwt-cpp-fuzz-${TARGET} PRIVATE + -fsanitize=fuzzer,address,signed-integer-overflow,undefined + -fno-omit-frame-pointer) + target_link_libraries(jwt-cpp-fuzz-${TARGET} PRIVATE jwt-cpp::jwt-cpp) +endfunction() + +add_fuzzing_executable(BaseEncodeFuzz) +add_fuzzing_executable(BaseDecodeFuzz) +add_fuzzing_executable(TokenDecodeFuzz) diff --git a/dep/jwt-cpp/tests/fuzz/TokenDecodeFuzz.cpp b/dep/jwt-cpp/tests/fuzz/TokenDecodeFuzz.cpp new file mode 100644 index 000000000..6a23c2217 --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/TokenDecodeFuzz.cpp @@ -0,0 +1,27 @@ +#include + +extern "C" { + +int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { + try { + // step 1: parse input + const auto jwt1 = jwt::decode(std::string{(char*)Data, Size}); + + try { + // step 2: round trip + std::string s1 = jwt1.get_token(); + const auto jwt2 = jwt::decode(s1); + + // tokens must match + if (s1 != jwt2.get_token()) abort(); + } catch (...) { + // parsing raw data twice must not fail + abort(); + } + } catch (...) { + // parse errors are ok, because input may be random bytes + } + + return 0; // Non-zero return values are reserved for future use. +} +} diff --git a/dep/jwt-cpp/tests/fuzz/decode-corpus/086a3aa337038cac8a75a05131444f222e48aee8 b/dep/jwt-cpp/tests/fuzz/decode-corpus/086a3aa337038cac8a75a05131444f222e48aee8 new file mode 100644 index 000000000..510325478 --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/decode-corpus/086a3aa337038cac8a75a05131444f222e48aee8 @@ -0,0 +1 @@ +FMF= \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/decode-corpus/8ebaef2304e91465585c8d7fcf4d9f939e08d6b4 b/dep/jwt-cpp/tests/fuzz/decode-corpus/8ebaef2304e91465585c8d7fcf4d9f939e08d6b4 new file mode 100644 index 000000000..4ce4f4553 --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/decode-corpus/8ebaef2304e91465585c8d7fcf4d9f939e08d6b4 @@ -0,0 +1 @@ +eCy \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/decode-corpus/ba528234d9f6949ed9c9626c08a782f6e7c15b8b b/dep/jwt-cpp/tests/fuzz/decode-corpus/ba528234d9f6949ed9c9626c08a782f6e7c15b8b new file mode 100644 index 000000000..d2563290e --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/decode-corpus/ba528234d9f6949ed9c9626c08a782f6e7c15b8b @@ -0,0 +1 @@ +FF== \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/decode-corpus/de1028a3fe87471f027522c3ed9ec02b8364a006 b/dep/jwt-cpp/tests/fuzz/decode-corpus/de1028a3fe87471f027522c3ed9ec02b8364a006 new file mode 100644 index 000000000..f66ae60aa --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/decode-corpus/de1028a3fe87471f027522c3ed9ec02b8364a006 @@ -0,0 +1 @@ +eCyIcHzyc2RQHa1EchsP11BhieWRIdm2MToLRpVLKFGNKFvfXIEinoFpLvÿæ \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/decode-corpus/e8f531caaa67cecb1c7b162f3e1d4e320d79befd b/dep/jwt-cpp/tests/fuzz/decode-corpus/e8f531caaa67cecb1c7b162f3e1d4e320d79befd new file mode 100644 index 000000000..0245b58cf --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/decode-corpus/e8f531caaa67cecb1c7b162f3e1d4e320d79befd @@ -0,0 +1 @@ +eCyI \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/token-corpus/9d891e731f75deae56884d79e9816736b7488080 b/dep/jwt-cpp/tests/fuzz/token-corpus/9d891e731f75deae56884d79e9816736b7488080 new file mode 100644 index 000000000..a96aa0ea9 --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/token-corpus/9d891e731f75deae56884d79e9816736b7488080 @@ -0,0 +1 @@ +.. \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/token-corpus/ff384e2421a333cd52f259cec14c7f790d595db9 b/dep/jwt-cpp/tests/fuzz/token-corpus/ff384e2421a333cd52f259cec14c7f790d595db9 new file mode 100644 index 000000000..d6b84aac8 --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/token-corpus/ff384e2421a333cd52f259cec14c7f790d595db9 @@ -0,0 +1 @@ +eyJhbGci.. \ No newline at end of file diff --git a/dep/jwt-cpp/tests/fuzz/token-corpus/valid-sample b/dep/jwt-cpp/tests/fuzz/token-corpus/valid-sample new file mode 100644 index 000000000..d16e17a9a --- /dev/null +++ b/dep/jwt-cpp/tests/fuzz/token-corpus/valid-sample @@ -0,0 +1 @@ +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE \ No newline at end of file diff --git a/dep/jwt-cpp/tests/traits/BoostJsonTest.cpp b/dep/jwt-cpp/tests/traits/BoostJsonTest.cpp new file mode 100644 index 000000000..058ce3859 --- /dev/null +++ b/dep/jwt-cpp/tests/traits/BoostJsonTest.cpp @@ -0,0 +1,128 @@ +#include "jwt-cpp/traits/boost-json/traits.h" + +#include + +TEST(BoostJsonTest, BasicClaims) { + const auto string = jwt::basic_claim(jwt::traits::boost_json::string_type("string")); + ASSERT_EQ(string.get_type(), jwt::json::type::string); + + const auto array = + jwt::basic_claim(std::set{"string", "string"}); + ASSERT_EQ(array.get_type(), jwt::json::type::array); + + jwt::traits::boost_json::value_type jvi = 159816816; + const auto integer = jwt::basic_claim(jvi); + ASSERT_EQ(integer.get_type(), jwt::json::type::integer); +} + +TEST(BoostJsonTest, AudienceAsString) { + jwt::traits::boost_json::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.WZnM3SIiSRHsbO3O7Z2bmIzTJ4EC32HRBKfLznHhrh4"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(1, aud.size()); + ASSERT_EQ("test", *aud.begin()); +} + +TEST(BoostJsonTest, SetArray) { + std::vector vect = {100, 20, 10}; + auto token = jwt::create() + .set_payload_claim("test", jwt::basic_claim(vect.begin(), vect.end())) + .sign(jwt::algorithm::none{}); + ASSERT_EQ(token, "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."); +} + +TEST(BoostJsonTest, SetObject) { + jwt::traits::boost_json::value_type value; + ASSERT_TRUE(jwt::traits::boost_json::parse(value, "{\"api-x\": [1]}")); + jwt::basic_claim object(value); + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto token = jwt::create() + .set_payload_claim("namespace", object) + .sign(jwt::algorithm::hs256("test")); + ASSERT_EQ(token, + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"); +} + +TEST(BoostJsonTest, VerifyTokenHS256) { + jwt::traits::boost_json::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(BoostJsonTest, VerifyTokenExpirationValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(BoostJsonTest, VerifyTokenExpired) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now() - std::chrono::seconds{3601}) + .set_expires_at(std::chrono::system_clock::now() - std::chrono::seconds{1}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(BoostJsonTest, VerifyArray) { + jwt::traits::boost_json::string_type token = "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."; + const auto decoded_token = jwt::decode(token); + + std::vector vect = {100, 20, 10}; + jwt::basic_claim array_claim(vect.begin(), vect.end()); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::none{}).with_claim("test", array_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} + +TEST(BoostJsonTest, VerifyObject) { + jwt::traits::boost_json::string_type token = + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"; + const auto decoded_token = jwt::decode(token); + + jwt::traits::boost_json::value_type value; + ASSERT_TRUE(jwt::traits::boost_json::parse(value, "{\"api-x\": [1]}")); + jwt::basic_claim object_claim(value); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256("test")) + .with_claim("namespace", object_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} diff --git a/dep/jwt-cpp/tests/traits/JsonconsTest.cpp b/dep/jwt-cpp/tests/traits/JsonconsTest.cpp new file mode 100644 index 000000000..685b1df9e --- /dev/null +++ b/dep/jwt-cpp/tests/traits/JsonconsTest.cpp @@ -0,0 +1,133 @@ +#include "jwt-cpp/traits/danielaparker-jsoncons/traits.h" + +#include + +TEST(JsonconsTest, BasicClaims) { + const auto string = jwt::basic_claim( + jwt::traits::danielaparker_jsoncons::string_type("string")); + ASSERT_EQ(string.get_type(), jwt::json::type::string); + + const auto array = jwt::basic_claim( + std::set{"string", "string"}); + ASSERT_EQ(array.get_type(), jwt::json::type::array); + + const auto integer = jwt::basic_claim(159816816); + ASSERT_EQ(integer.get_type(), jwt::json::type::integer); +} + +TEST(JsonconsTest, AudienceAsString) { + jwt::traits::danielaparker_jsoncons::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.WZnM3SIiSRHsbO3O7Z2bmIzTJ4EC32HRBKfLznHhrh4"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(1, aud.size()); + ASSERT_EQ("test", *aud.begin()); +} + +TEST(JsonconsTest, SetArray) { + std::vector vect = {100, 20, 10}; + auto token = + jwt::create() + .set_payload_claim("test", jwt::basic_claim(vect.begin(), vect.end())) + .sign(jwt::algorithm::none{}); + ASSERT_EQ(token, "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."); +} + +TEST(JsonconsTest, SetObject) { + std::istringstream iss{"{\"api-x\": [1]}"}; + jwt::basic_claim object; + iss >> object; + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto token = jwt::create() + .set_payload_claim("namespace", object) + .sign(jwt::algorithm::hs256("test")); + ASSERT_EQ(token, + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"); +} + +TEST(JsonconsTest, VerifyTokenHS256) { + jwt::traits::danielaparker_jsoncons::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(JsonconsTest, VerifyTokenExpirationValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(JsonconsTest, VerifyTokenExpired) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now() - std::chrono::seconds{3601}) + .set_expires_at(std::chrono::system_clock::now() - std::chrono::seconds{1}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(JsonconsTest, VerifyArray) { + jwt::traits::danielaparker_jsoncons::string_type token = "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."; + const auto decoded_token = jwt::decode(token); + + std::vector vect = {100, 20, 10}; + jwt::basic_claim array_claim(vect.begin(), vect.end()); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_claim("test", array_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} + +TEST(JsonconsTest, VerifyObject) { + jwt::traits::danielaparker_jsoncons::string_type token = + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"; + const auto decoded_token = jwt::decode(token); + + jwt::basic_claim object_claim; + std::istringstream iss{"{\"api-x\": [1]}"}; + iss >> object_claim; + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256("test")) + .with_claim("namespace", object_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} diff --git a/dep/jwt-cpp/tests/traits/NlohmannTest.cpp b/dep/jwt-cpp/tests/traits/NlohmannTest.cpp new file mode 100644 index 000000000..faa303eee --- /dev/null +++ b/dep/jwt-cpp/tests/traits/NlohmannTest.cpp @@ -0,0 +1,128 @@ +#include "jwt-cpp/traits/nlohmann-json/traits.h" + +#include + +TEST(NlohmannTest, BasicClaims) { + const auto string = jwt::basic_claim(jwt::traits::nlohmann_json::string_type("string")); + ASSERT_EQ(string.get_type(), jwt::json::type::string); + + const auto array = jwt::basic_claim( + std::set{"string", "string"}); + ASSERT_EQ(array.get_type(), jwt::json::type::array); + + const auto integer = jwt::basic_claim(159816816); + ASSERT_EQ(integer.get_type(), jwt::json::type::integer); +} + +TEST(NlohmannTest, AudienceAsString) { + jwt::traits::nlohmann_json::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.WZnM3SIiSRHsbO3O7Z2bmIzTJ4EC32HRBKfLznHhrh4"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(1, aud.size()); + ASSERT_EQ("test", *aud.begin()); +} + +TEST(NlohmannTest, SetArray) { + std::vector vect = {100, 20, 10}; + auto token = jwt::create() + .set_payload_claim("test", jwt::basic_claim(vect.begin(), vect.end())) + .sign(jwt::algorithm::none{}); + ASSERT_EQ(token, "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."); +} + +TEST(NlohmannTest, SetObject) { + std::istringstream iss{"{\"api-x\": [1]}"}; + jwt::basic_claim object; + iss >> object; + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto token = jwt::create() + .set_payload_claim("namespace", object) + .sign(jwt::algorithm::hs256("test")); + ASSERT_EQ(token, + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"); +} + +TEST(NlohmannTest, VerifyTokenHS256) { + jwt::traits::nlohmann_json::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(NlohmannTest, VerifyTokenExpirationValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST(NlohmannTest, VerifyTokenExpired) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now() - std::chrono::seconds{3601}) + .set_expires_at(std::chrono::system_clock::now() - std::chrono::seconds{1}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = + jwt::verify().allow_algorithm(jwt::algorithm::hs256{"secret"}).with_issuer("auth0"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST(NlohmannTest, VerifyArray) { + jwt::traits::nlohmann_json::string_type token = "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."; + const auto decoded_token = jwt::decode(token); + + std::vector vect = {100, 20, 10}; + jwt::basic_claim array_claim(vect.begin(), vect.end()); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_claim("test", array_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} + +TEST(NlohmannTest, VerifyObject) { + jwt::traits::nlohmann_json::string_type token = + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"; + const auto decoded_token = jwt::decode(token); + + jwt::basic_claim object_claim; + std::istringstream iss{"{\"api-x\": [1]}"}; + iss >> object_claim; + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256("test")) + .with_claim("namespace", object_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} diff --git a/dep/jwt-cpp/tests/traits/TraitsTest.cpp.mustache b/dep/jwt-cpp/tests/traits/TraitsTest.cpp.mustache new file mode 100644 index 000000000..db7d8c417 --- /dev/null +++ b/dep/jwt-cpp/tests/traits/TraitsTest.cpp.mustache @@ -0,0 +1,133 @@ +#include "jwt-cpp/traits/{{traits_dir}}/traits.h" + +#include + +TEST({{test_suite_name}}, BasicClaims) { + const auto string = jwt::basic_claim( + jwt::traits::{{traits_name}}::string_type("string")); + ASSERT_EQ(string.get_type(), jwt::json::type::string); + + const auto array = jwt::basic_claim( + std::set{"string", "string"}); + ASSERT_EQ(array.get_type(), jwt::json::type::array); + + const auto integer = jwt::basic_claim(159816816); + ASSERT_EQ(integer.get_type(), jwt::json::type::integer); +} + +TEST({{test_suite_name}}, AudienceAsString) { + jwt::traits::{{traits_name}}::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0In0.WZnM3SIiSRHsbO3O7Z2bmIzTJ4EC32HRBKfLznHhrh4"; + auto decoded = jwt::decode(token); + + ASSERT_TRUE(decoded.has_algorithm()); + ASSERT_TRUE(decoded.has_type()); + ASSERT_FALSE(decoded.has_content_type()); + ASSERT_FALSE(decoded.has_key_id()); + ASSERT_FALSE(decoded.has_issuer()); + ASSERT_FALSE(decoded.has_subject()); + ASSERT_TRUE(decoded.has_audience()); + ASSERT_FALSE(decoded.has_expires_at()); + ASSERT_FALSE(decoded.has_not_before()); + ASSERT_FALSE(decoded.has_issued_at()); + ASSERT_FALSE(decoded.has_id()); + + ASSERT_EQ("HS256", decoded.get_algorithm()); + ASSERT_EQ("JWT", decoded.get_type()); + auto aud = decoded.get_audience(); + ASSERT_EQ(1, aud.size()); + ASSERT_EQ("test", *aud.begin()); +} + +TEST({{test_suite_name}}, SetArray) { + std::vector vect = {100, 20, 10}; + auto token = + jwt::create() + .set_payload_claim("test", jwt::basic_claim(vect.begin(), vect.end())) + .sign(jwt::algorithm::none{}); + ASSERT_EQ(token, "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."); +} + +TEST({{test_suite_name}}, SetObject) { + std::istringstream iss{"{\"api-x\": [1]}"}; + jwt::basic_claim object; + iss >> object; + ASSERT_EQ(object.get_type(), jwt::json::type::object); + + auto token = jwt::create() + .set_payload_claim("namespace", object) + .sign(jwt::algorithm::hs256("test")); + ASSERT_EQ(token, + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"); +} + +TEST({{test_suite_name}}, VerifyTokenHS256) { + jwt::traits::{{traits_name}}::string_type token = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE"; + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST({{test_suite_name}}, VerifyTokenExpirationValid) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now()) + .set_expires_at(std::chrono::system_clock::now() + std::chrono::seconds{3600}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + verify.verify(decoded_token); +} + +TEST({{test_suite_name}}, VerifyTokenExpired) { + const auto token = jwt::create() + .set_issuer("auth0") + .set_issued_at(std::chrono::system_clock::now() - std::chrono::seconds{3601}) + .set_expires_at(std::chrono::system_clock::now() - std::chrono::seconds{1}) + .sign(jwt::algorithm::hs256{"secret"}); + + const auto decoded_token = jwt::decode(token); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256{"secret"}) + .with_issuer("auth0"); + ASSERT_THROW(verify.verify(decoded_token), jwt::error::token_verification_exception); + + std::error_code ec; + ASSERT_NO_THROW(verify.verify(decoded_token, ec)); + ASSERT_TRUE(!(!ec)); + ASSERT_EQ(ec.category(), jwt::error::token_verification_error_category()); + ASSERT_EQ(ec.value(), static_cast(jwt::error::token_verification_error::token_expired)); +} + +TEST({{test_suite_name}}, VerifyArray) { + jwt::traits::{{traits_name}}::string_type token = "eyJhbGciOiJub25lIn0.eyJ0ZXN0IjpbMTAwLDIwLDEwXX0."; + const auto decoded_token = jwt::decode(token); + + std::vector vect = {100, 20, 10}; + jwt::basic_claim array_claim(vect.begin(), vect.end()); + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::none{}) + .with_claim("test", array_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +} + +TEST({{test_suite_name}}, VerifyObject) { + jwt::traits::{{traits_name}}::string_type token = + "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lc3BhY2UiOnsiYXBpLXgiOlsxXX19.F8I6I2RcSF98bKa0IpIz09fRZtHr1CWnWKx2za-tFQA"; + const auto decoded_token = jwt::decode(token); + + jwt::basic_claim object_claim; + std::istringstream iss{"{\"api-x\": [1]}"}; + iss >> object_claim; + const auto verify = jwt::verify() + .allow_algorithm(jwt::algorithm::hs256("test")) + .with_claim("namespace", object_claim); + ASSERT_NO_THROW(verify.verify(decoded_token)); +}