10Duke Scale C++ Client
Loading...
Searching...
No Matches
OAuthPKCEFlow_test.h
1#ifndef TENDUKE_TEST_OAUTHPKCEFLOW_TEST_H
2#define TENDUKE_TEST_OAUTHPKCEFLOW_TEST_H
3
4#include "oauth/pkce/OAuthPKCEFlow.h"
5#include "utl/DefaultBase64Encoder.h"
6#include "utl/random/RandomURLSafeString.h"
7
8#include "mocks/MessageDigestMock.h"
9#include "mocks/HTTPCallMock.h"
10#include "mocks/HTTPClientMock.h"
11#include "mocks/JSONObjectMock.h"
12#include "mocks/JSONParserMock.h"
13#include "mocks/JSONNumberMock.h"
14#include "mocks/JSONStringMock.h"
15#include "mocks/ClockMock.h"
16#include "mocks/RandomBytesMock.h"
17#include "mocks/URLMock.h"
18#include "mocks/URLEncoderMock.h"
19#include "mocks/URLParserMock.h"
20#include "utils/BinaryDataUtils.h"
21
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24
25#include <cstring>
26
27namespace xdcrypto = tenduke::crypto;
28namespace xdhttp = tenduke::http;
29namespace xdnet = tenduke::net;
30namespace xdoauth = tenduke::oauth;
32namespace xdutl = tenduke::utl;
33
34namespace xdmock = tenduke::test::mocks;
35
42using tenduke::test::utils::makeFixedSizeBinaryData;
43
44
45using ::testing::_;
46using ::testing::StrEq;
47
48using ::testing::Invoke;
49using ::testing::Return;
50using ::testing::ReturnRef;
51
52namespace tenduke { namespace test { namespace oauth {
53
54void generateRandomBytes(unsigned char * buffer, std::size_t len)
55{
56 switch (len) {
57 case 16:
58 std::strcpy((char *) buffer, "simulated-state"); break;
59 case 64:
60 std::strcpy((char *) buffer, "simulated-code-generator-value-on-which-sha256-will-be-applied."); break;
61 }
62}
63
64static void fakeSha256(unsigned char * digest)
65{
66 xdmock::generateFakeSha256Hash(digest, "0123456789ABCDEF0123456789ABCDEF");
67}
68
69class OAuthPKCEFlowTest : public ::testing::Test
70{
71protected:
72 void SetUp() override
73 {
74 httpClient = std::shared_ptr<xdmock::HTTPClientMock>(new xdmock::HTTPClientMock());
75 urlParser = std::shared_ptr<xdmock::URLParserMock>(new xdmock::URLParserMock());
76 jsonParser = std::shared_ptr<xdmock::JSONParserMock>(new xdmock::JSONParserMock());
77 base64Encoder = std::shared_ptr<xdutl::Base64Encoder>(new xdutl::DefaultBase64Encoder());
78 messageDigestFactory = std::shared_ptr<xdmock::MessageDigestFactoryMock>(new xdmock::MessageDigestFactoryMock());
79 clock = std::shared_ptr<xdmock::ClockMock>(new xdmock::ClockMock());
80 randomBytes = std::shared_ptr<xdmock::RandomBytesMock>(new xdmock::RandomBytesMock());
81 urlEncoder = std::shared_ptr<xdmock::URLEncoderMock>(new xdmock::URLEncoderMock());
82
83 oauth = std::unique_ptr<xdpkce::OAuthPKCEFlow>(new xdpkce::OAuthPKCEFlow(
84 std::shared_ptr<xdoauth::OAuthConfiguration>(new xdoauth::OAuthConfiguration("/authz", "/token", "client-id", "", "/redir", tenduke::oauth::OAuthClientConfiguration::PKCE)),
85 httpClient,
86 urlParser,
87 jsonParser,
88 base64Encoder,
89 messageDigestFactory,
90 clock,
91 std::shared_ptr<tenduke::utl::random::RandomUrlSafeString>(new tenduke::utl::random::RandomUrlSafeString(randomBytes))
92 ));
93
94 EXPECT_CALL(*randomBytes, generate(_, _))
95 .WillRepeatedly(Invoke(generateRandomBytes));
96 EXPECT_CALL(*httpClient, request())
97 .WillRepeatedly(Return(xdhttp::HTTPRequestBuilder(urlEncoder, httpClient.get())));
98 EXPECT_CALL(*urlEncoder, encode(_))
99 .WillRepeatedly(::testing::ReturnArg<0>());
100 }
101
102 void stubForBuildAuthorizationUrl()
103 {
104 digest = new xdmock::MessageDigestMock();
105 EXPECT_CALL(*messageDigestFactory, create(xdcrypto::MessageDigest::SHA256))
106 .Times(1)
107 .WillOnce(Return(std::unique_ptr<xdcrypto::MessageDigest>(digest)));
108 EXPECT_CALL(*digest, update(_, _))
109 .Times(1)
110 .WillOnce(Return(digest));
111 EXPECT_CALL(*digest, digestTo(_))
112 .Times(1)
113 .WillOnce(Invoke(fakeSha256));
114 }
115
116 void stubForHandleCallback(const std::string &redirectUri)
117 {
118 url = new xdmock::URLMock();
119 EXPECT_CALL(*urlParser, from(StrEq(redirectUri)))
120 .Times(1)
121 .WillOnce(Return(std::unique_ptr<xdnet::URL>(url)));
122 }
123
124 void stubForTokenResponse()
125 {
126 auto responseBody = ::makeFixedSizeBinaryData("simulated-response-body");
127 auto tokenResponse = new ::HTTPResponse(200, {}, std::move(responseBody));
128
129 auto tokenRequestCall = new ::HTTPCallMock();
130 EXPECT_CALL(*httpClient, request()).WillRepeatedly(::Return(xdhttp::HTTPRequestBuilder(urlEncoder, httpClient.get())));
131 EXPECT_CALL(*httpClient, call(::_)).WillOnce(::Return(std::unique_ptr<::HTTPCallMock>(tokenRequestCall)));
132 EXPECT_CALL(*tokenRequestCall, execute()).WillOnce(::Return(std::unique_ptr<::HTTPResponse>(tokenResponse)));
133
134 auto json = ::JSONObjectMock::create();
135 auto accessToken = ::JSONStringMock::createShared("simulated-access-token");
136 auto refreshToken = ::JSONStringMock::createShared("simulated-refresh-token");
137 auto expiresIn = ::JSONNumberMock::createShared(42);
138 auto additionalProperty1 = ::JSONStringMock::createShared("value-1");
139 auto additionalProperty2 = ::JSONStringMock::createShared("value-2");
140 additionalTokenResponseProperties.emplace("name-1", additionalProperty1);
141 additionalTokenResponseProperties.emplace("name-2", additionalProperty2);
142
143 EXPECT_CALL(*jsonParser, from("simulated-response-body")).WillOnce(::Return(std::unique_ptr<::JSONObjectMock>(json)));
144 EXPECT_CALL(*json, removeProperty("access_token")).WillOnce(::Return(accessToken));
145 EXPECT_CALL(*json, removeProperty("refresh_token")).WillOnce(::Return(refreshToken));
146 EXPECT_CALL(*json, removeProperty("expires_in")).WillOnce(::Return(expiresIn));
147 EXPECT_CALL(*json, getProperties()).WillOnce(::ReturnRef(additionalTokenResponseProperties));
148
149 EXPECT_CALL(*clock, epochSeconds()).WillRepeatedly(::Return(100));
150 }
151
153 xdmock::URLMock *url;
154
155 std::map<std::string, std::shared_ptr<::JSONElement>> additionalTokenResponseProperties;
156 std::shared_ptr<xdmock::HTTPClientMock> httpClient;
157 std::shared_ptr<xdmock::URLParserMock> urlParser;
158 std::shared_ptr<xdmock::JSONParserMock> jsonParser;
159 std::shared_ptr<xdutl::Base64Encoder> base64Encoder;
160 std::shared_ptr<xdmock::MessageDigestFactoryMock> messageDigestFactory;
161 std::shared_ptr<xdmock::ClockMock> clock;
162 std::shared_ptr<xdmock::RandomBytesMock> randomBytes;
163 std::shared_ptr<xdmock::URLEncoderMock> urlEncoder;
164
165 std::unique_ptr<xdpkce::OAuthPKCEFlow> oauth;
166}; // OAuthPKCEFlowTest
167}}} // namespace
168
169
170#endif //TENDUKE_TEST_OAUTHPKCEFLOW_TEST_H
Builds HTTPRequest.
Definition HTTPRequestBuilder.h:22
A HTTP Response.
Definition HTTPResponse.h:15
Superclass of JSON elements.
Definition JSONElement.h:12
Container for OAuth-configuration.
Definition OAuthConfiguration.h:17
OAuth Authorization Code Grant with PKCE implementation of tenduke::oauth::OAuthClient.
Definition OAuthPKCEFlow.h:35
Definition ClockMock.h:13
Definition HTTPCallMock.h:10
Definition HTTPClientMock.h:13
Definition JSONNumberMock.h:10
Definition JSONObjectMock.h:10
Definition JSONParserMock.h:11
Definition JSONStringMock.h:10
Definition MessageDigestMock.h:23
Definition MessageDigestMock.h:13
Definition RandomBytesMock.h:11
Definition URLEncoderMock.h:13
Definition URLMock.h:11
Definition URLParserMock.h:11
Definition OAuthPKCEFlow_test.h:70
Default tenduke::utl::Base64Encoder implementation.
Definition DefaultBase64Encoder.h:13
Generates string of random URL-safe characters.
Definition RandomURLSafeString.h:17
Cryptography services.
Definition CryptoException.h:7
HTTP-related services.
Definition BadRequest.h:6
JSON support.
Definition JSONArray.h:10
Generic networking support.
Definition MalformedURLException.h:6
Implementation of OAuth "Authorization Code Flow with PKCE".
Definition OAuthPKCEFlow.h:21
OAuth services.
Definition AccessTokenRequestAuthenticator.h:8
Utilities.
Definition Base64Decoder.h:10
Root for classes, functions and globals of 10Duke C++ Client.
Definition BackendConfiguration.h:7