1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "remoting/host/token_validator_base.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/base64.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/callback.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/json/json_reader.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/weak_ptr.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/single_thread_task_runner.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_util.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/values.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/escape.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/io_buffer.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/request_priority.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/upload_bytes_element_reader.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/base/upload_data_stream.h" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/ssl/client_cert_store.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(USE_NSS) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/ssl/client_cert_store_nss.h" 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_WIN) 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/ssl/client_cert_store_win.h" 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_MACOSX) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/ssl/client_cert_store_mac.h" 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h" 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request.h" 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request_context.h" 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request_status.h" 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/gurl.h" 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kBufferSize = 4096; 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kCertIssuerWildCard[] = "*"; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace remoting { 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TokenValidatorBase::TokenValidatorBase( 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ThirdPartyAuthConfig& third_party_auth_config, 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& token_scope, 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter) 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : third_party_auth_config_(third_party_auth_config), 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) token_scope_(token_scope), 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_context_getter_(request_context_getter), 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer_(new net::IOBuffer(kBufferSize)), 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_(this) { 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(third_party_auth_config_.token_url.is_valid()); 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(third_party_auth_config_.token_validation_url.is_valid()); 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TokenValidatorBase::~TokenValidatorBase() { 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TokenValidator interface. 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorBase::ValidateThirdPartyToken( 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& token, 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Callback<void( 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& shared_secret)>& on_token_validated) { 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!request_); 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!on_token_validated.is_null()); 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) on_token_validated_ = on_token_validated; 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartValidateRequest(token); 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const GURL& TokenValidatorBase::token_url() const { 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return third_party_auth_config_.token_url; 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const std::string& TokenValidatorBase::token_scope() const { 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return token_scope_; 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// URLFetcherDelegate interface. 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorBase::OnResponseStarted(net::URLRequest* source) { 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(request_.get(), source); 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int bytes_read = 0; 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_->Read(buffer_.get(), kBufferSize, &bytes_read); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnReadCompleted(request_.get(), bytes_read); 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorBase::OnReadCompleted(net::URLRequest* source, 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int bytes_read) { 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(request_.get(), source); 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) do { 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!request_->status().is_success() || bytes_read <= 0) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data_.append(buffer_->data(), bytes_read); 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read)); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const net::URLRequestStatus status = request_->status(); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!status.is_io_pending()) { 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string shared_token = ProcessResponse(); 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_.reset(); 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) on_token_validated_.Run(shared_token); 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorBase::OnCertificateRequested( 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequest* source, 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::SSLCertRequestInfo* cert_request_info) { 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(request_.get(), source); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::ClientCertStore* client_cert_store; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(USE_NSS) 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_cert_store = new net::ClientCertStoreNSS( 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::ClientCertStoreNSS::PasswordDelegateFactory()); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_WIN) 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_cert_store = new net::ClientCertStoreWin(); 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#elif defined(OS_MACOSX) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_cert_store = new net::ClientCertStoreMac(); 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#elif defined(USE_OPENSSL) 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // OpenSSL does not use the ClientCertStore infrastructure. 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) client_cert_store = NULL; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#else 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#error Unknown platform. 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The callback is uncancellable, and GetClientCert requires selected_certs 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // and client_cert_store to stay alive until the callback is called. So we 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // must give it a WeakPtr for |this|, and ownership of the other parameters. 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::CertificateList* selected_certs(new net::CertificateList()); 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_cert_store->GetClientCerts( 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *cert_request_info, selected_certs, 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&TokenValidatorBase::OnCertificatesSelected, 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_factory_.GetWeakPtr(), base::Owned(selected_certs), 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Owned(client_cert_store))); 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorBase::OnCertificatesSelected( 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::CertificateList* selected_certs, 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::ClientCertStore* unused) { 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& issuer = 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) third_party_auth_config_.token_validation_cert_issuer; 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (request_) { 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < selected_certs->size(); ++i) { 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (issuer == kCertIssuerWildCard || 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) issuer == (*selected_certs)[i]->issuer().common_name) { 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request_->ContinueWithCertificate((*selected_certs)[i].get()); 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_->ContinueWithCertificate(NULL); 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool TokenValidatorBase::IsValidScope(const std::string& token_scope) { 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc. 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return token_scope == token_scope_; 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string TokenValidatorBase::ProcessResponse() { 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Verify that we got a successful response. 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequestStatus status = request_->status(); 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!status.is_success()) { 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Error validating token, status=" << status.status() 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " err=" << status.error(); 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int response = request_->GetResponseCode(); 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (response != 200) { 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Error " << response << " validating token: '" << data_ << "'"; 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Decode the JSON data from the response. 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(data_)); 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DictionaryValue* dict; 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY || 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !value->GetAsDictionary(&dict)) { 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Invalid token validation response: '" << data_ << "'"; 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string token_scope; 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dict->GetStringWithoutPathExpansion("scope", &token_scope); 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsValidScope(token_scope)) { 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG(ERROR) << "Invalid scope: '" << token_scope 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "', expected: '" << token_scope_ <<"'."; 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::string(); 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string shared_secret; 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Everything is valid, so return the shared secret to the caller. 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dict->GetStringWithoutPathExpansion("access_token", &shared_secret); 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return shared_secret; 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace remoting 202