1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // A set of unit tests for TokenValidatorFactoryImpl
6
7 #include "remoting/host/token_validator_factory_impl.h"
8
9 #include <memory>
10 #include <string>
11
12 #include "base/bind.h"
13 #include "base/json/json_writer.h"
14 #include "base/run_loop.h"
15 #include "base/test/task_environment.h"
16 #include "base/values.h"
17 #include "net/base/net_errors.h"
18 #include "net/http/http_status_code.h"
19 #include "net/test/url_request/url_request_failed_job.h"
20 #include "net/url_request/url_request_filter.h"
21 #include "net/url_request/url_request_interceptor.h"
22 #include "net/url_request/url_request_test_job.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "remoting/base/rsa_key_pair.h"
25 #include "remoting/base/test_rsa_key_pair.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
28
29 namespace {
30
31 const char kTokenUrl[] = "https://example.com/token";
32 const char kTokenValidationUrl[] = "https://example.com/validate";
33 const char kTokenValidationCertIssuer[] = "";
34 const char kLocalJid[] = "user@example.com/local";
35 const char kRemoteJid[] = "user@example.com/remote";
36 const char kToken[] = "xyz123456";
37 const char kSharedSecret[] = "abcdefgh";
38
39 // Bad scope: no nonce element.
40 const char kBadScope[] =
41 "client:user@example.com/local host:user@example.com/remote";
42
43 class TestURLRequestInterceptor : public net::URLRequestInterceptor {
44 public:
TestURLRequestInterceptor(const std::string & headers,const std::string & response)45 TestURLRequestInterceptor(const std::string& headers,
46 const std::string& response)
47 : headers_(headers), response_(response) {}
48
49 ~TestURLRequestInterceptor() override = default;
50
MaybeInterceptRequest(net::URLRequest * request) const51 std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
52 net::URLRequest* request) const override {
53 return std::make_unique<net::URLRequestTestJob>(request, headers_,
54 response_, true);
55 }
56
57 private:
58 std::string headers_;
59 std::string response_;
60 };
61
62 // Creates URLRequestJobs that fail at the specified phase.
63 class TestFailingURLRequestInterceptor : public net::URLRequestInterceptor {
64 public:
TestFailingURLRequestInterceptor(net::URLRequestFailedJob::FailurePhase failure_phase,net::Error net_error)65 TestFailingURLRequestInterceptor(
66 net::URLRequestFailedJob::FailurePhase failure_phase,
67 net::Error net_error)
68 : failure_phase_(failure_phase), net_error_(net_error) {}
69
70 ~TestFailingURLRequestInterceptor() override = default;
71
MaybeInterceptRequest(net::URLRequest * request) const72 std::unique_ptr<net::URLRequestJob> MaybeInterceptRequest(
73 net::URLRequest* request) const override {
74 return std::make_unique<net::URLRequestFailedJob>(request, failure_phase_,
75 net_error_);
76 }
77
78 private:
79 const net::URLRequestFailedJob::FailurePhase failure_phase_;
80 const net::Error net_error_;
81 };
82
83 } // namespace
84
85 namespace remoting {
86
87 class TokenValidatorFactoryImplTest : public testing::Test {
88 public:
TokenValidatorFactoryImplTest()89 TokenValidatorFactoryImplTest()
90 : task_environment_(
91 base::test::SingleThreadTaskEnvironment::MainThreadType::IO) {}
92
~TokenValidatorFactoryImplTest()93 ~TokenValidatorFactoryImplTest() override {
94 net::URLRequestFilter::GetInstance()->ClearHandlers();
95 }
96
SuccessCallback(const std::string & shared_secret)97 void SuccessCallback(const std::string& shared_secret) {
98 EXPECT_FALSE(shared_secret.empty());
99 run_loop_.QuitWhenIdle();
100 }
101
FailureCallback(const std::string & shared_secret)102 void FailureCallback(const std::string& shared_secret) {
103 EXPECT_TRUE(shared_secret.empty());
104 run_loop_.QuitWhenIdle();
105 }
106
DeleteOnFailureCallback(const std::string & shared_secret)107 void DeleteOnFailureCallback(const std::string& shared_secret) {
108 EXPECT_TRUE(shared_secret.empty());
109 token_validator_.reset();
110 run_loop_.QuitWhenIdle();
111 }
112
113 protected:
SetUp()114 void SetUp() override {
115 key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair);
116 request_context_getter_ = new net::TestURLRequestContextGetter(
117 task_environment_.GetMainThreadTaskRunner());
118 ThirdPartyAuthConfig config;
119 config.token_url = GURL(kTokenUrl);
120 config.token_validation_url = GURL(kTokenValidationUrl);
121 config.token_validation_cert_issuer = kTokenValidationCertIssuer;
122 token_validator_factory_ = new TokenValidatorFactoryImpl(
123 config, key_pair_, request_context_getter_);
124 }
125
CreateResponse(const std::string & scope)126 static std::string CreateResponse(const std::string& scope) {
127 base::DictionaryValue response_dict;
128 response_dict.SetString("access_token", kSharedSecret);
129 response_dict.SetString("token_type", "shared_secret");
130 response_dict.SetString("scope", scope);
131 std::string response;
132 base::JSONWriter::Write(response_dict, &response);
133 return response;
134 }
135
CreateErrorResponse(const std::string & error)136 static std::string CreateErrorResponse(const std::string& error) {
137 base::DictionaryValue response_dict;
138 response_dict.SetString("error", error);
139 std::string response;
140 base::JSONWriter::Write(response_dict, &response);
141 return response;
142 }
143
SetResponse(const std::string & headers,const std::string & response)144 void SetResponse(const std::string& headers, const std::string& response) {
145 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
146 "https", "example.com",
147 std::make_unique<TestURLRequestInterceptor>(headers, response));
148 }
149
SetErrorResponse(net::URLRequestFailedJob::FailurePhase failure_phase,net::Error net_error)150 void SetErrorResponse(net::URLRequestFailedJob::FailurePhase failure_phase,
151 net::Error net_error) {
152 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
153 "https", "example.com",
154 std::make_unique<TestFailingURLRequestInterceptor>(failure_phase,
155 net_error));
156 }
157
158 base::test::SingleThreadTaskEnvironment task_environment_;
159 base::RunLoop run_loop_;
160 scoped_refptr<RsaKeyPair> key_pair_;
161 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
162 scoped_refptr<TokenValidatorFactoryImpl> token_validator_factory_;
163 std::unique_ptr<protocol::TokenValidator> token_validator_;
164 };
165
TEST_F(TokenValidatorFactoryImplTest,Success)166 TEST_F(TokenValidatorFactoryImplTest, Success) {
167 token_validator_ =
168 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
169
170 SetResponse(net::URLRequestTestJob::test_headers(),
171 CreateResponse(token_validator_->token_scope()));
172
173 token_validator_->ValidateThirdPartyToken(
174 kToken, base::BindOnce(&TokenValidatorFactoryImplTest::SuccessCallback,
175 base::Unretained(this)));
176 run_loop_.Run();
177 }
178
TEST_F(TokenValidatorFactoryImplTest,ValidResponseWithJsonSafetyPrefix_Success)179 TEST_F(TokenValidatorFactoryImplTest,
180 ValidResponseWithJsonSafetyPrefix_Success) {
181 token_validator_ =
182 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
183
184 SetResponse(net::URLRequestTestJob::test_headers(),
185 ")]}'\n" + CreateResponse(token_validator_->token_scope()));
186
187 token_validator_->ValidateThirdPartyToken(
188 kToken, base::BindOnce(&TokenValidatorFactoryImplTest::SuccessCallback,
189 base::Unretained(this)));
190 run_loop_.Run();
191 }
192
TEST_F(TokenValidatorFactoryImplTest,BadToken)193 TEST_F(TokenValidatorFactoryImplTest, BadToken) {
194 token_validator_ =
195 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
196
197 SetResponse(net::URLRequestTestJob::test_error_headers(), std::string());
198
199 token_validator_->ValidateThirdPartyToken(
200 kToken, base::BindOnce(&TokenValidatorFactoryImplTest::FailureCallback,
201 base::Unretained(this)));
202 run_loop_.Run();
203 }
204
TEST_F(TokenValidatorFactoryImplTest,BadScope)205 TEST_F(TokenValidatorFactoryImplTest, BadScope) {
206 token_validator_ =
207 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
208
209 SetResponse(net::URLRequestTestJob::test_headers(),
210 CreateResponse(kBadScope));
211
212 token_validator_->ValidateThirdPartyToken(
213 kToken, base::BindOnce(&TokenValidatorFactoryImplTest::FailureCallback,
214 base::Unretained(this)));
215 run_loop_.Run();
216 }
217
TEST_F(TokenValidatorFactoryImplTest,DeleteOnFailure)218 TEST_F(TokenValidatorFactoryImplTest, DeleteOnFailure) {
219 token_validator_ =
220 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
221
222 SetResponse(net::URLRequestTestJob::test_error_headers(), std::string());
223
224 token_validator_->ValidateThirdPartyToken(
225 kToken,
226 base::BindOnce(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
227 base::Unretained(this)));
228 run_loop_.Run();
229 }
230
TEST_F(TokenValidatorFactoryImplTest,DeleteOnStartError)231 TEST_F(TokenValidatorFactoryImplTest, DeleteOnStartError) {
232 token_validator_ =
233 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
234
235 SetErrorResponse(net::URLRequestFailedJob::START, net::ERR_FAILED);
236
237 token_validator_->ValidateThirdPartyToken(
238 kToken,
239 base::BindOnce(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
240 base::Unretained(this)));
241 run_loop_.Run();
242 }
243
TEST_F(TokenValidatorFactoryImplTest,DeleteOnSyncReadError)244 TEST_F(TokenValidatorFactoryImplTest, DeleteOnSyncReadError) {
245 token_validator_ =
246 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
247
248 SetErrorResponse(net::URLRequestFailedJob::READ_SYNC, net::ERR_FAILED);
249
250 token_validator_->ValidateThirdPartyToken(
251 kToken,
252 base::BindOnce(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
253 base::Unretained(this)));
254 run_loop_.Run();
255 }
256
TEST_F(TokenValidatorFactoryImplTest,DeleteOnAsyncReadError)257 TEST_F(TokenValidatorFactoryImplTest, DeleteOnAsyncReadError) {
258 token_validator_ =
259 token_validator_factory_->CreateTokenValidator(kLocalJid, kRemoteJid);
260
261 SetErrorResponse(net::URLRequestFailedJob::READ_ASYNC, net::ERR_FAILED);
262
263 token_validator_->ValidateThirdPartyToken(
264 kToken,
265 base::BindOnce(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
266 base::Unretained(this)));
267 run_loop_.Run();
268 }
269
270 } // namespace remoting
271