Skip to content

Commit 63e5a1c

Browse files
committed
Several changes:
- WViewWidget: Fixed crash due to removeFromParent on widget being destructed - add configuration parameter for the maximum size of the form-data - add logging to oauth and oidc
1 parent f36f334 commit 63e5a1c

File tree

13 files changed

+88
-13
lines changed

13 files changed

+88
-13
lines changed

examples/feature/oidc/Oidc.C

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ private:
7171

7272
int main(int argc, char** argv)
7373
{
74+
try {
7475
Wt::WServer server(argc, argv, WTHTTP_CONFIGURATION);
7576
server.readConfigurationProperty("application-url",deployUrl);
7677

@@ -112,4 +113,7 @@ int main(int argc, char** argv)
112113
Session::configureAuth();
113114

114115
server.run();
116+
} catch (Wt::WException &e) {
117+
std::cerr << "Exception: " << e.what() << std::endl;
118+
}
115119
}

src/Wt/Auth/OAuthAuthorizationEndpointProcess.C

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,23 @@ void OAuthAuthorizationEndpointProcess::processEnvironment()
5757
}
5858
client_ = db_->idpClientFindWithId(*clientId);
5959
if (!client_.checkValid()) {
60-
LOG_ERROR("Unknown or invalid client_id.");
60+
LOG_ERROR("Unknown or invalid client_id " << *clientId);
6161
return;
6262
}
6363
std::set<std::string> redirectUris = client_.redirectUris();
6464
if (redirectUris.find(redirectUri_) == redirectUris.end()) {
65-
LOG_ERROR("The client application passed an unregistered redirection URI.");
65+
LOG_ERROR("The client application passed the unregistered redirection URI " << redirectUri_);
6666
return;
6767
}
6868
const std::string *scope = env.getParameter("scope");
6969
const std::string *responseType = env.getParameter("response_type");
7070
const std::string *state = env.getParameter("state");
7171
if (!scope || !responseType || *responseType != "code") {
7272
sendResponse("error=invalid_request");
73+
LOG_INFO("error=invalid_request: "
74+
<< " scope: " << (scope ? *scope : "NULL")
75+
<< " response_type: " << (responseType ? *responseType : "NULL")
76+
);
7377
return;
7478
}
7579
validRequest_ = true;
@@ -85,6 +89,7 @@ void OAuthAuthorizationEndpointProcess::processEnvironment()
8589
return;
8690
} else if (prompt && *prompt == "none") {
8791
sendResponse("error=login_required");
92+
LOG_INFO("error=login_required but prompt == none");
8893
return;
8994
}
9095
}
@@ -97,6 +102,8 @@ void OAuthAuthorizationEndpointProcess::authorizeScope(const std::string& scope)
97102
db_->idpTokenAdd(authCodeValue, expirationTime, "authorization_code", scope,
98103
redirectUri_, login_.user(), client_);
99104
sendResponse("code=" + authCodeValue);
105+
LOG_INFO("authorization_code created for " << login_.user().id() << "(" << login_.user().email() << ")"
106+
<< ", code = " + authCodeValue);
100107
} else {
101108
throw WException("Wt::Auth::OAuthAuthorizationEndpointProcess::authorizeScope: request isn't valid");
102109
}

src/Wt/Auth/OAuthTokenEndpoint.C

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ const std::string AUTH_TYPE = "Basic";
3636
}
3737

