blob: 6d2a066d164186a164c925e9113d4f5a538e4709 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/token_validator_factory_impl.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include "base/base64.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/stringize_macros.h"
#include "base/values.h"
#include "crypto/random.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/escape.h"
#include "net/base/io_buffer.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/host/token_validator_base.h"
#include "url/gurl.h"
namespace {
// Length in bytes of the cryptographic nonce used to salt the token scope.
const size_t kNonceLength = 16; // 128 bits.
} // namespace
namespace remoting {
class TokenValidatorImpl : public TokenValidatorBase {
public:
TokenValidatorImpl(
const ThirdPartyAuthConfig& third_party_auth_config,
scoped_refptr<RsaKeyPair> key_pair,
const std::string& local_jid,
const std::string& remote_jid,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
protected:
void StartValidateRequest(const std::string& token) override;
private:
static std::string CreateScope(const std::string& local_jid,
const std::string& remote_jid);
std::string post_body_;
scoped_refptr<RsaKeyPair> key_pair_;
DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl);
};
TokenValidatorImpl::TokenValidatorImpl(
const ThirdPartyAuthConfig& third_party_auth_config,
scoped_refptr<RsaKeyPair> key_pair,
const std::string& local_jid,
const std::string& remote_jid,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
: TokenValidatorBase(third_party_auth_config,
CreateScope(local_jid, remote_jid),
request_context_getter),
key_pair_(key_pair) {
DCHECK(key_pair_.get());
token_scope_ = CreateScope(local_jid, remote_jid);
}
// TokenValidator interface.
void TokenValidatorImpl::StartValidateRequest(const std::string& token) {
post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) +
"&client_id=" + net::EscapeUrlEncodedData(
key_pair_->GetPublicKey(), true) +
"&client_secret=" + net::EscapeUrlEncodedData(
key_pair_->SignMessage(token), true) +
"&grant_type=authorization_code";
request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY,
this);
#if defined(GOOGLE_CHROME_BUILD)
std::string app_name = "Chrome Remote Desktop";
#else
std::string app_name = "Chromoting";
#endif
#ifndef VERSION
#error VERSION is not set.
#endif
// Set a user-agent for logging/auditing purposes.
request_->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kUserAgent,
app_name + " " + STRINGIZE(VERSION),
true);
request_->SetExtraRequestHeaderByName(
net::HttpRequestHeaders::kContentType,
"application/x-www-form-urlencoded", true);
request_->set_method("POST");
std::unique_ptr<net::UploadElementReader> reader(
new net::UploadBytesElementReader(post_body_.data(), post_body_.size()));
request_->set_upload(
net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
request_->Start();
}
std::string TokenValidatorImpl::CreateScope(
const std::string& local_jid,
const std::string& remote_jid) {
std::string nonce_bytes;
crypto::RandBytes(base::WriteInto(&nonce_bytes, kNonceLength + 1),
kNonceLength);
std::string nonce;
base::Base64Encode(nonce_bytes, &nonce);
return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce;
}
TokenValidatorFactoryImpl::TokenValidatorFactoryImpl(
const ThirdPartyAuthConfig& third_party_auth_config,
scoped_refptr<RsaKeyPair> key_pair,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
: third_party_auth_config_(third_party_auth_config),
key_pair_(key_pair),
request_context_getter_(request_context_getter) {
}
TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() = default;
std::unique_ptr<protocol::TokenValidator>
TokenValidatorFactoryImpl::CreateTokenValidator(const std::string& local_jid,
const std::string& remote_jid) {
return std::make_unique<TokenValidatorImpl>(third_party_auth_config_,
key_pair_, local_jid, remote_jid,
request_context_getter_);
}
} // namespace remoting