Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: remoting/host/token_validator_factory_impl.cc

Issue 165293004: Refactor TokenValidatorImpl into a base class + implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/token_validator_factory_impl.h" 5 #include "remoting/host/token_validator_factory_impl.h"
6 6
7 #include <set>
8
9 #include "base/base64.h" 7 #include "base/base64.h"
10 #include "base/bind.h" 8 #include "base/bind.h"
11 #include "base/callback.h" 9 #include "base/callback.h"
12 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
13 #include "base/location.h"
14 #include "base/logging.h" 11 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
17 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
18 #include "base/values.h" 14 #include "base/values.h"
19 #include "crypto/random.h" 15 #include "crypto/random.h"
20 #include "net/base/escape.h" 16 #include "net/base/escape.h"
21 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
22 #include "net/base/request_priority.h" 18 #include "net/base/request_priority.h"
23 #include "net/base/upload_bytes_element_reader.h" 19 #include "net/base/upload_bytes_element_reader.h"
24 #include "net/base/upload_data_stream.h" 20 #include "net/base/upload_data_stream.h"
25 #include "net/ssl/client_cert_store.h"
26 #if defined(USE_NSS)
27 #include "net/ssl/client_cert_store_nss.h"
28 #elif defined(OS_WIN)
29 #include "net/ssl/client_cert_store_win.h"
30 #elif defined(OS_MACOSX)
31 #include "net/ssl/client_cert_store_mac.h"
32 #endif
33 #include "net/ssl/ssl_cert_request_info.h"
34 #include "net/url_request/url_request.h" 21 #include "net/url_request/url_request.h"
35 #include "net/url_request/url_request_context.h" 22 #include "net/url_request/url_request_context.h"
36 #include "net/url_request/url_request_status.h" 23 #include "net/url_request/url_request_status.h"
37 #include "remoting/base/rsa_key_pair.h" 24 #include "remoting/base/rsa_key_pair.h"
25 #include "remoting/host/token_validator_base.h"
38 #include "url/gurl.h" 26 #include "url/gurl.h"
39 27
40 namespace { 28 namespace {
41 29
42 // Length in bytes of the cryptographic nonce used to salt the token scope. 30 // Length in bytes of the cryptographic nonce used to salt the token scope.
43 const size_t kNonceLength = 16; // 128 bits. 31 const size_t kNonceLength = 16; // 128 bits.
44 const int kBufferSize = 4096;
45 const char kCertIssuerWildCard[] = "*";
46 32
47 } // namespace 33 } // namespace
48 34
49 namespace remoting { 35 namespace remoting {
50 36
51 class TokenValidatorImpl 37
52 : public net::URLRequest::Delegate, 38 class TokenValidatorImpl : public TokenValidatorBase {
53 public protocol::ThirdPartyHostAuthenticator::TokenValidator {
54 public: 39 public:
55 TokenValidatorImpl( 40 TokenValidatorImpl(
56 const ThirdPartyAuthConfig& third_party_auth_config, 41 const ThirdPartyAuthConfig& third_party_auth_config,
57 scoped_refptr<RsaKeyPair> key_pair, 42 scoped_refptr<RsaKeyPair> key_pair,
58 const std::string& local_jid, 43 const std::string& local_jid,
59 const std::string& remote_jid, 44 const std::string& remote_jid,
60 scoped_refptr<net::URLRequestContextGetter> request_context_getter); 45 scoped_refptr<net::URLRequestContextGetter> request_context_getter);
61 virtual ~TokenValidatorImpl();
62 46
63 // TokenValidator interface. 47 protected:
64 virtual const GURL& token_url() const OVERRIDE; 48 virtual void StartValidateRequest(const std::string& token) OVERRIDE;
65 virtual const std::string& token_scope() const OVERRIDE;
66 virtual void ValidateThirdPartyToken(
67 const std::string& token,
68 const base::Callback<void(
69 const std::string& shared_secret)>& on_token_validated) OVERRIDE;
70
71 // URLFetcherDelegate interface.
72 virtual void OnResponseStarted(net::URLRequest* source) OVERRIDE;
73 virtual void OnReadCompleted(net::URLRequest* source,
74 int bytes_read) OVERRIDE;
75 virtual void OnCertificateRequested(
76 net::URLRequest* source,
77 net::SSLCertRequestInfo* cert_request_info) OVERRIDE;
78 49
79 private: 50 private:
80 static std::string CreateScope(const std::string& local_jid, 51 static std::string CreateScope(const std::string& local_jid,
81 const std::string& remote_jid); 52 const std::string& remote_jid);
82 53
83 void OnCertificatesSelected(net::CertificateList* selected_certs,
84 net::ClientCertStore* unused);
85 bool IsValidScope(const std::string& token_scope);
86 std::string ProcessResponse();
87
88 std::string post_body_; 54 std::string post_body_;
89 scoped_ptr<net::URLRequest> request_;
90 scoped_refptr<net::IOBuffer> buffer_;
91 std::string data_;
92 ThirdPartyAuthConfig third_party_auth_config_;
93 scoped_refptr<RsaKeyPair> key_pair_; 55 scoped_refptr<RsaKeyPair> key_pair_;
94 std::string token_scope_;
95 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
96 base::Callback<void(const std::string& shared_secret)> on_token_validated_;
97
98 base::WeakPtrFactory<TokenValidatorImpl> weak_factory_;
99 56
100 DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl); 57 DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl);
101 }; 58 };
102 59
103 TokenValidatorImpl::TokenValidatorImpl( 60 TokenValidatorImpl::TokenValidatorImpl(
104 const ThirdPartyAuthConfig& third_party_auth_config, 61 const ThirdPartyAuthConfig& third_party_auth_config,
105 scoped_refptr<RsaKeyPair> key_pair, 62 scoped_refptr<RsaKeyPair> key_pair,
106 const std::string& local_jid, 63 const std::string& local_jid,
107 const std::string& remote_jid, 64 const std::string& remote_jid,
108 scoped_refptr<net::URLRequestContextGetter> request_context_getter) 65 scoped_refptr<net::URLRequestContextGetter> request_context_getter)
109 : buffer_(new net::IOBuffer(kBufferSize)), 66 : TokenValidatorBase(third_party_auth_config,
110 third_party_auth_config_(third_party_auth_config), 67 CreateScope(local_jid, remote_jid),
111 key_pair_(key_pair), 68 request_context_getter),
112 request_context_getter_(request_context_getter), 69 key_pair_(key_pair) {
113 weak_factory_(this) {
114 DCHECK(third_party_auth_config_.token_url.is_valid());
115 DCHECK(third_party_auth_config_.token_validation_url.is_valid());
116 DCHECK(key_pair_.get()); 70 DCHECK(key_pair_.get());
117 token_scope_ = CreateScope(local_jid, remote_jid); 71 token_scope_ = CreateScope(local_jid, remote_jid);
118 } 72 }
119 73
120 TokenValidatorImpl::~TokenValidatorImpl() {
121 }
122
123 // TokenValidator interface. 74 // TokenValidator interface.
124 void TokenValidatorImpl::ValidateThirdPartyToken( 75 void TokenValidatorImpl::StartValidateRequest(const std::string& token) {
125 const std::string& token,
126 const base::Callback<void(
127 const std::string& shared_secret)>& on_token_validated) {
128 DCHECK(!request_);
129 DCHECK(!on_token_validated.is_null());
130
131 on_token_validated_ = on_token_validated;
132
133 post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) + 76 post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) +
134 "&client_id=" + net::EscapeUrlEncodedData( 77 "&client_id=" + net::EscapeUrlEncodedData(
135 key_pair_->GetPublicKey(), true) + 78 key_pair_->GetPublicKey(), true) +
136 "&client_secret=" + net::EscapeUrlEncodedData( 79 "&client_secret=" + net::EscapeUrlEncodedData(
137 key_pair_->SignMessage(token), true) + 80 key_pair_->SignMessage(token), true) +
138 "&grant_type=authorization_code"; 81 "&grant_type=authorization_code";
139 82
140 request_ = request_context_getter_->GetURLRequestContext()->CreateRequest( 83 request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
141 third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY, 84 third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY,
142 this); 85 this);
143 request_->SetExtraRequestHeaderByName( 86 request_->SetExtraRequestHeaderByName(
144 net::HttpRequestHeaders::kContentType, 87 net::HttpRequestHeaders::kContentType,
145 "application/x-www-form-urlencoded", true); 88 "application/x-www-form-urlencoded", true);
146 request_->set_method("POST"); 89 request_->set_method("POST");
147 scoped_ptr<net::UploadElementReader> reader( 90 scoped_ptr<net::UploadElementReader> reader(
148 new net::UploadBytesElementReader( 91 new net::UploadBytesElementReader(
149 post_body_.data(), post_body_.size())); 92 post_body_.data(), post_body_.size()));
150 request_->set_upload(make_scoped_ptr( 93 request_->set_upload(make_scoped_ptr(
151 net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); 94 net::UploadDataStream::CreateWithReader(reader.Pass(), 0)));
152 request_->Start(); 95 request_->Start();
153 } 96 }
154 97
155 const GURL& TokenValidatorImpl::token_url() const {
156 return third_party_auth_config_.token_url;
157 }
158
159 const std::string& TokenValidatorImpl::token_scope() const {
160 return token_scope_;
161 }
162
163 // URLFetcherDelegate interface.
164 void TokenValidatorImpl::OnResponseStarted(net::URLRequest* source) {
165 DCHECK_EQ(request_.get(), source);
166
167 int bytes_read = 0;
168 request_->Read(buffer_.get(), kBufferSize, &bytes_read);
169 OnReadCompleted(request_.get(), bytes_read);
170 }
171
172 void TokenValidatorImpl::OnReadCompleted(net::URLRequest* source,
173 int bytes_read) {
174 DCHECK_EQ(request_.get(), source);
175
176 do {
177 if (!request_->status().is_success() || bytes_read <= 0)
178 break;
179
180 data_.append(buffer_->data(), bytes_read);
181 } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read));
182
183 const net::URLRequestStatus status = request_->status();
184
185 if (!status.is_io_pending()) {
186 std::string shared_token = ProcessResponse();
187 request_.reset();
188 on_token_validated_.Run(shared_token);
189 }
190 }
191
192 void TokenValidatorImpl::OnCertificateRequested(
193 net::URLRequest* source,
194 net::SSLCertRequestInfo* cert_request_info) {
195 DCHECK_EQ(request_.get(), source);
196
197 net::ClientCertStore* client_cert_store;
198 #if defined(USE_NSS)
199 client_cert_store = new net::ClientCertStoreNSS(
200 net::ClientCertStoreNSS::PasswordDelegateFactory());
201 #elif defined(OS_WIN)
202 client_cert_store = new net::ClientCertStoreWin();
203 #elif defined(OS_MACOSX)
204 client_cert_store = new net::ClientCertStoreMac();
205 #else
206 #error Unknown platform.
207 #endif
208 // The callback is uncancellable, and GetClientCert requires selected_certs
209 // and client_cert_store to stay alive until the callback is called. So we
210 // must give it a WeakPtr for |this|, and ownership of the other parameters.
211 net::CertificateList* selected_certs(new net::CertificateList());
212 client_cert_store->GetClientCerts(
213 *cert_request_info, selected_certs,
214 base::Bind(&TokenValidatorImpl::OnCertificatesSelected,
215 weak_factory_.GetWeakPtr(), base::Owned(selected_certs),
216 base::Owned(client_cert_store)));
217 }
218
219 void TokenValidatorImpl::OnCertificatesSelected(
220 net::CertificateList* selected_certs,
221 net::ClientCertStore* unused) {
222 const std::string& issuer =
223 third_party_auth_config_.token_validation_cert_issuer;
224 if (request_) {
225 for (size_t i = 0; i < selected_certs->size(); ++i) {
226 if (issuer == kCertIssuerWildCard ||
227 issuer == (*selected_certs)[i]->issuer().common_name) {
228 request_->ContinueWithCertificate((*selected_certs)[i]);
229 return;
230 }
231 }
232 request_->ContinueWithCertificate(NULL);
233 }
234 }
235
236 bool TokenValidatorImpl::IsValidScope(const std::string& token_scope) {
237 // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc.
238 return token_scope == token_scope_;
239 }
240
241 std::string TokenValidatorImpl::CreateScope( 98 std::string TokenValidatorImpl::CreateScope(
242 const std::string& local_jid, 99 const std::string& local_jid,
243 const std::string& remote_jid) { 100 const std::string& remote_jid) {
244 std::string nonce_bytes; 101 std::string nonce_bytes;
245 crypto::RandBytes(WriteInto(&nonce_bytes, kNonceLength + 1), kNonceLength); 102 crypto::RandBytes(WriteInto(&nonce_bytes, kNonceLength + 1), kNonceLength);
246 std::string nonce; 103 std::string nonce;
247 base::Base64Encode(nonce_bytes, &nonce); 104 base::Base64Encode(nonce_bytes, &nonce);
248 return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce; 105 return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce;
249 } 106 }
250 107
251 std::string TokenValidatorImpl::ProcessResponse() {
252 // Verify that we got a successful response.
253 net::URLRequestStatus status = request_->status();
254 if (!status.is_success()) {
255 LOG(ERROR) << "Error validating token, status=" << status.status()
256 << " err=" << status.error();
257 return std::string();
258 }
259
260 int response = request_->GetResponseCode();
261 if (response != 200) {
262 LOG(ERROR)
263 << "Error " << response << " validating token: '" << data_ << "'";
264 return std::string();
265 }
266
267 // Decode the JSON data from the response.
268 scoped_ptr<base::Value> value(base::JSONReader::Read(data_));
269 base::DictionaryValue* dict;
270 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY ||
271 !value->GetAsDictionary(&dict)) {
272 LOG(ERROR) << "Invalid token validation response: '" << data_ << "'";
273 return std::string();
274 }
275
276 std::string token_scope;
277 dict->GetStringWithoutPathExpansion("scope", &token_scope);
278 if (!IsValidScope(token_scope)) {
279 LOG(ERROR) << "Invalid scope: '" << token_scope
280 << "', expected: '" << token_scope_ <<"'.";
281 return std::string();
282 }
283
284 std::string shared_secret;
285 // Everything is valid, so return the shared secret to the caller.
286 dict->GetStringWithoutPathExpansion("access_token", &shared_secret);
287 return shared_secret;
288 }
289
290 TokenValidatorFactoryImpl::TokenValidatorFactoryImpl( 108 TokenValidatorFactoryImpl::TokenValidatorFactoryImpl(
291 const ThirdPartyAuthConfig& third_party_auth_config, 109 const ThirdPartyAuthConfig& third_party_auth_config,
292 scoped_refptr<RsaKeyPair> key_pair, 110 scoped_refptr<RsaKeyPair> key_pair,
293 scoped_refptr<net::URLRequestContextGetter> request_context_getter) 111 scoped_refptr<net::URLRequestContextGetter> request_context_getter)
294 : third_party_auth_config_(third_party_auth_config), 112 : third_party_auth_config_(third_party_auth_config),
295 key_pair_(key_pair), 113 key_pair_(key_pair),
296 request_context_getter_(request_context_getter) { 114 request_context_getter_(request_context_getter) {
297 } 115 }
298 116
299 TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() { 117 TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() {
300 } 118 }
301 119
302 scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator> 120 scoped_ptr<protocol::TokenValidator>
303 TokenValidatorFactoryImpl::CreateTokenValidator( 121 TokenValidatorFactoryImpl::CreateTokenValidator(
304 const std::string& local_jid, 122 const std::string& local_jid,
305 const std::string& remote_jid) { 123 const std::string& remote_jid) {
306 return scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>( 124 return scoped_ptr<protocol::TokenValidator>(
307 new TokenValidatorImpl(third_party_auth_config_, 125 new TokenValidatorImpl(third_party_auth_config_,
308 key_pair_, local_jid, remote_jid, 126 key_pair_, local_jid, remote_jid,
309 request_context_getter_)); 127 request_context_getter_));
310 } 128 }
311 129
312 } // namespace remoting 130 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/token_validator_factory_impl.h ('k') | remoting/host/token_validator_factory_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698