zswag 1.9.1.dev6__tar.gz → 1.9.2.dev21__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/.github/workflows/build-deploy.yml +5 -3
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/.gitignore +2 -0
- zswag-1.9.2.dev21/.gitmodules +3 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/CMakeLists.txt +9 -4
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/PKG-INFO +16 -5
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/README.md +15 -4
- zswag-1.9.2.dev21/cmake/Dependencies.cmake +121 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/include/httpcl/http-settings.hpp +11 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/src/http-settings.cpp +58 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag.egg-info/PKG-INFO +16 -5
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag.egg-info/SOURCES.txt +10 -2
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag.egg-info/requires.txt +1 -1
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/CMakeLists.txt +5 -1
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-client.hpp +2 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-config.hpp +25 -26
- zswag-1.9.2.dev21/libs/zswagcl/include/zswagcl/private/openapi-oauth.hpp +60 -0
- zswag-1.9.2.dev21/libs/zswagcl/include/zswagcl/private/openapi-security.hpp +56 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/openapi-client.cpp +6 -36
- zswag-1.9.2.dev21/libs/zswagcl/src/openapi-config.cpp +14 -0
- zswag-1.9.2.dev21/libs/zswagcl/src/openapi-oauth.cpp +190 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/openapi-parser.cpp +50 -18
- zswag-1.9.2.dev21/libs/zswagcl/src/openapi-security.cpp +147 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/CMakeLists.txt +3 -1
- zswag-1.9.2.dev21/libs/zswagcl/test/src/oauth2-integration-test.cpp +292 -0
- zswag-1.9.2.dev21/libs/zswagcl/test/src/oauth2-test.cpp +466 -0
- zswag-1.9.2.dev21/libs/zswagcl/test/testdata/oauth2-openapi.yaml +60 -0
- zswag-1.9.2.dev21/libs/zswagcl/test/testdata/oauth2-settings.yaml +25 -0
- zswag-1.9.1.dev6/cmake/Dependencies.cmake +0 -223
- zswag-1.9.1.dev6/cmake/OpenSSL.cmake +0 -172
- zswag-1.9.1.dev6/libs/zswagcl/src/openapi-config.cpp +0 -113
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/.clang-format +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/.github/pull_request_template.md +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/.github/scripts/validate_version.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/LICENSE +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/deploy.sh +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/doc/zswag-architecture.mdj +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/doc/zswag-architecture.png +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/CMakeLists.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/include/httpcl/http-client.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/include/httpcl/log.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/include/httpcl/uri.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/src/http-client.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/src/log.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/src/uri.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/test/CMakeLists.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/test/src/main.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/httpcl/test/src/uri.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/pyzswagcl/CMakeLists.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/pyzswagcl/py-openapi-client.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/pyzswagcl/py-openapi-client.h +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/pyzswagcl/py-zswagcl.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/__init__.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/app.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/doc.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/gen.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/reflect.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/.gitignore +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/CMakeLists.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/__init__.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/__init__.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/__main__.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/api.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/calculator.zs +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/client.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/calc/server.py +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/client.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_nested_service/services.zs +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_openapi_generator.bash +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_openapi_generator_1.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_openapi_generator_2.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_openapi_generator_3.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag/test/test_openapi_generator_base_config.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag.egg-info/dependency_links.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswag.egg-info/top_level.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/export.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/oaclient.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-parameter-helper.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-parser.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/base64.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/base64.hpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/oaclient.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/src/openapi-parameter-helper.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/base64.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/http-service-format.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/main.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/oaclient.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/openapi-parameter-helper.cpp +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/src/service_client_test.zs +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/testdata/auth.yaml +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/testdata/config-template.json +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/testdata/config-with-auth.json +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/test/testdata/dummy.json +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/requirements.txt +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/setup.cfg +0 -0
- {zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/setup.py +0 -0
|
@@ -48,6 +48,8 @@ jobs:
|
|
|
48
48
|
echo "Node at $(which node): $(node -v); npm: $(npm -v)"
|
|
49
49
|
- name: Checkout code
|
|
50
50
|
uses: actions/checkout@v4
|
|
51
|
+
with:
|
|
52
|
+
submodules: recursive
|
|
51
53
|
- name: Configure
|
|
52
54
|
run: |
|
|
53
55
|
python3 -m venv venv && . ./venv/bin/activate
|
|
@@ -124,8 +126,8 @@ jobs:
|
|
|
124
126
|
if: matrix.os == 'windows-latest'
|
|
125
127
|
working-directory: build
|
|
126
128
|
run: |
|
|
127
|
-
# Install NASM using chocolatey (required for OpenSSL build)
|
|
128
|
-
choco install nasm -y
|
|
129
|
+
# Install NASM and jom using chocolatey (required for OpenSSL build)
|
|
130
|
+
choco install nasm jom -y
|
|
129
131
|
# Add NASM to PATH for current session
|
|
130
132
|
$env:PATH = "$env:PATH;C:\Program Files\NASM"
|
|
131
133
|
# Verify NASM installation
|
|
@@ -155,7 +157,7 @@ jobs:
|
|
|
155
157
|
with:
|
|
156
158
|
fetch-depth: 0
|
|
157
159
|
fetch-tags: true
|
|
158
|
-
|
|
160
|
+
|
|
159
161
|
- name: Setup Python
|
|
160
162
|
uses: actions/setup-python@v5
|
|
161
163
|
with:
|
|
@@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
10
10
|
# without requiring CMakeLists.txt updates between releases.
|
|
11
11
|
# For official releases, this value should match the git tag.
|
|
12
12
|
if(NOT DEFINED ZSWAG_VERSION)
|
|
13
|
-
set(ZSWAG_VERSION 1.
|
|
13
|
+
set(ZSWAG_VERSION 1.10.0)
|
|
14
14
|
endif()
|
|
15
15
|
|
|
16
16
|
option(ZSWAG_BUILD_WHEELS "Enable zswag whl-output to WHEEL_DEPLOY_DIRECTORY." ON)
|
|
@@ -41,9 +41,14 @@ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${ZSWAG_DEPLOY_DIR}")
|
|
|
41
41
|
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${ZSWAG_DEPLOY_DIR}")
|
|
42
42
|
|
|
43
43
|
##############
|
|
44
|
-
# Dependencies via
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
# Dependencies via CPM (CMake Package Manager)
|
|
45
|
+
|
|
46
|
+
set(CPM_DOWNLOAD_ALL ON)
|
|
47
|
+
set(CPM_USE_LOCAL_PACKAGES OFF)
|
|
48
|
+
# Include CPM.cmake
|
|
49
|
+
if (NOT CPM_INITIALIZED)
|
|
50
|
+
add_subdirectory(cmake/CPM.cmake)
|
|
51
|
+
endif ()
|
|
47
52
|
include(cmake/Dependencies.cmake)
|
|
48
53
|
|
|
49
54
|
##############
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zswag
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2.dev21
|
|
4
4
|
Summary: OpenAPI service transport layer for zserio.
|
|
5
5
|
Home-page: https://github.com/klebert-engineering/zswag
|
|
6
6
|
Author: Klebert Engineering
|
|
@@ -705,11 +705,13 @@ http-settings:
|
|
|
705
705
|
basic-auth: # Basic auth credentials for matching requests.
|
|
706
706
|
user: johndoe
|
|
707
707
|
keychain: keychain-service-string
|
|
708
|
+
password: cleartext-password # alternative to keychain
|
|
708
709
|
proxy: # Proxy settings for matching requests.
|
|
709
710
|
host: localhost
|
|
710
711
|
port: 8888
|
|
711
712
|
user: test
|
|
712
713
|
keychain: ...
|
|
714
|
+
password: cleartext-password # alternative to keychain
|
|
713
715
|
cookies: # Additional Cookies for matching requests.
|
|
714
716
|
key: value
|
|
715
717
|
headers: # Additional Headers for matching requests.
|
|
@@ -717,6 +719,14 @@ http-settings:
|
|
|
717
719
|
query: # Additional Query parameters for matching requests.
|
|
718
720
|
key: value
|
|
719
721
|
api-key: value # API Key as required by OpenAPI config - see description below.
|
|
722
|
+
oauth2:
|
|
723
|
+
clientId: my-client-id # For OAuth2 client-credentials auth
|
|
724
|
+
clientSecretKeychain: keychain-service-string # Prefer a keychain entry over cleartext
|
|
725
|
+
clientSecret: cleartext-secret # discouraged, use keychain
|
|
726
|
+
tokenUrl: https://issuer.example.com/oauth/token # optional override; defaults to tokenUrl from OpenAPI
|
|
727
|
+
refreshUrl: https://issuer.example.com/oauth/token # optional override; defaults to refreshUrl from OpenAPI, then tokenUrl
|
|
728
|
+
audience: https://api.example.com/ # Optional (some providers require it)
|
|
729
|
+
scope: ["orders.read", ...] # Optional scope override; defaults to OpenAPI setting per operation
|
|
720
730
|
```
|
|
721
731
|
|
|
722
732
|
**Note:** For `proxy` configs, the credentials are optional.
|
|
@@ -965,10 +975,11 @@ constructor in C++/Python with the relevant detail.
|
|
|
965
975
|
|
|
966
976
|
#### Component Support
|
|
967
977
|
|
|
968
|
-
| Feature
|
|
969
|
-
|
|
970
|
-
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key`
|
|
971
|
-
| `
|
|
978
|
+
| Feature | C++ Client | Python Client | OAServer | zswag.gen |
|
|
979
|
+
|----------------------------------------------------------------------------------------| ---------- | ------------- | -------- | --------- |
|
|
980
|
+
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
981
|
+
| `OAuth2[clientCredentials]` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
982
|
+
| `OpenID Connect` `OAuth2[authorizationCode]` `OAuth2[implicit]` `OAuth2[password]` | ❌️ | ❌️ | ✔️(**) | ❌️ |
|
|
972
983
|
|
|
973
984
|
**(\*\*)**: The server support for all authentication schemes depends on your
|
|
974
985
|
configuration of the WSGI server (Apache/Nginx/...) which wraps the zswag Flask app.
|
|
@@ -690,11 +690,13 @@ http-settings:
|
|
|
690
690
|
basic-auth: # Basic auth credentials for matching requests.
|
|
691
691
|
user: johndoe
|
|
692
692
|
keychain: keychain-service-string
|
|
693
|
+
password: cleartext-password # alternative to keychain
|
|
693
694
|
proxy: # Proxy settings for matching requests.
|
|
694
695
|
host: localhost
|
|
695
696
|
port: 8888
|
|
696
697
|
user: test
|
|
697
698
|
keychain: ...
|
|
699
|
+
password: cleartext-password # alternative to keychain
|
|
698
700
|
cookies: # Additional Cookies for matching requests.
|
|
699
701
|
key: value
|
|
700
702
|
headers: # Additional Headers for matching requests.
|
|
@@ -702,6 +704,14 @@ http-settings:
|
|
|
702
704
|
query: # Additional Query parameters for matching requests.
|
|
703
705
|
key: value
|
|
704
706
|
api-key: value # API Key as required by OpenAPI config - see description below.
|
|
707
|
+
oauth2:
|
|
708
|
+
clientId: my-client-id # For OAuth2 client-credentials auth
|
|
709
|
+
clientSecretKeychain: keychain-service-string # Prefer a keychain entry over cleartext
|
|
710
|
+
clientSecret: cleartext-secret # discouraged, use keychain
|
|
711
|
+
tokenUrl: https://issuer.example.com/oauth/token # optional override; defaults to tokenUrl from OpenAPI
|
|
712
|
+
refreshUrl: https://issuer.example.com/oauth/token # optional override; defaults to refreshUrl from OpenAPI, then tokenUrl
|
|
713
|
+
audience: https://api.example.com/ # Optional (some providers require it)
|
|
714
|
+
scope: ["orders.read", ...] # Optional scope override; defaults to OpenAPI setting per operation
|
|
705
715
|
```
|
|
706
716
|
|
|
707
717
|
**Note:** For `proxy` configs, the credentials are optional.
|
|
@@ -950,10 +960,11 @@ constructor in C++/Python with the relevant detail.
|
|
|
950
960
|
|
|
951
961
|
#### Component Support
|
|
952
962
|
|
|
953
|
-
| Feature
|
|
954
|
-
|
|
955
|
-
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key`
|
|
956
|
-
| `
|
|
963
|
+
| Feature | C++ Client | Python Client | OAServer | zswag.gen |
|
|
964
|
+
|----------------------------------------------------------------------------------------| ---------- | ------------- | -------- | --------- |
|
|
965
|
+
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
966
|
+
| `OAuth2[clientCredentials]` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
967
|
+
| `OpenID Connect` `OAuth2[authorizationCode]` `OAuth2[implicit]` `OAuth2[password]` | ❌️ | ❌️ | ✔️(**) | ❌️ |
|
|
957
968
|
|
|
958
969
|
**(\*\*)**: The server support for all authentication schemes depends on your
|
|
959
970
|
configuration of the WSGI server (Apache/Nginx/...) which wraps the zswag Flask app.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Dependencies.cmake
|
|
2
|
+
# Centralized dependency management using CPM (CMake Package Manager)
|
|
3
|
+
# CPM provides better version management and diagnostics compared to raw FetchContent
|
|
4
|
+
|
|
5
|
+
# =============================================================================
|
|
6
|
+
# Core dependencies
|
|
7
|
+
# =============================================================================
|
|
8
|
+
|
|
9
|
+
# zlib
|
|
10
|
+
CPMAddPackage(
|
|
11
|
+
URI "gh:madler/zlib@1.3.1"
|
|
12
|
+
OPTIONS
|
|
13
|
+
"ZLIB_BUILD_EXAMPLES OFF"
|
|
14
|
+
"BUILD_TESTING OFF")
|
|
15
|
+
if(zlib_ADDED)
|
|
16
|
+
set_target_properties(zlib PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
17
|
+
set_target_properties(zlibstatic PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
18
|
+
# Create ZLIB::ZLIB alias if it doesn't exist
|
|
19
|
+
if(NOT TARGET ZLIB::ZLIB)
|
|
20
|
+
if(TARGET zlib)
|
|
21
|
+
add_library(ZLIB::ZLIB ALIAS zlib)
|
|
22
|
+
elseif(TARGET zlibstatic)
|
|
23
|
+
add_library(ZLIB::ZLIB ALIAS zlibstatic)
|
|
24
|
+
endif()
|
|
25
|
+
endif()
|
|
26
|
+
endif()
|
|
27
|
+
|
|
28
|
+
# fmt
|
|
29
|
+
CPMAddPackage(
|
|
30
|
+
URI "gh:fmtlib/fmt#11.1.3"
|
|
31
|
+
OPTIONS "FMT_HEADER_ONLY OFF"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# spdlog
|
|
35
|
+
CPMAddPackage(
|
|
36
|
+
URI "gh:gabime/spdlog@1.15.3"
|
|
37
|
+
OPTIONS
|
|
38
|
+
"SPDLOG_BUILD_TESTS OFF"
|
|
39
|
+
"SPDLOG_BUILD_EXAMPLE OFF"
|
|
40
|
+
"SPDLOG_FMT_EXTERNAL ON"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# yaml-cpp
|
|
44
|
+
CPMAddPackage(
|
|
45
|
+
URI "gh:jbeder/yaml-cpp#aa8d4e4750ec9fe9f8cc680eb90f1b15955c817e"
|
|
46
|
+
OPTIONS
|
|
47
|
+
"YAML_CPP_BUILD_TESTS OFF"
|
|
48
|
+
"YAML_CPP_BUILD_TOOLS OFF"
|
|
49
|
+
"YAML_CPP_BUILD_CONTRIB OFF"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# stx
|
|
53
|
+
CPMAddPackage("gh:Klebert-Engineering/stx@1.0.0")
|
|
54
|
+
|
|
55
|
+
# httplib
|
|
56
|
+
CPMAddPackage(
|
|
57
|
+
URI "gh:yhirose/cpp-httplib@0.15.3"
|
|
58
|
+
OPTIONS
|
|
59
|
+
"HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN OFF"
|
|
60
|
+
"HTTPLIB_INSTALL OFF"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# OpenSSL
|
|
64
|
+
set (OPENSSL_VERSION openssl-3.5.2)
|
|
65
|
+
CPMAddPackage("gh:klebert-engineering/openssl-cmake@1.0.0")
|
|
66
|
+
|
|
67
|
+
# pybind11 (only needed when building wheels)
|
|
68
|
+
if(ZSWAG_BUILD_WHEELS)
|
|
69
|
+
CPMAddPackage("gh:pybind/pybind11@2.13.6")
|
|
70
|
+
endif()
|
|
71
|
+
|
|
72
|
+
# python-cmake-wheel (only needed when building wheels)
|
|
73
|
+
if(ZSWAG_BUILD_WHEELS)
|
|
74
|
+
CPMAddPackage("gh:Klebert-Engineering/python-cmake-wheel@1.0.1")
|
|
75
|
+
endif()
|
|
76
|
+
|
|
77
|
+
# keychain
|
|
78
|
+
if(ZSWAG_KEYCHAIN_SUPPORT)
|
|
79
|
+
CPMAddPackage("gh:hrantzsch/keychain@1.3.1")
|
|
80
|
+
endif()
|
|
81
|
+
|
|
82
|
+
# Catch2 (for testing)
|
|
83
|
+
if(ZSWAG_ENABLE_TESTING)
|
|
84
|
+
CPMAddPackage(
|
|
85
|
+
URI "gh:catchorg/Catch2@3.8.1"
|
|
86
|
+
OPTIONS
|
|
87
|
+
"CATCH_INSTALL_DOCS OFF"
|
|
88
|
+
"CATCH_INSTALL_EXTRAS OFF"
|
|
89
|
+
)
|
|
90
|
+
endif()
|
|
91
|
+
|
|
92
|
+
# zserio-cmake-helper
|
|
93
|
+
set(ZSERIO_VERSION "2.16.1")
|
|
94
|
+
CPMAddPackage("gh:Klebert-Engineering/zserio-cmake-helper@1.1.4")
|
|
95
|
+
# Add zserio C++ runtime target
|
|
96
|
+
if(NOT TARGET ZserioCppRuntime)
|
|
97
|
+
add_zserio_cpp_runtime()
|
|
98
|
+
endif()
|
|
99
|
+
|
|
100
|
+
# =============================================================================
|
|
101
|
+
# Configure httplib with OpenSSL and zlib support
|
|
102
|
+
# =============================================================================
|
|
103
|
+
|
|
104
|
+
if (TARGET httplib)
|
|
105
|
+
target_compile_definitions(httplib INTERFACE CPPHTTPLIB_OPENSSL_SUPPORT)
|
|
106
|
+
target_link_libraries(httplib INTERFACE OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB)
|
|
107
|
+
endif()
|
|
108
|
+
|
|
109
|
+
# =============================================================================
|
|
110
|
+
# Configure python-cmake-wheel integration
|
|
111
|
+
# =============================================================================
|
|
112
|
+
|
|
113
|
+
if(ZSWAG_BUILD_WHEELS AND python-cmake-wheel_ADDED)
|
|
114
|
+
set(CMAKE_MODULE_PATH "${python-cmake-wheel_SOURCE_DIR}" ${CMAKE_MODULE_PATH})
|
|
115
|
+
|
|
116
|
+
if(NOT TARGET wheel)
|
|
117
|
+
set(Python3_FIND_STRATEGY LOCATION)
|
|
118
|
+
include(python-wheel)
|
|
119
|
+
set(WHEEL_DEPLOY_DIRECTORY "${ZSWAG_DEPLOY_DIR}/wheel")
|
|
120
|
+
endif()
|
|
121
|
+
endif()
|
|
@@ -46,6 +46,16 @@ struct Config
|
|
|
46
46
|
std::string keychain;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
struct OAuth2 {
|
|
50
|
+
std::string clientId;
|
|
51
|
+
std::string clientSecret;
|
|
52
|
+
std::string clientSecretKeychain;
|
|
53
|
+
std::string tokenUrlOverride; // optional
|
|
54
|
+
std::string refreshUrlOverride; // optional
|
|
55
|
+
std::string audience; // optional
|
|
56
|
+
std::vector<std::string> scopesOverride; // optional
|
|
57
|
+
};
|
|
58
|
+
|
|
49
59
|
std::optional<std::string> scope;
|
|
50
60
|
std::regex urlPattern;
|
|
51
61
|
std::string urlPatternString;
|
|
@@ -53,6 +63,7 @@ struct Config
|
|
|
53
63
|
std::map<std::string, std::string> cookies;
|
|
54
64
|
std::optional<BasicAuthentication> auth;
|
|
55
65
|
std::optional<Proxy> proxy;
|
|
66
|
+
std::optional<OAuth2> oauth2;
|
|
56
67
|
std::optional<std::string> apiKey;
|
|
57
68
|
Headers headers;
|
|
58
69
|
Query query;
|
|
@@ -180,6 +180,25 @@ YAML::Node configToNode(Config const& config) {
|
|
|
180
180
|
if (config.apiKey)
|
|
181
181
|
result["api-key"] = *config.apiKey;
|
|
182
182
|
|
|
183
|
+
if (config.oauth2) {
|
|
184
|
+
YAML::Node oauth2Node;
|
|
185
|
+
if (!config.oauth2->clientId.empty())
|
|
186
|
+
oauth2Node["clientId"] = config.oauth2->clientId;
|
|
187
|
+
if (!config.oauth2->clientSecret.empty())
|
|
188
|
+
oauth2Node["clientSecret"] = config.oauth2->clientSecret;
|
|
189
|
+
if (!config.oauth2->clientSecretKeychain.empty())
|
|
190
|
+
oauth2Node["clientSecretKeychain"] = config.oauth2->clientSecretKeychain;
|
|
191
|
+
if (!config.oauth2->tokenUrlOverride.empty())
|
|
192
|
+
oauth2Node["tokenUrl"] = config.oauth2->tokenUrlOverride;
|
|
193
|
+
if (!config.oauth2->refreshUrlOverride.empty())
|
|
194
|
+
oauth2Node["refreshUrl"] = config.oauth2->refreshUrlOverride;
|
|
195
|
+
if (!config.oauth2->audience.empty())
|
|
196
|
+
oauth2Node["audience"] = config.oauth2->audience;
|
|
197
|
+
if (!config.oauth2->scopesOverride.empty())
|
|
198
|
+
oauth2Node["scopes"] = config.oauth2->scopesOverride;
|
|
199
|
+
result["oauth2"] = oauth2Node;
|
|
200
|
+
}
|
|
201
|
+
|
|
183
202
|
return result;
|
|
184
203
|
}
|
|
185
204
|
|
|
@@ -221,6 +240,27 @@ Config configFromNode(YAML::Node const& node)
|
|
|
221
240
|
if (auto apiKey = node["api-key"])
|
|
222
241
|
conf.apiKey = apiKey.as<std::string>();
|
|
223
242
|
|
|
243
|
+
if (auto oauth2Node = node["oauth2"]) {
|
|
244
|
+
Config::OAuth2 oauth2;
|
|
245
|
+
if (auto v = oauth2Node["clientId"])
|
|
246
|
+
oauth2.clientId = v.as<std::string>();
|
|
247
|
+
if (auto v = oauth2Node["clientSecret"])
|
|
248
|
+
oauth2.clientSecret = v.as<std::string>();
|
|
249
|
+
if (auto v = oauth2Node["clientSecretKeychain"])
|
|
250
|
+
oauth2.clientSecretKeychain = v.as<std::string>();
|
|
251
|
+
if (auto v = oauth2Node["tokenUrl"])
|
|
252
|
+
oauth2.tokenUrlOverride = v.as<std::string>();
|
|
253
|
+
if (auto v = oauth2Node["refreshUrl"])
|
|
254
|
+
oauth2.refreshUrlOverride = v.as<std::string>();
|
|
255
|
+
if (auto v = oauth2Node["audience"])
|
|
256
|
+
oauth2.audience = v.as<std::string>();
|
|
257
|
+
if (auto v = oauth2Node["scope"]) {
|
|
258
|
+
for (auto const& scope : v)
|
|
259
|
+
oauth2.scopesOverride.emplace_back(scope.as<std::string>());
|
|
260
|
+
}
|
|
261
|
+
conf.oauth2 = oauth2;
|
|
262
|
+
}
|
|
263
|
+
|
|
224
264
|
return conf;
|
|
225
265
|
}
|
|
226
266
|
}
|
|
@@ -520,5 +560,23 @@ Config& Config::operator |= (Config const& other) {
|
|
|
520
560
|
proxy = other.proxy;
|
|
521
561
|
if (other.apiKey)
|
|
522
562
|
apiKey = other.apiKey;
|
|
563
|
+
if (other.oauth2) {
|
|
564
|
+
if (!oauth2)
|
|
565
|
+
oauth2.emplace();
|
|
566
|
+
if (!other.oauth2->clientId.empty())
|
|
567
|
+
oauth2->clientId = other.oauth2->clientId;
|
|
568
|
+
if (!other.oauth2->clientSecretKeychain.empty())
|
|
569
|
+
oauth2->clientSecretKeychain = other.oauth2->clientSecretKeychain;
|
|
570
|
+
if (!other.oauth2->clientSecret.empty())
|
|
571
|
+
oauth2->clientSecret = other.oauth2->clientSecret;
|
|
572
|
+
if (!other.oauth2->tokenUrlOverride.empty())
|
|
573
|
+
oauth2->tokenUrlOverride = other.oauth2->tokenUrlOverride;
|
|
574
|
+
if (!other.oauth2->refreshUrlOverride.empty())
|
|
575
|
+
oauth2->refreshUrlOverride = other.oauth2->refreshUrlOverride;
|
|
576
|
+
if (!other.oauth2->audience.empty())
|
|
577
|
+
oauth2->audience = other.oauth2->audience;
|
|
578
|
+
if (!other.oauth2->scopesOverride.empty())
|
|
579
|
+
oauth2->scopesOverride = other.oauth2->scopesOverride;
|
|
580
|
+
}
|
|
523
581
|
return *this;
|
|
524
582
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zswag
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2.dev21
|
|
4
4
|
Summary: OpenAPI service transport layer for zserio.
|
|
5
5
|
Home-page: https://github.com/klebert-engineering/zswag
|
|
6
6
|
Author: Klebert Engineering
|
|
@@ -705,11 +705,13 @@ http-settings:
|
|
|
705
705
|
basic-auth: # Basic auth credentials for matching requests.
|
|
706
706
|
user: johndoe
|
|
707
707
|
keychain: keychain-service-string
|
|
708
|
+
password: cleartext-password # alternative to keychain
|
|
708
709
|
proxy: # Proxy settings for matching requests.
|
|
709
710
|
host: localhost
|
|
710
711
|
port: 8888
|
|
711
712
|
user: test
|
|
712
713
|
keychain: ...
|
|
714
|
+
password: cleartext-password # alternative to keychain
|
|
713
715
|
cookies: # Additional Cookies for matching requests.
|
|
714
716
|
key: value
|
|
715
717
|
headers: # Additional Headers for matching requests.
|
|
@@ -717,6 +719,14 @@ http-settings:
|
|
|
717
719
|
query: # Additional Query parameters for matching requests.
|
|
718
720
|
key: value
|
|
719
721
|
api-key: value # API Key as required by OpenAPI config - see description below.
|
|
722
|
+
oauth2:
|
|
723
|
+
clientId: my-client-id # For OAuth2 client-credentials auth
|
|
724
|
+
clientSecretKeychain: keychain-service-string # Prefer a keychain entry over cleartext
|
|
725
|
+
clientSecret: cleartext-secret # discouraged, use keychain
|
|
726
|
+
tokenUrl: https://issuer.example.com/oauth/token # optional override; defaults to tokenUrl from OpenAPI
|
|
727
|
+
refreshUrl: https://issuer.example.com/oauth/token # optional override; defaults to refreshUrl from OpenAPI, then tokenUrl
|
|
728
|
+
audience: https://api.example.com/ # Optional (some providers require it)
|
|
729
|
+
scope: ["orders.read", ...] # Optional scope override; defaults to OpenAPI setting per operation
|
|
720
730
|
```
|
|
721
731
|
|
|
722
732
|
**Note:** For `proxy` configs, the credentials are optional.
|
|
@@ -965,10 +975,11 @@ constructor in C++/Python with the relevant detail.
|
|
|
965
975
|
|
|
966
976
|
#### Component Support
|
|
967
977
|
|
|
968
|
-
| Feature
|
|
969
|
-
|
|
970
|
-
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key`
|
|
971
|
-
| `
|
|
978
|
+
| Feature | C++ Client | Python Client | OAServer | zswag.gen |
|
|
979
|
+
|----------------------------------------------------------------------------------------| ---------- | ------------- | -------- | --------- |
|
|
980
|
+
| `HTTP Basic-Auth` `HTTP Bearer-Auth` `Cookie API-Key` `Header API-Key` `Query API-Key` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
981
|
+
| `OAuth2[clientCredentials]` | ✔️ | ✔️ | ✔️(**) | ✔️ |
|
|
982
|
+
| `OpenID Connect` `OAuth2[authorizationCode]` `OAuth2[implicit]` `OAuth2[password]` | ❌️ | ❌️ | ✔️(**) | ❌️ |
|
|
972
983
|
|
|
973
984
|
**(\*\*)**: The server support for all authentication schemes depends on your
|
|
974
985
|
configuration of the WSGI server (Apache/Nginx/...) which wraps the zswag Flask app.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.clang-format
|
|
2
2
|
.gitignore
|
|
3
|
+
.gitmodules
|
|
3
4
|
CMakeLists.txt
|
|
4
5
|
LICENSE
|
|
5
6
|
README.md
|
|
@@ -10,7 +11,6 @@ setup.py
|
|
|
10
11
|
.github/scripts/validate_version.py
|
|
11
12
|
.github/workflows/build-deploy.yml
|
|
12
13
|
cmake/Dependencies.cmake
|
|
13
|
-
cmake/OpenSSL.cmake
|
|
14
14
|
doc/zswag-architecture.mdj
|
|
15
15
|
doc/zswag-architecture.png
|
|
16
16
|
libs/httpcl/CMakeLists.txt
|
|
@@ -60,23 +60,31 @@ libs/zswagcl/include/zswagcl/export.hpp
|
|
|
60
60
|
libs/zswagcl/include/zswagcl/oaclient.hpp
|
|
61
61
|
libs/zswagcl/include/zswagcl/private/openapi-client.hpp
|
|
62
62
|
libs/zswagcl/include/zswagcl/private/openapi-config.hpp
|
|
63
|
+
libs/zswagcl/include/zswagcl/private/openapi-oauth.hpp
|
|
63
64
|
libs/zswagcl/include/zswagcl/private/openapi-parameter-helper.hpp
|
|
64
65
|
libs/zswagcl/include/zswagcl/private/openapi-parser.hpp
|
|
66
|
+
libs/zswagcl/include/zswagcl/private/openapi-security.hpp
|
|
65
67
|
libs/zswagcl/src/base64.cpp
|
|
66
68
|
libs/zswagcl/src/base64.hpp
|
|
67
69
|
libs/zswagcl/src/oaclient.cpp
|
|
68
70
|
libs/zswagcl/src/openapi-client.cpp
|
|
69
71
|
libs/zswagcl/src/openapi-config.cpp
|
|
72
|
+
libs/zswagcl/src/openapi-oauth.cpp
|
|
70
73
|
libs/zswagcl/src/openapi-parameter-helper.cpp
|
|
71
74
|
libs/zswagcl/src/openapi-parser.cpp
|
|
75
|
+
libs/zswagcl/src/openapi-security.cpp
|
|
72
76
|
libs/zswagcl/test/CMakeLists.txt
|
|
73
77
|
libs/zswagcl/test/src/base64.cpp
|
|
74
78
|
libs/zswagcl/test/src/http-service-format.cpp
|
|
75
79
|
libs/zswagcl/test/src/main.cpp
|
|
76
80
|
libs/zswagcl/test/src/oaclient.cpp
|
|
81
|
+
libs/zswagcl/test/src/oauth2-integration-test.cpp
|
|
82
|
+
libs/zswagcl/test/src/oauth2-test.cpp
|
|
77
83
|
libs/zswagcl/test/src/openapi-parameter-helper.cpp
|
|
78
84
|
libs/zswagcl/test/src/service_client_test.zs
|
|
79
85
|
libs/zswagcl/test/testdata/auth.yaml
|
|
80
86
|
libs/zswagcl/test/testdata/config-template.json
|
|
81
87
|
libs/zswagcl/test/testdata/config-with-auth.json
|
|
82
|
-
libs/zswagcl/test/testdata/dummy.json
|
|
88
|
+
libs/zswagcl/test/testdata/dummy.json
|
|
89
|
+
libs/zswagcl/test/testdata/oauth2-openapi.yaml
|
|
90
|
+
libs/zswagcl/test/testdata/oauth2-settings.yaml
|
|
@@ -10,13 +10,17 @@ add_library(zswagcl SHARED
|
|
|
10
10
|
include/zswagcl/private/openapi-parameter-helper.hpp
|
|
11
11
|
include/zswagcl/private/openapi-parser.hpp
|
|
12
12
|
include/zswagcl/oaclient.hpp
|
|
13
|
+
include/zswagcl/private/openapi-security.hpp
|
|
14
|
+
include/zswagcl/private/openapi-oauth.hpp
|
|
13
15
|
|
|
14
16
|
src/base64.cpp
|
|
15
17
|
src/openapi-client.cpp
|
|
16
18
|
src/openapi-config.cpp
|
|
17
19
|
src/openapi-parameter-helper.cpp
|
|
18
20
|
src/openapi-parser.cpp
|
|
19
|
-
src/
|
|
21
|
+
src/openapi-security.cpp
|
|
22
|
+
src/oaclient.cpp
|
|
23
|
+
src/openapi-oauth.cpp)
|
|
20
24
|
|
|
21
25
|
target_link_libraries(zswagcl
|
|
22
26
|
PUBLIC
|
{zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-client.hpp
RENAMED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "openapi-parser.hpp"
|
|
6
6
|
#include "openapi-config.hpp"
|
|
7
7
|
#include "openapi-parameter-helper.hpp"
|
|
8
|
+
#include "openapi-security.hpp"
|
|
8
9
|
|
|
9
10
|
#include "httpcl/uri.hpp"
|
|
10
11
|
#include "httpcl/http-client.hpp"
|
|
@@ -17,6 +18,7 @@ class OpenAPIClient
|
|
|
17
18
|
public:
|
|
18
19
|
OpenAPIConfig config_;
|
|
19
20
|
httpcl::Config httpConfig_;
|
|
21
|
+
AuthRegistry authHandlers_;
|
|
20
22
|
|
|
21
23
|
OpenAPIClient(OpenAPIConfig config,
|
|
22
24
|
httpcl::Config httpConfig,
|
{zswag-1.9.1.dev6 → zswag-1.9.2.dev21}/libs/zswagcl/include/zswagcl/private/openapi-config.hpp
RENAMED
|
@@ -21,46 +21,45 @@ struct OpenAPIConfig
|
|
|
21
21
|
Header
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
enum class SecuritySchemeType {
|
|
25
|
+
HttpBasic,
|
|
26
|
+
HttpBearer,
|
|
27
|
+
ApiKeyQuery,
|
|
28
|
+
ApiKeyHeader,
|
|
29
|
+
ApiKeyCookie,
|
|
30
|
+
OAuth2ClientCredentials
|
|
29
31
|
};
|
|
30
32
|
|
|
33
|
+
struct SecurityScheme
|
|
34
|
+
{
|
|
35
|
+
SecuritySchemeType type;
|
|
36
|
+
std::string oauthTokenUrl; // For oauth2
|
|
37
|
+
std::string oauthRefreshUrl; // For oauth2
|
|
38
|
+
std::map<std::string, std::string> oauthScopes; // Scope -> Description
|
|
39
|
+
std::string apiKeyName; // Header/Query/Cookie name
|
|
40
|
+
std::string id; // Scheme name for introspection/debugging
|
|
41
|
+
};
|
|
31
42
|
using SecuritySchemePtr = std::shared_ptr<SecurityScheme>;
|
|
32
43
|
|
|
33
44
|
/**
|
|
34
|
-
* Security Scheme References
|
|
45
|
+
* Security Scheme References by operations.
|
|
35
46
|
*
|
|
36
47
|
* Disjunctive normal form ([A [AND B]+][ OR C [AND D]+]+) of required
|
|
37
48
|
* security schemes. An empty vector is used to encode that no auth
|
|
38
49
|
* scheme is required.
|
|
39
50
|
*/
|
|
40
|
-
|
|
51
|
+
struct SecurityRequirement
|
|
52
|
+
{
|
|
53
|
+
SecuritySchemePtr scheme;
|
|
54
|
+
// For each operation, a subset of scopes may be defined which are required for it.
|
|
55
|
+
std::vector<std::string> scopes;
|
|
56
|
+
};
|
|
57
|
+
using SecurityAlternative = std::vector<SecurityRequirement>;
|
|
58
|
+
using SecurityAlternatives = std::vector<SecurityAlternative>;
|
|
41
59
|
|
|
42
60
|
/**
|
|
43
61
|
* Supported Authentication Schemes
|
|
44
62
|
*/
|
|
45
|
-
struct BasicAuth : public SecurityScheme {
|
|
46
|
-
explicit BasicAuth(std::string id);
|
|
47
|
-
bool checkOrApply(httpcl::Config& config, std::string& err) const override;
|
|
48
|
-
};
|
|
49
|
-
struct BearerAuth : public SecurityScheme {
|
|
50
|
-
explicit BearerAuth(std::string id);
|
|
51
|
-
bool checkOrApply(httpcl::Config& config, std::string& err) const override;
|
|
52
|
-
};
|
|
53
|
-
struct APIKeyAuth : public SecurityScheme {
|
|
54
|
-
explicit APIKeyAuth(std::string id, ParameterLocation location, std::string keyName);
|
|
55
|
-
bool checkOrApply(httpcl::Config& config, std::string& err) const override;
|
|
56
|
-
ParameterLocation location = ParameterLocation::Header;
|
|
57
|
-
std::string keyName;
|
|
58
|
-
};
|
|
59
|
-
struct CookieAuth : public SecurityScheme {
|
|
60
|
-
explicit CookieAuth(std::string id, std::string cookieName);
|
|
61
|
-
bool checkOrApply(httpcl::Config& config, std::string& err) const override;
|
|
62
|
-
std::string cookieName;
|
|
63
|
-
};
|
|
64
63
|
|
|
65
64
|
struct Parameter {
|
|
66
65
|
ParameterLocation location = ParameterLocation::Query;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "openapi-security.hpp"
|
|
4
|
+
|
|
5
|
+
namespace zswagcl
|
|
6
|
+
{
|
|
7
|
+
|
|
8
|
+
class OAuth2ClientCredentialsHandler final : public ISecurityHandler
|
|
9
|
+
{
|
|
10
|
+
public:
|
|
11
|
+
bool satisfy(
|
|
12
|
+
const OpenAPIConfig::SecurityRequirement& req,
|
|
13
|
+
AuthContext const& ctx,
|
|
14
|
+
std::string& mismatchReason) override;
|
|
15
|
+
|
|
16
|
+
private:
|
|
17
|
+
// OAuth2 grant type constants
|
|
18
|
+
static constexpr const char* GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials";
|
|
19
|
+
static constexpr const char* GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
|
|
20
|
+
|
|
21
|
+
struct TokenKey
|
|
22
|
+
{
|
|
23
|
+
std::string tokenUrl, clientId, audience, scopeKey;
|
|
24
|
+
bool operator==(const TokenKey& o) const
|
|
25
|
+
{
|
|
26
|
+
return tokenUrl == o.tokenUrl && clientId == o.clientId && audience == o.audience &&
|
|
27
|
+
scopeKey == o.scopeKey;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
struct TokenKeyHash
|
|
32
|
+
{
|
|
33
|
+
size_t operator()(const TokenKey& k) const
|
|
34
|
+
{
|
|
35
|
+
std::hash<std::string> H;
|
|
36
|
+
return H(k.tokenUrl) ^ H(k.clientId) ^ H(k.audience) ^ H(k.scopeKey);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
struct MintedToken
|
|
41
|
+
{
|
|
42
|
+
std::string accessToken;
|
|
43
|
+
std::string refreshToken; // may be empty (most CC flows don’t return one)
|
|
44
|
+
std::chrono::steady_clock::time_point expiresAt;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
std::shared_mutex m_;
|
|
48
|
+
std::unordered_map<TokenKey, MintedToken, TokenKeyHash> cache_;
|
|
49
|
+
|
|
50
|
+
// Method for both token fetch and refresh requests
|
|
51
|
+
MintedToken requestToken(
|
|
52
|
+
AuthContext const& httpCtx,
|
|
53
|
+
const httpcl::Config::OAuth2& oauthConfig,
|
|
54
|
+
const std::string& resolvedTokenUrl,
|
|
55
|
+
const std::string& grantType,
|
|
56
|
+
const std::vector<std::string>& resolvedScopes = {},
|
|
57
|
+
const std::string& refreshToken = "");
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
} // namespace zswagcl
|