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

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

Issue 12313085: Host-side third party token validation (Closed) Base URL: http://git.chromium.org/chromium/src.git@third_party_auth_protocol
Patch Set: Reviewer comments Created 7 years, 8 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
OLDNEW
(Empty)
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/url_fetcher_token_validator_factory.h"
6
7 #include <set>
8
9 #include "base/base64.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/json/json_reader.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/values.h"
17 #include "crypto/random.h"
18 #include "googleurl/src/gurl.h"
19 #include "net/base/escape.h"
20 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_fetcher_delegate.h"
22 #include "net/url_request/url_request_status.h"
23 #include "remoting/base/rsa_key_pair.h"
24
25 namespace {
26
27 // Length in bytes of the cryptographic nonce used to salt the token scope.
28 const size_t kNonceLength = 16; // 128 bits.
29
30 }
31
32 namespace remoting {
33
34 class UrlFetcherTokenValidator
35 : public net::URLFetcherDelegate,
36 public protocol::ThirdPartyHostAuthenticator::TokenValidator {
37 public:
38 UrlFetcherTokenValidator(
39 const GURL& token_url,
40 const GURL& token_validation_url,
41 scoped_refptr<RsaKeyPair> key_pair,
42 const std::string& local_jid,
43 const std::string& remote_jid,
44 scoped_refptr<net::URLRequestContextGetter> request_context_getter)
45 : token_url_(token_url),
46 token_validation_url_(token_validation_url),
47 key_pair_(key_pair),
48 request_context_getter_(request_context_getter) {
49 DCHECK(token_url_.is_valid());
50 DCHECK(token_validation_url_.is_valid());
51 DCHECK(key_pair_);
52 token_scope_ = CreateScope(local_jid, remote_jid);
53 }
54
55 virtual ~UrlFetcherTokenValidator() {
56 }
57
58 // TokenValidator interface.
59 virtual void ValidateThirdPartyToken(
60 const std::string& token,
61 const base::Callback<void(
62 const std::string& shared_secret)>& on_token_validated) OVERRIDE {
63 DCHECK(!request_);
64 DCHECK(!on_token_validated.is_null());
65
66 on_token_validated_ = on_token_validated;
67
68 std::string post_body =
69 "code=" + net::EscapeUrlEncodedData(token, true) +
70 "&client_id=" + net::EscapeUrlEncodedData(
71 key_pair_->GetPublicKey(), true) +
72 "&client_secret=" + net::EscapeUrlEncodedData(
73 key_pair_->SignMessage(token), true) +
74 "&grant_type=authorization_code";
75 request_.reset(net::URLFetcher::Create(
76 token_validation_url_, net::URLFetcher::POST, this));
77 request_->SetUploadData("application/x-www-form-urlencoded", post_body);
78 request_->SetRequestContext(request_context_getter_);
79 request_->Start();
80 }
81
82 virtual const GURL& token_url() const OVERRIDE {
83 return token_url_;
84 }
85
86 virtual const std::string& token_scope() const OVERRIDE {
87 return token_scope_;
88 }
89
90 // URLFetcherDelegate interface.
91 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
92 DCHECK_EQ(request_.get(), source);
93 std::string shared_token = ProcessResponse();
94 on_token_validated_.Run(shared_token);
95 request_.reset();
96 }
97
98 private:
99 bool IsValidScope(const std::string& token_scope) {
100 // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc.
101 return token_scope == token_scope_;
102 }
103
104 static std::string CreateScope(const std::string& local_jid,
105 const std::string& remote_jid) {
106 char nonce_bytes[kNonceLength];
107 crypto::RandBytes(nonce_bytes, kNonceLength);
108 std::string nonce;
109 bool success = base::Base64Encode(nonce_bytes, &nonce);
110 DCHECK(success);
111 return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce;
112 }
113
114 std::string ProcessResponse() {
115 // Verify that we got a successful response.
116 int response = request_->GetResponseCode();
117 net::URLRequestStatus status = request_->GetStatus();
118 std::string data;
119 if (!status.is_success() || response != 200) {
120 LOG(ERROR)
121 << "Error " << response << " validating token: '" << data << "'";
122 return std::string();
123 }
124
125 // Decode the JSON data from the response.
126 request_->GetResponseAsString(&data);
127 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
128 DictionaryValue* dict;
129 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY ||
130 !value->GetAsDictionary(&dict)) {
131 LOG(ERROR) << "Invalid token validation response: '" << data << "'";
132 return std::string();
133 }
134
135 std::string token_scope;
136 dict->GetStringWithoutPathExpansion("scope", &token_scope);
137 if (!IsValidScope(token_scope)) {
138 LOG(ERROR) << "Invalid scope: '" << token_scope
139 << "', expected: '" << token_scope_ <<"'.";
140 return std::string();
141 }
142
143 std::string shared_secret;
144 // Everything is valid, so return the shared secret to the caller.
145 dict->GetStringWithoutPathExpansion("access_token", &shared_secret);
146 return shared_secret;
147 }
148
149 scoped_ptr<net::URLFetcher> request_;
150 GURL token_url_;
151 GURL token_validation_url_;
152 scoped_refptr<RsaKeyPair> key_pair_;
153 std::string token_scope_;
154 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
155 base::Callback<void(const std::string& shared_secret)> on_token_validated_;
156
157 DISALLOW_COPY_AND_ASSIGN(UrlFetcherTokenValidator);
158 };
159
160 UrlFetcherTokenValidatorFactory::UrlFetcherTokenValidatorFactory(
161 const GURL& token_url,
162 const GURL& token_validation_url,
163 scoped_refptr<RsaKeyPair> key_pair,
164 scoped_refptr<net::URLRequestContextGetter> request_context_getter)
165 : token_url_(token_url),
166 token_validation_url_(token_validation_url),
167 key_pair_(key_pair),
168 request_context_getter_(request_context_getter) {
169 }
170
171 UrlFetcherTokenValidatorFactory::~UrlFetcherTokenValidatorFactory() {
172 }
173
174 scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>
175 UrlFetcherTokenValidatorFactory::CreateTokenValidator(
176 const std::string& local_jid,
177 const std::string& remote_jid) {
178 return scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>(
179 new UrlFetcherTokenValidator(token_url_, token_validation_url_, key_pair_,
180 local_jid, remote_jid,
181 request_context_getter_));
182 }
183
184 bool UrlFetcherTokenValidatorFactory::IsEnabled() const {
185 return token_url_.is_valid() && token_validation_url_.is_valid() && key_pair_;
Sergey Ulanov 2013/04/05 20:28:34 If admin configured the policies but made a typo i
Wez 2013/04/05 22:46:12 Generally speaking we should disable the host enti
rmsousa 2013/04/06 00:37:25 I moved this logic to the host itself. At the time
186 }
187
188
189 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698