1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/host/token_validator_factory_impl.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base64.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_reader.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/single_thread_task_runner.h" 135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "crypto/random.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/escape.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/io_buffer.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/request_priority.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/upload_bytes_element_reader.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/upload_data_stream.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_context.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_status.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/rsa_key_pair.h" 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "remoting/host/token_validator_base.h" 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Length in bytes of the cryptographic nonce used to salt the token scope. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kNonceLength = 16; // 128 bits. 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace remoting { 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class TokenValidatorImpl : public TokenValidatorBase { 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TokenValidatorImpl( 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ThirdPartyAuthConfig& third_party_auth_config, 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair, 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& local_jid, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& remote_jid, 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter); 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected: 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void StartValidateRequest(const std::string& token) OVERRIDE; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static std::string CreateScope(const std::string& local_jid, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& remote_jid); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string post_body_; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair_; 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TokenValidatorImpl::TokenValidatorImpl( 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ThirdPartyAuthConfig& third_party_auth_config, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair, 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& local_jid, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& remote_jid, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : TokenValidatorBase(third_party_auth_config, 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateScope(local_jid, remote_jid), 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_context_getter), 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) key_pair_(key_pair) { 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(key_pair_.get()); 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) token_scope_ = CreateScope(local_jid, remote_jid); 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TokenValidator interface. 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TokenValidatorImpl::StartValidateRequest(const std::string& token) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) + 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "&client_id=" + net::EscapeUrlEncodedData( 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_pair_->GetPublicKey(), true) + 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "&client_secret=" + net::EscapeUrlEncodedData( 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_pair_->SignMessage(token), true) + 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "&grant_type=authorization_code"; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_ = request_context_getter_->GetURLRequestContext()->CreateRequest( 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY, 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, NULL); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_->SetExtraRequestHeaderByName( 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::HttpRequestHeaders::kContentType, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "application/x-www-form-urlencoded", true); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_->set_method("POST"); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<net::UploadElementReader> reader( 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new net::UploadBytesElementReader( 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) post_body_.data(), post_body_.size())); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_->set_upload(make_scoped_ptr( 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_->Start(); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string TokenValidatorImpl::CreateScope( 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& local_jid, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& remote_jid) { 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string nonce_bytes; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) crypto::RandBytes(WriteInto(&nonce_bytes, kNonceLength + 1), kNonceLength); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string nonce; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Base64Encode(nonce_bytes, &nonce); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce; 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TokenValidatorFactoryImpl::TokenValidatorFactoryImpl( 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ThirdPartyAuthConfig& third_party_auth_config, 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair, 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : third_party_auth_config_(third_party_auth_config), 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key_pair_(key_pair), 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request_context_getter_(request_context_getter) { 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() { 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<protocol::TokenValidator> 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TokenValidatorFactoryImpl::CreateTokenValidator( 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& local_jid, 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& remote_jid) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return scoped_ptr<protocol::TokenValidator>( 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new TokenValidatorImpl(third_party_auth_config_, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) key_pair_, local_jid, remote_jid, 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request_context_getter_)); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace remoting 131