diff --git a/.github/actions/generate-defaults-dot-h/action.yml b/.github/actions/generate-defaults-dot-h/action.yml new file mode 100644 index 000000000..808494462 --- /dev/null +++ b/.github/actions/generate-defaults-dot-h/action.yml @@ -0,0 +1,7 @@ +name: "Render `defaults.h` Template" +description: "Generate all the `defaults.h` header file for JSON libraries" +runs: + using: composite + steps: + - run: ${{ github.action_path }}/configure-traits.sh + shell: bash diff --git a/.github/actions/generate-defaults-dot-h/configure-traits.sh b/.github/actions/generate-defaults-dot-h/configure-traits.sh new file mode 100755 index 000000000..f815bd01e --- /dev/null +++ b/.github/actions/generate-defaults-dot-h/configure-traits.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Trait metadata configuration for generating defaults.h files +# Maps trait names to their library information + +set -e # Exit on error + +# Define traits metadata as pipe-delimited strings +# Format: TRAITS_NAME|LIBRARY_NAME|LIBRARY_URL|DISABLE_DEFAULT_TRAITS +JWT_TRAITS_METADATA=( + "kazuho_picojson|picojson|https://github.com/kazuho/picojson|false" + "nlohmann_json|JSON for Modern C++|https://github.com/nlohmann/json|true" + "boost_json|Boost.JSON|https://github.com/boostorg/json|true" + "danielaparker_jsoncons|jsoncons|https://github.com/danielaparker/jsoncons|true" + "open_source_parsers_jsoncpp|jsoncpp|https://github.com/open-source-parsers/jsoncpp|true" + "glaze_json|Glaze|https://github.com/stephenberry/glaze|true" + "reflectcpp_json|ReflectCpp|https://github.com/getml/reflect-cpp|true" +) + +# Function to configure traits defaults +configure_traits_defaults() { + for trait_meta in "${JWT_TRAITS_METADATA[@]}"; do + # Split the metadata by pipe delimiter + IFS='|' read -r TRAITS_NAME LIBRARY_NAME LIBRARY_URL DISABLE_DEFAULT_TRAITS <<< "$trait_meta" + + # Call the CMake script to generate defaults.h for this trait + if ! cmake \ + -DTRAITS_NAME="$TRAITS_NAME" \ + -DLIBRARY_NAME="$LIBRARY_NAME" \ + -DLIBRARY_URL="$LIBRARY_URL" \ + -DDISABLE_DEFAULT_TRAITS="$DISABLE_DEFAULT_TRAITS" \ + -P "cmake/generate-defaults-h.cmake"; then + echo "::error::Failed to configure defaults.h for $TRAITS_NAME" + fi + done +} + +# Execute the configuration +configure_traits_defaults diff --git a/.github/actions/process-linting-results/action.yml b/.github/actions/process-linting-results/action.yml index 55d350496..1fd65d7bb 100644 --- a/.github/actions/process-linting-results/action.yml +++ b/.github/actions/process-linting-results/action.yml @@ -10,17 +10,4 @@ runs: - run: git add --update shell: bash - id: stage - #continue-on-error: true uses: Thalhammer/patch-generator-action@v3 - - # Unfortunately the previous action reports a failure so nothing else can run - # partially a limitation on composite actions since `continue-on-error` is not - # yet supported - - if: steps.stage.outputs.result == 'dirty' - uses: actions-ecosystem/action-create-comment@v1 - with: - github_token: ${{ github.token }} - body: | - Hello, @${{ github.actor }}! `${{ inputs.linter_name }}` had some concerns :scream: - - run: exit $(git status -uno -s | wc -l) - shell: bash diff --git a/.github/actions/render/defaults/action.yml b/.github/actions/render/defaults/action.yml deleted file mode 100644 index 4942e00d4..000000000 --- a/.github/actions/render/defaults/action.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: "Render `defaults.h` Template" -description: "Generate the `defaults.h` header file for a JSON library" -inputs: - traits_name: - description: "Name of the traits structure to be used. Typically in the format `author_repository` or equivilant" - required: true - library_name: - description: "Name of the JSON library." - required: true - library_url: - description: "URL to the JSON library." - required: true - disable_default_traits: - description: "Set the macro to disable the default traits" - required: false - default: "true" -outputs: - file_path: - description: "Relative path which the 'defaults.h' was written to" - value: ${{ steps.script.outputs.result }} -runs: - using: composite - steps: - - uses: actions/setup-node@v3 - with: - node-version: 14 - - run: npm install mustache - shell: bash - - uses: actions/github-script@v6 - id: script - env: - TRAITS_NAME: ${{ inputs.traits_name }} - LIBRARY_NAME: ${{ inputs.library_name }} - LIBRARY_URL: ${{ inputs.library_url }} - DISABLE_DEFAULT_TRAITS: ${{ inputs.disable_default_traits }} - with: - result-encoding: string - script: | - const mustache = require('mustache') - const path = require('path') - const fs = require('fs') - - const { TRAITS_NAME, LIBRARY_NAME, LIBRARY_URL, DISABLE_DEFAULT_TRAITS } = process.env - console.log(`Rendering ${TRAITS_NAME}!`) - - const disableDefault = DISABLE_DEFAULT_TRAITS === 'true' - - const template = fs.readFileSync(path.join('include', 'jwt-cpp', 'traits', 'defaults.h.mustache'), 'utf8') - const content = mustache.render(template, { - traits_name: TRAITS_NAME, - traits_name_upper: TRAITS_NAME.toUpperCase(), - library_name: LIBRARY_NAME, - library_url: LIBRARY_URL, - disable_default_traits: disableDefault, - }) - // https://dmitripavlutin.com/replace-all-string-occurrences-javascript/ - function replaceAll(string, search, replace) { - return string.split(search).join(replace); - } - - const outputDir = path.join('include', 'jwt-cpp', 'traits', replaceAll(TRAITS_NAME, '_', '-')) - fs.mkdirSync(outputDir, { recursive: true }) - - const filePath = path.join(outputDir, 'defaults.h') - fs.writeFileSync(filePath, content) - - return filePath diff --git a/.github/actions/render/tests/action.yml b/.github/actions/render/tests/action.yml deleted file mode 100644 index fe1f58649..000000000 --- a/.github/actions/render/tests/action.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: "Render `TraitsTests.cpp` Template" -description: "Generate the `TraitsTests.cpp` header file for a JSON library" -inputs: - traits_name: - description: "Name of the traits structure to be used. Typically in the format `author_repository` or equivilant" - required: true - test_suite_name: - description: "Name of the JSON library." - required: true -runs: - using: composite - steps: - - uses: actions/setup-node@v3 - with: - node-version: 14 - - run: npm install mustache - shell: bash - - uses: actions/github-script@v6 - env: - TRAITS_NAME: ${{ inputs.traits_name }} - SUITE_NAME: ${{ inputs.test_suite_name }} - with: - script: | - const mustache = require('mustache') - const path = require('path') - const fs = require('fs') - - const { TRAITS_NAME, SUITE_NAME } = process.env - console.log(`Rendering ${TRAITS_NAME}!`) - - // https://dmitripavlutin.com/replace-all-string-occurrences-javascript/ - function replaceAll(string, search, replace) { - return string.split(search).join(replace); - } - - const template = fs.readFileSync(path.join('tests', 'traits', 'TraitsTest.cpp.mustache'), 'utf8') - const content = mustache.render(template, { - traits_name: TRAITS_NAME, - traits_dir: replaceAll(TRAITS_NAME, '_', '-'), - test_suite_name: SUITE_NAME, - }) - const outputDir = path.join('tests', 'traits') - fs.mkdirSync(outputDir, { recursive: true }) - fs.writeFileSync(path.join(outputDir, `${SUITE_NAME}.cpp`), content) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8312b8f3a..abbef77a3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -34,7 +34,7 @@ jobs: strategy: fail-fast: false matrix: - files: ["**/CMakeLists.txt", "cmake/code-coverage.cmake"] + files: ["**/CMakeLists.txt", "cmake/code-coverage.cmake", "cmake/generate-defaults-h.cmake"] steps: - uses: actions/setup-python@v5 with: @@ -60,65 +60,17 @@ jobs: with: linter_name: clang-tidy - render-defaults: + generate-defaults: runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - traits: - - { name: "boost_json", library: "Boost.JSON", url: "https://github.com/boostorg/json", disable_pico: true } - - { name: "danielaparker_jsoncons", library: "jsoncons", url: "https://github.com/danielaparker/jsoncons", disable_pico: true } - - { name: "kazuho_picojson", library: "picojson", url: "https://github.com/kazuho/picojson", disable_pico: false } - - { name: "nlohmann_json", library: "JSON for Modern C++", url: "https://github.com/nlohmann/json", disable_pico: true } - - { name: "open_source_parsers_jsoncpp", library: "jsoncpp", url: "https://github.com/open-source-parsers/jsoncpp", disable_pico: true } - - { name: "glaze_json", library: "Glaze", url: "https://github.com/stephenberry/glaze", disable_pico: true } - - { name: "reflectcpp_json", library: "ReflectCpp", url: "https://github.com/getml/reflect-cpp", disable_pico: true } - name: render-defaults (${{ matrix.traits.name }}) steps: - uses: actions/checkout@v4 - - run: | - sudo apt-get install clang-format-14 - - uses: ./.github/actions/render/defaults - id: render - with: - traits_name: ${{ matrix.traits.name }} - library_name: ${{ matrix.traits.library }} - library_url: ${{ matrix.traits.url }} - disable_default_traits: ${{ matrix.traits.disable_pico }} - - run: clang-format-14 -i ${{ steps.render.outputs.file_path }} - - run: git add ${{ steps.render.outputs.file_path }} - - uses: ./.github/actions/process-linting-results - with: - linter_name: render-defaults - - render-tests: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - matrix: - traits: - # - { name: "boost_json", suite: "BoostJsonTest" } # Currently needs work around for API limitations - - { name: "danielaparker_jsoncons", suite: "JsonconsTest" } - # - { name: "kazuho_picojson", suite: "PicoJsonTest" } # No ctor for integer type - - { name: "nlohmann_json", suite: "NlohmannTest" } - - { name: "open_source_parsers_jsoncpp", suite: "OspJsoncppTest" } - # - { name: "glaze_json", suite: "GlazeTest" } # No supported due to istream buffer being specialized - # - { name: "reflectcpp_json", suite: "ReflectCppJsonTest" } # No supported due to istream buffer being specialized - name: render-tests (${{ matrix.traits.name }}) - steps: - - uses: actions/checkout@v4 - - run: | - sudo apt-get install clang-format-14 - shopt -s globstar - - uses: ./.github/actions/render/tests - with: - traits_name: ${{ matrix.traits.name }} - test_suite_name: ${{ matrix.traits.suite }} - - run: clang-format-14 -i tests/**/*.cpp - - run: git add tests/traits/* + - run: sudo apt-get install clang-format-14 + - uses: ./.github/actions/generate-defaults-dot-h + - run: clang-format-14 -i include/jwt-cpp/traits/*/*.h + - run: git add include/jwt-cpp/traits/*/*.h - uses: ./.github/actions/process-linting-results with: - linter_name: render-tests + linter_name: generate-defaults line-ending: runs-on: ubuntu-latest diff --git a/.github/workflows/ssl.yml b/.github/workflows/ssl.yml index cc87b44ef..580e3b980 100644 --- a/.github/workflows/ssl.yml +++ b/.github/workflows/ssl.yml @@ -28,11 +28,7 @@ jobs: with: version: ${{ matrix.openssl.tag }} - - name: configure - run: cmake --preset unit-tests - - run: cmake --build --preset unit-tests - - name: test - run: ctest --preset unit-tests --output-on-failure + - run: cmake --workflow --preset unit-tests - if: github.event_name == 'push' && always() uses: ./.github/actions/badge diff --git a/CMakeLists.txt b/CMakeLists.txt index a8086ae58..5b494d4fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,9 @@ option(JWT_ENABLE_FUZZING "Enable fuzz testing" OFF) option(JWT_DISABLE_PICOJSON "Do not provide the picojson template specialiaze" OFF) option(JWT_DISABLE_BASE64 "Do not include the base64 implementation from this library" OFF) include(CMakeDependentOption) +cmake_dependent_option( + JWT_BUILD_TESTS "Configure CMake to build tests (or not)" OFF + "NOT JWT_DISABLE_BASE64 AND NOT JWT_DISABLE_PICOJSON" OFF) cmake_dependent_option( JWT_EXTERNAL_PICOJSON "Use find_package() to locate picojson, provided to integrate with package managers" OFF "NOT JWT_DISABLE_PICOJSON" OFF) diff --git a/CMakePresets.json b/CMakePresets.json index 03dc92250..acac67081 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -6,8 +6,8 @@ "patch": 0 }, "include": [ - "example/CMakePresets.json", - "tests/CMakePresets.json" + "example/CMakePresets.json", + "tests/CMakePresets.json" ], "configurePresets": [ { @@ -29,5 +29,12 @@ "configurePreset": "dev", "configuration": "Debug" } + ], + "testPresets": [ + { + "name": "dev", + "displayName": "Run all tests", + "configurePreset": "dev" + } ] } \ No newline at end of file diff --git a/cmake/generate-defaults-h.cmake b/cmake/generate-defaults-h.cmake new file mode 100644 index 000000000..ddfe11aa1 --- /dev/null +++ b/cmake/generate-defaults-h.cmake @@ -0,0 +1,54 @@ +#[[ +# This script generates a single defaults.h file from the defaults.h.in template +# It is invoked from the root directory of the project. +# +# Expected variables (set via -D command line): +# - TRAITS_NAME: name of the trait (e.g., nlohmann_json) +# - LIBRARY_NAME: name of the JSON library (e.g., JSON for Modern C++) +# - LIBRARY_URL: URL to the library +# - DISABLE_DEFAULT_TRAITS: whether to disable default picojson (true/false) +#]] + +if(NOT DEFINED TRAITS_NAME) + message(FATAL_ERROR "TRAITS_NAME must be defined") +endif() + +if(NOT DEFINED LIBRARY_NAME) + message(FATAL_ERROR "LIBRARY_NAME must be defined") +endif() + +if(NOT DEFINED LIBRARY_URL) + message(FATAL_ERROR "LIBRARY_URL must be defined") +endif() + +# Convert traits name to directory format (replace underscores with dashes) +string(REPLACE "_" "-" TRAITS_DIR_NAME "${TRAITS_NAME}") +string(TOUPPER "${TRAITS_NAME}" TRAITS_NAME_UPPER) + +set(TEMPLATE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/include/jwt-cpp/traits/defaults.h.in") +if(NOT EXISTS "${TEMPLATE_FILE}") + message(FATAL_ERROR "Wrong working directory! Template file `${TEMPLATE_FILE}` does not exist.") +endif() + +# Determine output directory +set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/jwt-cpp/traits/${TRAITS_DIR_NAME}") +set(OUTPUT_FILE "${OUTPUT_DIR}/defaults.h") + +# Ensure output directory exists +file(MAKE_DIRECTORY "${OUTPUT_DIR}") + +# Handle the conditional DISABLE_PICOJSON block +if(DISABLE_DEFAULT_TRAITS) + set(DISABLE_PICOJSON_DEFINE + " +#ifndef JWT_DISABLE_PICOJSON +#define JWT_DISABLE_PICOJSON +#endif") +else() + set(DISABLE_PICOJSON_DEFINE "") +endif() + +# Configure the file +configure_file("${TEMPLATE_FILE}" "${OUTPUT_FILE}" @ONLY) + +message(STATUS "Generated ${OUTPUT_FILE}") diff --git a/include/jwt-cpp/traits/defaults.h.mustache b/include/jwt-cpp/traits/defaults.h.in similarity index 53% rename from include/jwt-cpp/traits/defaults.h.mustache rename to include/jwt-cpp/traits/defaults.h.in index 82a67aeb7..0f5dd95ad 100644 --- a/include/jwt-cpp/traits/defaults.h.mustache +++ b/include/jwt-cpp/traits/defaults.h.in @@ -1,37 +1,32 @@ -#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}} +#ifndef JWT_CPP_@TRAITS_NAME_UPPER@_DEFAULTS_H +#define JWT_CPP_@TRAITS_NAME_UPPER@_DEFAULTS_H +@DISABLE_PICOJSON_DEFINE@ #include "traits.h" namespace jwt { /** - * \brief a class to store a generic [{{library_name}}]({{{library_url}}}) value as claim + * \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; + using claim = basic_claim; /** * Create a verifier using the default clock * \return verifier instance */ - inline verifier verify() { - return verify(default_clock{}); + inline verifier verify() { + return verify(default_clock{}); } /** * Create a builder using the default clock * \return builder instance to create a new token */ - inline builder create() { - return builder(default_clock{}); + inline builder create() { + return builder(default_clock{}); } #ifndef JWT_DISABLE_BASE64 @@ -42,8 +37,8 @@ namespace jwt { * \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); + inline decoded_jwt decode(const std::string& token) { + return decoded_jwt(token); } #endif @@ -59,8 +54,8 @@ namespace jwt { * \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); + decoded_jwt decode(const std::string& token, Decode decode) { + return decoded_jwt(token, decode); } /** @@ -69,8 +64,8 @@ namespace jwt { * \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); + inline jwk parse_jwk(const traits::@TRAITS_NAME@::string_type& token) { + return jwk(token); } /** @@ -79,15 +74,15 @@ namespace jwt { * \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); + 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; + using verify_context = verify_ops::verify_context; } // namespace jwt -#endif // JWT_CPP_{{traits_name_upper}}_DEFAULTS_H +#endif // JWT_CPP_@TRAITS_NAME_UPPER@_DEFAULTS_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 39a008467..91f21fb45 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,11 +1,3 @@ -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() - include(GoogleTest) if(HUNTER_ENABLED) hunter_add_package(GTest) diff --git a/tests/CMakePresets.json b/tests/CMakePresets.json index 36550390f..dd6f7f1ca 100644 --- a/tests/CMakePresets.json +++ b/tests/CMakePresets.json @@ -178,9 +178,31 @@ "name": "unit-tests", "description": "Run the unit tests", "configurePreset": "unit-tests", + "output": { + "outputOnFailure": true + }, "execution": { "noTestsAction": "error" } } + ], + "workflowPresets": [ + { + "name": "unit-tests", + "steps": [ + { + "type": "configure", + "name": "unit-tests" + }, + { + "type": "build", + "name": "unit-tests" + }, + { + "type": "test", + "name": "unit-tests" + } + ] + } ] } \ No newline at end of file diff --git a/tests/traits/TraitsTest.cpp.mustache b/tests/traits/TraitsTest.cpp.mustache deleted file mode 100644 index bc94fc916..000000000 --- a/tests/traits/TraitsTest.cpp.mustache +++ /dev/null @@ -1,147 +0,0 @@ -#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}}, VerifyTokenExpirationInValid) { - const auto token = jwt::create() - .set_issuer("auth0") - .set_issued_now() - .set_expires_in(std::chrono::hours{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"); - 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)); -}