3838
namespace Wt {
39-
namespace Auth {
4039

4140
LOGGER("OAuthTokenEndpoint");
4241

42+
namespace Auth {
43+
4344
OAuthTokenEndpoint::OAuthTokenEndpoint(AbstractUserDatabase& db,
4445
std::string issuer)
4546
: db_(&db),
@@ -115,6 +116,12 @@ void OAuthTokenEndpoint::handleRequest(const Http::Request &request, Http::Respo
115116
if (!code || clientId.empty() || clientSecret.empty() || !grantType || !redirectUri) {
116117
response.setStatus(400);
117118
response.out() << "{\"error\": \"invalid_request\"}" << std::endl;
119+
LOG_INFO("{\"error\": \"invalid_request\"}:"
120+
<< " code:" << (code ? *code : "NULL")
121+
<< " clientId: " << clientId
122+
<< " clientSecret: " << (clientSecret.empty() ? "MISSING" : "NOT MISSING")
123+
<< " grantType: " << (grantType ? *grantType : "NULL")
124+
<< " redirectUri: " << (redirectUri ? *redirectUri : "NULL"));
118125
return;
119126
}
120127
OAuthClient client = db_->idpClientFindWithId(clientId);
@@ -129,18 +136,35 @@ void OAuthTokenEndpoint::handleRequest(const Http::Request &request, Http::Respo
129136
methodToString(client.authMethod()));
130137
}
131138
response.out() << "{\n\"error\": \"invalid_client\"\n}" << std::endl;
139+
LOG_INFO("{\"error\": \"invalid_client\"}: "
140+
<< " id: " << clientId
141+
<< " client: " << (client.checkValid() ? "valid" : "not valid")
142+
<< " secret: " << (client.verifySecret(clientSecret) ? "correct" : "incorrect")
143+
<< " method: " << (client.authMethod() != authMethod ? "no match" : "match")
144+
);
132145
return;
133146
}
134147
if (*grantType != GRANT_TYPE) {
135148
response.setStatus(400);
136149
response.out() << "{\n\"error\": \"unsupported_grant_type\"\n}" << std::endl;
150+
LOG_INFO("{\"error\": \"unsupported_grant_type\"}: "
151+
<< " id: " << clientId
152+
<< " grantType: " << grantType
153+
);
137154
return;
138155
}
139156
IssuedToken authCode = db_->idpTokenFindWithValue(GRANT_TYPE, *code);
140157
if (!authCode.checkValid() || authCode.redirectUri() != *redirectUri
141158
|| WDateTime::currentDateTime() > authCode.expirationTime()) {
142159
response.setStatus(400);
143160
response.out() << "{\n\"error\": \"invalid_grant\"\n}" << std::endl;
161+
LOG_INFO("{\"error\": \"invalid_grant\"}:"
162+
<< " id: " << clientId
163+
<< " code: " << *code
164+
<< " authCode: " << (authCode.checkValid() ? "valid" : "not valid")
165+
<< " redirectUri: " << *redirectUri << (authCode.redirectUri() != *redirectUri ? " - invalid" : " - valid")
166+
<< " timestamp: " << authCode.expirationTime().toString() << (WDateTime::currentDateTime() > authCode.expirationTime() ? ", expired" : ", not expired")
167+
);
144168
return;
145169
}
146170
std::string accessTokenValue = WRandom::generateId();
@@ -178,6 +202,9 @@ void OAuthTokenEndpoint::handleRequest(const Http::Request &request, Http::Respo
178202
root["id_token"] = Json::Value(header + "." + payload + "." + signature);
179203
}
180204
response.out() << Json::serialize(root);
205+
206+
LOG_INFO("success: " << clientId << ", " << user.id() << ", " << db_->email(user));
207+
181208
#ifdef WT_TARGET_JAVA
182209
} catch (std::io_exception ioe) {
183210
LOG_ERROR(ioe.message());

src/Wt/Auth/OidcUserInfoEndpoint.C

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ const std::string AUTH_TYPE = "Bearer ";
2727
}
2828

2929
namespace Wt {
30+
31+
LOGGER("OidcUserInfoEndpoint");
32+
3033
namespace Auth {
3134

32-
LOGGER("OidcUserInfoEndpoint");
3335

3436
OidcUserInfoEndpoint::OidcUserInfoEndpoint(AbstractUserDatabase &db)
3537
: db_(&db)
@@ -54,13 +56,15 @@ void OidcUserInfoEndpoint::handleRequest(const Http::Request& request, Http::Res
5456
if (!boost::starts_with(authHeader, AUTH_TYPE)) {
5557
response.setStatus(400);
5658
response.addHeader("WWW-Authenticate", "error=\"invalid_request\"");
59+
LOG_INFO("error=\"invalid_request\": Authorization header missing");
5760
return;
5861
}
5962
std::string tokenValue = authHeader.substr(AUTH_TYPE.length());
6063
IssuedToken accessToken = db_->idpTokenFindWithValue("access_token", tokenValue);
6164
if (!accessToken.checkValid() || WDateTime::currentDateTime() > accessToken.expirationTime()) {
6265
response.setStatus(401);
6366
response.addHeader("WWW-Authenticate", "error=\"invalid_token\"");
67+
LOG_INFO("error=\"invalid_token\" " << authHeader);
6468
return;
6569
}
6670
response.setMimeType("application/json");
@@ -73,6 +77,7 @@ void OidcUserInfoEndpoint::handleRequest(const Http::Request& request, Http::Res
7377
try {
7478
#endif
7579
response.out() << Json::serialize(generateUserInfo(user, scopeSet)) << std::endl;
80+
LOG_INFO("Response sent for " << user.id() << "(" << db_->email(user) << ")");
7681
#ifdef WT_TARGET_JAVA
7782
} catch (std::io_exception ioe) {
7883
LOG_ERROR(ioe.message());

src/Wt/WViewWidget.C

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ namespace Wt {
1414
WViewWidget::WViewWidget()
1515
{ }
1616

17+
WViewWidget::~WViewWidget()
18+
{
19+
manageWidget(contents_, std::unique_ptr<WWidget>{});
20+
}
21+
1722
void WViewWidget::load()
1823
{
1924
update();

src/Wt/WViewWidget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class WT_API WViewWidget : public WWebWidget
110110
*/
111111
WViewWidget();
112112

113+
~WViewWidget();
114+
113115
/*! \brief Updates the view.
114116
*
115117
* Typically, the model will want to update the view when the model

src/web/CgiParser.C

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ void CgiParser::init()
174174
#endif
175175
}
176176

177-
CgiParser::CgiParser(::int64_t maxPostData)
178-
: maxPostData_(maxPostData)
177+
CgiParser::CgiParser(::int64_t maxRequestSize, ::int64_t maxFormData)
178+
: maxFormData_(maxFormData),
179+
maxRequestSize_(maxRequestSize)
179180
{ }
180181

181182
void CgiParser::parse(WebRequest& request, ReadOption readOption)
@@ -189,7 +190,7 @@ void CgiParser::parse(WebRequest& request, ReadOption readOption)
189190
const char *type = request.contentType();
190191
const char *meth = request.requestMethod();
191192

192-
request.postDataExceeded_ = (len > maxPostData_ ? len : 0);
193+
request.postDataExceeded_ = (len > maxRequestSize_ ? len : 0);
193194

194195
std::string queryString = request.queryString();
195196

@@ -204,7 +205,7 @@ void CgiParser::parse(WebRequest& request, ReadOption readOption)
204205
* TODO: parse this stream-based to avoid the malloc here. For now
205206
* we protect the maximum that can be POST'ed as form data.
206207
*/
207-
if (len > 5*1024*1024)
208+
if (len > maxFormData_)
208209
throw WException("Oversized application/x-www-form-urlencoded ("
209210
+ std::to_string(len) + ")");
210211

src/web/CgiParser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class CgiParser
2929

3030
static void init();
3131

32-
CgiParser(::int64_t maxPostData);
32+
CgiParser(::int64_t maxRequestSize, ::int64_t maxFormData);
3333

3434
/*
3535
* Reads in GET or POST data, converts it to unescaped text, and
@@ -43,7 +43,7 @@ class CgiParser
4343
::int64_t len);
4444
bool parseBody(WebRequest& request, const std::string boundary);
4545
bool parseHead(WebRequest& request);
46-
::int64_t maxPostData_, left_;
46+
::int64_t maxFormData_, maxRequestSize_, left_;
4747
std::ostream *spoolStream_;
4848
WebRequest *request_;
4949

src/web/Configuration.C

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ void Configuration::reset()
212212
numThreads_ = 10;
213213
maxNumSessions_ = 100;
214214
maxRequestSize_ = 128 * 1024;
215+
maxFormDataSize_ = 5 * 1024 * 1024;
215216
isapiMaxMemoryRequestSize_ = 128 * 1024;
216217
sessionTracking_ = URL;
217218
reloadIsNewSession_ = true;
@@ -285,6 +286,12 @@ int Configuration::maxNumSessions() const
285286
return maxRequestSize_;
286287
}
287288

289+
290+
::int64_t Configuration::maxFormDataSize() const
291+
{
292+
return maxFormDataSize_;
293+
}
294+
288295
::int64_t Configuration::isapiMaxMemoryRequestSize() const
289296
{
290297
READ_LOCK;
@@ -775,6 +782,11 @@ void Configuration::readApplicationSettings(xml_node<> *app)
775782
if (!maxRequestStr.empty())
776783
maxRequestSize_ = Utils::stol(maxRequestStr) * 1024;
777784

785+
std::string maxFormDataStr =
786+
singleChildElementValue(app, "max-formdata-size", "");
787+
if (!maxFormDataStr.empty())
788+
maxFormDataSize_ = Utils::stoll(maxFormDataStr) * 1024;
789+
778790
std::string debugStr = singleChildElementValue(app, "debug", "");
779791

780792
if (!debugStr.empty()) {

src/web/Configuration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ class WT_API Configuration
159159
int numThreads() const;
160160
int maxNumSessions() const;
161161
::int64_t maxRequestSize() const;
162+
::int64_t maxFormDataSize() const;
162163
::int64_t isapiMaxMemoryRequestSize() const;
163164
SessionTracking sessionTracking() const;
164165
bool reloadIsNewSession() const;
@@ -246,6 +247,7 @@ class WT_API Configuration
246247
int numThreads_;
247248
int maxNumSessions_;
248249
::int64_t maxRequestSize_;
250+
::int64_t maxFormDataSize_;
249251
::int64_t isapiMaxMemoryRequestSize_;
250252
SessionTracking sessionTracking_;
251253
bool reloadIsNewSession_;

0 commit comments

Comments
 (0)