Skip to content

Commit 18b359b

Browse files
KRJ-RTXmowijo
andauthored
Add Basic and Bearer Authorization to the CPP Pistache generator (#22337)
* [cpp][pistache-server] Add extraction and forwarding of credentials for HTTP Basic protected endpoints. * [cpp][pistache-server] Change HTTP Basic credentials to be contained on a struct instead of two std::strings * [cpp][pistache-server] Add callbacks to authenticate http basic credentials. * [cpp][pistache-server] Add `void* userdata` to HttpBasicCredentials. This allows for data ft be passed on from the authenticator to the handler implementation. For example a userid that has already been looked up * [cpp][pistache-server] Add support for HTTP Bearer authentication. * [cpp][pistache-server] Add new file `api-base-source.mustache` `api-base-source.mustache` contain implementations of security related methods and also the empty constructor. * [cpp][pistache-server] Add re-generated samples. * Fix PR 19978: Updated indentation levels and fixed test problems --------- Co-authored-by: Morten Winkler <[email protected]>
1 parent 39ea9b6 commit 18b359b

File tree

37 files changed

+2122
-864
lines changed

37 files changed

+2122
-864
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ public CppPistacheServerCodegen() {
191191
private void setupSupportingFiles() {
192192
supportingFiles.clear();
193193
supportingFiles.add(new SupportingFile("api-base-header.mustache", "api", "ApiBase.h"));
194+
supportingFiles.add(new SupportingFile("api-base-source.mustache", "api", "ApiBase.cpp"));
194195
supportingFiles.add(new SupportingFile("helpers-header.mustache", "model", modelNamePrefix + "Helpers.h"));
195196
supportingFiles.add(new SupportingFile("helpers-source.mustache", "model", modelNamePrefix + "Helpers.cpp"));
196197
supportingFiles.add(new SupportingFile("main-api-server.mustache", "", modelNamePrefix + "main-api-server.cpp"));

modules/openapi-generator/src/main/resources/cpp-pistache-server/api-base-header.mustache

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,47 @@
1414
namespace {{apiNamespace}}
1515
{
1616
17+
18+
{{#authMethods}}{{#isBasicBasic}}
19+
typedef struct
20+
{
21+
std::string user;
22+
std::string password;
23+
std::unique_ptr<void, std::function<void(void*)>> userdata;
24+
} HttpBasicCredentials;
25+
26+
typedef std::function<bool(HttpBasicCredentials &)> BasicCredentialsAuthenticator;
27+
{{/isBasicBasic}}
28+
29+
{{#isBasicBearer}}
30+
typedef struct
31+
{
32+
std::string token;
33+
std::unique_ptr<void, std::function<void(void*)>> userdata;
34+
} HttpBearerToken;
35+
36+
typedef std::function<bool(HttpBearerToken &)> BearerTokenAuthenticator;
37+
{{/isBasicBearer}}
38+
{{/authMethods}}
39+
40+
41+
1742
class ApiBase {
1843
public:
19-
explicit ApiBase(const std::shared_ptr<Pistache::Rest::Router>& rtr) : router(rtr) {};
44+
explicit ApiBase(const std::shared_ptr<Pistache::Rest::Router>& rtr);
2045
virtual ~ApiBase() = default;
2146
virtual void init() = 0;
2247
48+
{{#authMethods}}{{#isBasicBasic}}void setBasicCredentialsAuthenticator( const BasicCredentialsAuthenticator &newBasicCredentialsAuthenticator);{{/isBasicBasic}}{{/authMethods}}
49+
{{#authMethods}}{{#isBasicBearer}}void setBearerTokenAuthenticator( const BearerTokenAuthenticator &newbearerTokenAuthenticator);{{/isBasicBearer}}{{/authMethods}}
50+
51+
2352
protected:
2453
const std::shared_ptr<Pistache::Rest::Router> router;
54+
{{#authMethods}}{{#isBasicBasic}}std::optional<BasicCredentialsAuthenticator> basicCredentialsAuthenticator;{{/isBasicBasic}}{{/authMethods}}
55+
{{#authMethods}}{{#isBasicBearer}}std::optional<BearerTokenAuthenticator> bearerTokenAuthenticator;{{/isBasicBearer}}{{/authMethods}}
56+
57+
2558
};
2659

2760
} // namespace {{apiNamespace}}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{>licenseInfo}}
2+
#include "ApiBase.h"
3+
4+
namespace {{apiNamespace}}
5+
{
6+
7+
ApiBase::ApiBase(const std::shared_ptr<Pistache::Rest::Router>& rtr) : router(rtr)
8+
{
9+
}
10+
11+
{{#authMethods}}{{#isBasicBasic}}
12+
void ApiBase::setBasicCredentialsAuthenticator( const BasicCredentialsAuthenticator &newBasicCredentialsAuthenticator)
13+
{
14+
basicCredentialsAuthenticator = newBasicCredentialsAuthenticator;
15+
}
16+
{{/isBasicBasic}}
17+
{{#isBasicBearer}}
18+
void ApiBase::setBearerTokenAuthenticator( const BearerTokenAuthenticator &newbearerTokenAuthenticator)
19+
{
20+
bearerTokenAuthenticator = newbearerTokenAuthenticator;
21+
}
22+
{{/isBasicBearer}}
23+
{{/authMethods}}
24+
25+
} // Namespace {{apiNamespace}}

modules/openapi-generator/src/main/resources/cpp-pistache-server/api-header.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private:
7979
{{#allParams}}
8080
/// <param name="{{paramName}}">{{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}</param>
8181
{{/allParams}}
82-
virtual void {{operationIdSnakeCase}}({{#allParams}}const {{#isModel}}{{^isOptional}}{{modelNamespace}}::{{/isOptional}}{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
82+
virtual void {{operationIdSnakeCase}}({{#authMethods}}{{#isBasicBasic}}const HttpBasicCredentials &credentials, {{/isBasicBasic}}{{#isBasicBearer}}const HttpBearerToken &accessToken, {{/isBasicBearer}}{{/authMethods}} {{#allParams}}const {{#isModel}}{{^isOptional}}{{modelNamespace}}::{{/isOptional}}{{/isModel}}{{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) = 0;
8383
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
8484
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
8585
virtual void {{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0;

modules/openapi-generator/src/main/resources/cpp-pistache-server/api-impl-header.mustache

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ namespace {{apiNamespace}}
2626
{
2727
2828
{{#hasModelImport}}
29-
using namespace {{modelNamespace}};{{/hasModelImport}}
29+
using namespace {{modelNamespace}};
30+
{{/hasModelImport}}
3031

3132
class {{declspec}} {{classname}}Impl : public {{apiNamespace}}::{{classname}} {
3233
public:
@@ -35,7 +36,7 @@ public:
3536

3637
{{#operation}}
3738
{{#vendorExtensions.x-codegen-pistache-is-parsing-supported}}
38-
void {{operationIdSnakeCase}}({{#allParams}}const {{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response);
39+
void {{operationIdSnakeCase}}({{#authMethods}}{{#isBasicBasic}}const HttpBasicCredentials &credentials,{{/isBasicBasic}}{{#isBasicBearer}}const HttpBearerToken &bearerToken, {{/isBasicBearer}}{{/authMethods}}{{#allParams}}const {{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response);
3940
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
4041
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
4142
void {{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response);

modules/openapi-generator/src/main/resources/cpp-pistache-server/api-impl-source.mustache

Lines changed: 122 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,140 @@ namespace {{this}} {
88
{{/apiNamespaceDeclarations}}
99

1010
{{#hasModelImport}}
11-
using namespace {{modelNamespace}};{{/hasModelImport}}
11+
using namespace {{modelNamespace}};
12+
{{/hasModelImport}}
1213

1314
{{classname}}Impl::{{classname}}Impl(const std::shared_ptr<Pistache::Rest::Router>& rtr)
1415
: {{classname}}(rtr)
1516
{
17+
{{#authMethods}}{{#isBasicBasic}}/*
18+
19+
Http Basic Auth
20+
===============
21+
22+
Do this in the individual classes in the constructor
23+
24+
this->setBasicCredentialsAuthenticator(
25+
[](HttpBasicCredentials &credentials)->bool
26+
{
27+
if(credentials.user == "foo" && credentials.password == "bar")
28+
{
29+
30+
const int userIdOfFoo = 66;
31+
credentials.userdata = std::unique_ptr<void, std::function<void(void*)>> (
32+
reinterpret_cast<void*>(new int(userIdOfFoo)),
33+
[&](void* ptr)
34+
{
35+
int * value = reinterpret_cast<int*>(ptr);
36+
delete value;
37+
}
38+
);
39+
return true;
40+
}
41+
return false;
42+
}
43+
);
44+
45+
or in main:
46+
47+
for (auto api : apiImpls) {
48+
api->init();
49+
50+
api->setBasicCredentialsAuthenticator(
51+
[]( HttpBasicCredentials &credentials)->bool
52+
{
53+
if(credentials.user == "foo" && credentials.password == "bar")
54+
{
55+
56+
const int userIdOfFoo = 66;
57+
credentials.userdata = std::unique_ptr<void, std::function<void(void*)>> (
58+
reinterpret_cast<void*>(new int(userIdOfFoo)),
59+
[&](void* ptr)
60+
{
61+
int * value = reinterpret_cast<int*>(ptr);
62+
delete value;
63+
}
64+
);
65+
return true;
66+
}
67+
return false;
68+
}
69+
);
70+
}
71+
72+
or a mix.
73+
74+
Until you do either, protected resources will result in a 401.
75+
*/{{/isBasicBasic}}
76+
{{#isBasicBearer}}/*
77+
78+
Http Basic Bearer
79+
===============
80+
81+
Do this in the individual classes in the constructor
82+
83+
this->setBearerTokenAuthenticator(
84+
[](HttpBearerToken &token)->bool
85+
{
86+
if(token.token == "Zm9vYmFyCg==")
87+
{
88+
const int userIdOfFoo = 99;
89+
token.userdata = std::unique_ptr<void,std::function<void(void*)>>(
90+
reinterpret_cast<void*>(new int(userIdOfFoo)),
91+
[&](void* ptr)
92+
{
93+
int * value = reinterpret_cast<int*>(ptr);
94+
delete value;
95+
}
96+
);
97+
return true;
98+
}
99+
return false;
100+
}
101+
);
102+
103+
or in main:
104+
105+
for (auto api : apiImpls) {
106+
api->init();
107+
108+
api->setBearerTokenAuthenticator(
109+
[](HttpBearerToken &token)->bool
110+
{
111+
if(token.token == "Zm9vYmFyCg==")
112+
{
113+
const int userIdOfFoo = 99;
114+
token.userdata = std::unique_ptr<void,std::function<void(void*)>>(
115+
reinterpret_cast<void*>(new int(userIdOfFoo)),
116+
[&](void* ptr)
117+
{
118+
int * value = reinterpret_cast<int*>(ptr);
119+
delete value;
120+
}
121+
);
122+
return true;
123+
}
124+
return false;
125+
}
126+
);
127+
}
128+
129+
or a mix.
130+
131+
Until you do either, protected resources will result in a 401.
132+
*/{{/isBasicBearer}}
133+
{{/authMethods}}
134+
16135
}
17136

18137
{{#operation}}
19138
{{#vendorExtensions.x-codegen-pistache-is-parsing-supported}}
20-
void {{classname}}Impl::{{operationIdSnakeCase}}({{#allParams}}const {{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) {
139+
void {{classname}}Impl::{{operationIdSnakeCase}}({{#authMethods}}{{#isBasicBasic}}const HttpBasicCredentials &credentials, {{/isBasicBasic}}{{#isBasicBearer}}const HttpBearerToken &bearerToken, {{/isBasicBearer}}{{/authMethods}}{{#allParams}}const {{{dataType}}} &{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#hasParams}}, {{/hasParams}}Pistache::Http::ResponseWriter &response) {
21140
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
22141
}
23142
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}
24143
{{^vendorExtensions.x-codegen-pistache-is-parsing-supported}}
25-
void {{classname}}Impl::{{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response){
144+
void {{classname}}Impl::{{operationIdSnakeCase}}(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) {
26145
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
27146
}
28147
{{/vendorExtensions.x-codegen-pistache-is-parsing-supported}}

0 commit comments

Comments
 (0)