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#include "remoting/host/token_validator_factory_impl.h"
6
7#include "base/base64.h"
8#include "base/bind.h"
9#include "base/callback.h"
10#include "base/json/json_reader.h"
11#include "base/logging.h"
12#include "base/single_thread_task_runner.h"
13#include "base/strings/string_util.h"
14#include "base/values.h"
15#include "crypto/random.h"
16#include "net/base/escape.h"
17#include "net/base/io_buffer.h"
18#include "net/base/request_priority.h"
19#include "net/base/upload_bytes_element_reader.h"
20#include "net/base/upload_data_stream.h"
21#include "net/url_request/url_request.h"
22#include "net/url_request/url_request_context.h"
23#include "net/url_request/url_request_status.h"
24#include "remoting/base/rsa_key_pair.h"
25#include "remoting/host/token_validator_base.h"
26#include "url/gurl.h"
27
28namespace {
29
30// Length in bytes of the cryptographic nonce used to salt the token scope.
31const size_t kNonceLength = 16;  // 128 bits.
32
33}  // namespace
34
35namespace remoting {
36
37
38class TokenValidatorImpl : public TokenValidatorBase {
39 public:
40  TokenValidatorImpl(
41      const ThirdPartyAuthConfig& third_party_auth_config,
42      scoped_refptr<RsaKeyPair> key_pair,
43      const std::string& local_jid,
44      const std::string& remote_jid,
45      scoped_refptr<net::URLRequestContextGetter> request_context_getter);
46
47 protected:
48  virtual void StartValidateRequest(const std::string& token) OVERRIDE;
49
50 private:
51  static std::string CreateScope(const std::string& local_jid,
52                                 const std::string& remote_jid);
53
54  std::string post_body_;
55  scoped_refptr<RsaKeyPair> key_pair_;
56
57  DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl);
58};
59
60TokenValidatorImpl::TokenValidatorImpl(
61    const ThirdPartyAuthConfig& third_party_auth_config,
62    scoped_refptr<RsaKeyPair> key_pair,
63    const std::string& local_jid,
64    const std::string& remote_jid,
65    scoped_refptr<net::URLRequestContextGetter> request_context_getter)
66    : TokenValidatorBase(third_party_auth_config,
67                         CreateScope(local_jid, remote_jid),
68                         request_context_getter),
69      key_pair_(key_pair) {
70  DCHECK(key_pair_.get());
71  token_scope_ = CreateScope(local_jid, remote_jid);
72}
73
74// TokenValidator interface.
75void TokenValidatorImpl::StartValidateRequest(const std::string& token) {
76  post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) +
77      "&client_id=" + net::EscapeUrlEncodedData(
78          key_pair_->GetPublicKey(), true) +
79      "&client_secret=" + net::EscapeUrlEncodedData(
80          key_pair_->SignMessage(token), true) +
81      "&grant_type=authorization_code";
82
83  request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
84      third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY,
85      this, NULL);
86  request_->SetExtraRequestHeaderByName(
87      net::HttpRequestHeaders::kContentType,
88      "application/x-www-form-urlencoded", true);
89  request_->set_method("POST");
90  scoped_ptr<net::UploadElementReader> reader(
91      new net::UploadBytesElementReader(
92          post_body_.data(), post_body_.size()));
93  request_->set_upload(make_scoped_ptr(
94      net::UploadDataStream::CreateWithReader(reader.Pass(), 0)));
95  request_->Start();
96}
97
98std::string TokenValidatorImpl::CreateScope(
99    const std::string& local_jid,
100    const std::string& remote_jid) {
101  std::string nonce_bytes;
102  crypto::RandBytes(WriteInto(&nonce_bytes, kNonceLength + 1), kNonceLength);
103  std::string nonce;
104  base::Base64Encode(nonce_bytes, &nonce);
105  return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce;
106}
107
108TokenValidatorFactoryImpl::TokenValidatorFactoryImpl(
109    const ThirdPartyAuthConfig& third_party_auth_config,
110    scoped_refptr<RsaKeyPair> key_pair,
111    scoped_refptr<net::URLRequestContextGetter> request_context_getter)
112    : third_party_auth_config_(third_party_auth_config),
113      key_pair_(key_pair),
114      request_context_getter_(request_context_getter) {
115}
116
117TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() {
118}
119
120scoped_ptr<protocol::TokenValidator>
121TokenValidatorFactoryImpl::CreateTokenValidator(
122    const std::string& local_jid,
123    const std::string& remote_jid) {
124  return scoped_ptr<protocol::TokenValidator>(
125      new TokenValidatorImpl(third_party_auth_config_,
126                             key_pair_, local_jid, remote_jid,
127                             request_context_getter_));
128}
129
130}  // namespace remoting
131