blob: 3dd5fa3da60fbf951d562231cd583c7b30749a37 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef OAUTHTESTUTILS_H
#define OAUTHTESTUTILS_H
#include "tlswebserver.h"
#include "webserver.h"
#include <QtNetworkAuth/qoauthglobal.h>
#ifndef QT_NO_SSL
#include <QtNetwork/qsslconfiguration.h>
#endif
#include <QtNetwork/qtcpsocket.h>
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qstring.h>
#include <QtCore/qtenvironmentvariables.h>
#include <memory>
[[nodiscard]] inline auto useTemporaryKeychain()
{
#ifndef QT_NO_SSL
// Set the same environment value as CI uses, so that it's possible
// to run autotests locally without macOS asking for permission to use
// a private key in keychain (with TLS sockets)
auto value = qEnvironmentVariable("QT_SSL_USE_TEMPORARY_KEYCHAIN");
qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", "1");
auto envRollback = qScopeGuard([value](){
if (value.isEmpty())
qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
else
qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", value.toUtf8());
});
return envRollback;
#else
// avoid maybe-unused warnings from callers
return qScopeGuard([]{});
#endif // QT_NO_SSL
}
QString createSignedJWT(const QVariantMap &header = {}, const QVariantMap &payload = {});
#ifndef QT_NO_SSL
QSslConfiguration createSslConfiguration(const QString &keyFileName,
const QString &certificateFileName);
#endif // QT_NO_SSL
struct ServerResponses
{
QByteArray authBody;
QByteArray authHttpStatus;
QByteArray tokenBody;
QByteArray tokenHttpStatus;
};
template<typename ServerType>
struct TestAuthorizationServer
{
std::unique_ptr<ServerType> server;
QList<WebServer::HttpRequest> receivedAuthorizationRequests;
QList<WebServer::HttpRequest> receivedTokenRequests;
ServerResponses responses;
QUrl authorizationEndpoint()
{
Q_ASSERT(server);
return server->url(QStringLiteral("authorizationEndpoint"));
}
QUrl tokenEndpoint()
{
Q_ASSERT(server);
return server->url(QStringLiteral("tokenEndpoint"));
}
};
// Creates a local http authorization server.
// The provided ServerResponses are used as the initial values. The testcase
// can modify individual response members during the testcase by modifying the returned
// instance's TestAuthorizationServer::responses contents.
// The template is used so that the function can return either WebServer* or TlsWebServer*
template<typename ServerType, typename... Args>
std::unique_ptr<TestAuthorizationServer<ServerType>> createAuthorizationServer(
ServerResponses responses, Args&&... args)
{
auto result = std::make_unique<TestAuthorizationServer<ServerType>>();
result->responses = std::move(responses);
auto handler = [raw = result.get()]
(const WebServer::HttpRequest &request, QTcpSocket *socket) {
QByteArray replyMessage;
if (request.url.path() == QLatin1StringView("/authorizationEndpoint")) {
// Set received request for test cases to check
raw->receivedAuthorizationRequests.append(request);
replyMessage =
"HTTP/1.0 " + raw->responses.authHttpStatus + "\r\n"
"Content-Type: application/json; charset=\"utf-8\"\r\n"
"Content-Length: " + QByteArray::number(raw->responses.authBody.size())
+ "\r\n\r\n" + raw->responses.authBody;
} else if (request.url.path() == QLatin1StringView("/tokenEndpoint")) {
// Set received request for test cases to check
raw->receivedTokenRequests.append(request);
replyMessage =
"HTTP/1.0 " + raw->responses.tokenHttpStatus + "\r\n"
"Content-Type: application/json; charset=\"utf-8\"\r\n"
"Content-Length: " + QByteArray::number(raw->responses.tokenBody.size())
+ "\r\n\r\n" + raw->responses.tokenBody;
} else {
qFatal() << "Unsupported URL:" << request.url;
}
socket->write(replyMessage);
};
result->server.reset(new ServerType(handler, std::forward<Args>(args)...));
return result;
}
#endif // OAUTHTESTUTILS_H
|