OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "google_apis/gaia/fake_gaia.h" | 5 #include "google_apis/gaia/fake_gaia.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" |
10 #include "base/file_util.h" | 12 #include "base/file_util.h" |
11 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
12 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
13 #include "base/logging.h" | 15 #include "base/logging.h" |
14 #include "base/path_service.h" | 16 #include "base/path_service.h" |
15 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/strings/stringprintf.h" |
18 #include "base/values.h" | 21 #include "base/values.h" |
19 #include "google_apis/gaia/gaia_urls.h" | 22 #include "google_apis/gaia/gaia_urls.h" |
20 #include "net/base/url_util.h" | 23 #include "net/base/url_util.h" |
21 #include "net/http/http_status_code.h" | 24 #include "net/http/http_status_code.h" |
22 #include "net/test/embedded_test_server/http_request.h" | 25 #include "net/test/embedded_test_server/http_request.h" |
23 #include "net/test/embedded_test_server/http_response.h" | 26 #include "net/test/embedded_test_server/http_response.h" |
24 #include "url/url_parse.h" | 27 #include "url/url_parse.h" |
25 | 28 |
| 29 #define REGISTER_RESPONSE_HANDLER(url, method) \ |
| 30 request_handlers_.insert(std::make_pair( \ |
| 31 url.path(), base::Bind(&FakeGaia::method, base::Unretained(this)))) |
| 32 |
| 33 #define REGISTER_PATH_RESPONSE_HANDLER(path, method) \ |
| 34 request_handlers_.insert(std::make_pair( \ |
| 35 path, base::Bind(&FakeGaia::method, base::Unretained(this)))) |
| 36 |
26 using namespace net::test_server; | 37 using namespace net::test_server; |
27 | 38 |
28 namespace { | 39 namespace { |
| 40 |
29 const base::FilePath::CharType kServiceLogin[] = | 41 const base::FilePath::CharType kServiceLogin[] = |
30 FILE_PATH_LITERAL("google_apis/test/service_login.html"); | 42 FILE_PATH_LITERAL("google_apis/test/service_login.html"); |
| 43 |
| 44 // OAuth2 Authentication header value prefix. |
| 45 const char kAuthHeaderBearer[] = "Bearer "; |
| 46 const char kAuthHeaderOAuth[] = "OAuth "; |
| 47 |
31 } | 48 } |
32 | 49 |
33 FakeGaia::AccessTokenInfo::AccessTokenInfo() | 50 FakeGaia::AccessTokenInfo::AccessTokenInfo() |
34 : expires_in(3600) {} | 51 : expires_in(3600) {} |
35 | 52 |
36 FakeGaia::AccessTokenInfo::~AccessTokenInfo() {} | 53 FakeGaia::AccessTokenInfo::~AccessTokenInfo() {} |
37 | 54 |
38 FakeGaia::FakeGaia() { | 55 FakeGaia::FakeGaia() { |
39 base::FilePath source_root_dir; | 56 base::FilePath source_root_dir; |
40 PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir); | 57 PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir); |
41 CHECK(base::ReadFileToString( | 58 CHECK(base::ReadFileToString( |
42 source_root_dir.Append(base::FilePath(kServiceLogin)), | 59 source_root_dir.Append(base::FilePath(kServiceLogin)), |
43 &service_login_response_)); | 60 &service_login_response_)); |
44 } | 61 } |
45 | 62 |
46 FakeGaia::~FakeGaia() {} | 63 FakeGaia::~FakeGaia() {} |
47 | 64 |
| 65 void FakeGaia::SetAuthTokens(const std::string& auth_code, |
| 66 const std::string& refresh_token, |
| 67 const std::string& access_token, |
| 68 const std::string& gaia_uber_token, |
| 69 const std::string& session_sid_cookie, |
| 70 const std::string& session_lsid_cookie) { |
| 71 fake_auth_code_ = auth_code; |
| 72 fake_refresh_token_ = refresh_token; |
| 73 fake_access_token_ = access_token; |
| 74 fake_gaia_uber_token_ = gaia_uber_token; |
| 75 fake_session_sid_cookie_ = session_sid_cookie; |
| 76 fake_session_lsid_cookie_ = session_lsid_cookie; |
| 77 } |
| 78 |
| 79 void FakeGaia::Initialize() { |
| 80 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); |
| 81 // Handles /ServiceLogin GAIA call. |
| 82 REGISTER_RESPONSE_HANDLER( |
| 83 gaia_urls->service_login_url(), HandleServiceLogin); |
| 84 |
| 85 // Handles /ServiceLoginAuth GAIA call. |
| 86 REGISTER_RESPONSE_HANDLER( |
| 87 gaia_urls->service_login_auth_url(), HandleServiceLoginAuth); |
| 88 |
| 89 // Handles /o/oauth2/programmatic_auth GAIA call. |
| 90 REGISTER_RESPONSE_HANDLER( |
| 91 gaia_urls->client_login_to_oauth2_url(), HandleProgramaticAuth); |
| 92 |
| 93 // Handles /o/oauth2/token GAIA call. |
| 94 REGISTER_RESPONSE_HANDLER( |
| 95 gaia_urls->oauth2_token_url(), HandleAuthToken); |
| 96 |
| 97 // Handles /OAuthLogin GAIA call. |
| 98 REGISTER_RESPONSE_HANDLER( |
| 99 gaia_urls->oauth1_login_url(), HandleOAuthLogin); |
| 100 |
| 101 // Handles /MergeSession GAIA call. |
| 102 REGISTER_RESPONSE_HANDLER( |
| 103 gaia_urls->merge_session_url(), HandleMergeSession); |
| 104 |
| 105 // Handles /oauth2/v2/IssueToken GAIA call. |
| 106 REGISTER_RESPONSE_HANDLER( |
| 107 gaia_urls->oauth2_issue_token_url(), HandleIssueToken); |
| 108 |
| 109 // Handles /oauth2/v2/tokeninfo GAIA call. |
| 110 REGISTER_RESPONSE_HANDLER( |
| 111 gaia_urls->oauth2_token_info_url(), HandleTokenInfo); |
| 112 |
| 113 // Handles /SSO GAIA call (not GAIA, made up for SAML tests). |
| 114 REGISTER_PATH_RESPONSE_HANDLER("/SSO", HandleSSO); |
| 115 } |
| 116 |
| 117 void FakeGaia::HandleProgramaticAuth( |
| 118 const HttpRequest& request, |
| 119 BasicHttpResponse* http_response) { |
| 120 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); |
| 121 std::string scope; |
| 122 if (!GetQueryParameter(request.content, "scope", &scope) || |
| 123 gaia_urls->oauth1_login_scope() != scope) { |
| 124 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 125 return; |
| 126 } |
| 127 |
| 128 std::string client_id; |
| 129 if (!GetQueryParameter(request.content, "client_id", &client_id) || |
| 130 gaia_urls->oauth2_chrome_client_id() != client_id) { |
| 131 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 132 return; |
| 133 } |
| 134 |
| 135 http_response->AddCustomHeader( |
| 136 "Set-Cookie", |
| 137 base::StringPrintf( |
| 138 "oauth_code=%s; Path=/o/GetOAuth2Token; Secure; HttpOnly;", |
| 139 fake_auth_code_.c_str())); |
| 140 http_response->set_code(net::HTTP_OK); |
| 141 http_response->set_content_type("text/html"); |
| 142 } |
| 143 |
| 144 void FakeGaia::HandleServiceLogin(const HttpRequest& request, |
| 145 BasicHttpResponse* http_response) { |
| 146 http_response->set_code(net::HTTP_OK); |
| 147 http_response->set_content(service_login_response_); |
| 148 http_response->set_content_type("text/html"); |
| 149 } |
| 150 |
| 151 void FakeGaia::HandleOAuthLogin(const HttpRequest& request, |
| 152 BasicHttpResponse* http_response) { |
| 153 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 154 std::string access_token; |
| 155 if (!GetAccessToken(request, kAuthHeaderOAuth, &access_token)) { |
| 156 LOG(ERROR) << "/OAuthLogin missing access token in the header"; |
| 157 return; |
| 158 } |
| 159 |
| 160 GURL request_url = GURL("http://localhost").Resolve(request.relative_url); |
| 161 std::string request_query = request_url.query(); |
| 162 |
| 163 std::string source; |
| 164 if (!GetQueryParameter(request_query, "source", &source)) { |
| 165 LOG(ERROR) << "Missing 'source' param in /OAuthLogin call"; |
| 166 return; |
| 167 } |
| 168 |
| 169 std::string issue_uberauth; |
| 170 if (GetQueryParameter(request_query, "issueuberauth", &issue_uberauth) && |
| 171 issue_uberauth == "1") { |
| 172 http_response->set_content(fake_gaia_uber_token_); |
| 173 http_response->set_code(net::HTTP_OK); |
| 174 // Issue GAIA uber token. |
| 175 } else { |
| 176 LOG(FATAL) << "/OAuthLogin for SID/LSID is not supported"; |
| 177 } |
| 178 } |
| 179 |
| 180 void FakeGaia::HandleMergeSession(const HttpRequest& request, |
| 181 BasicHttpResponse* http_response) { |
| 182 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 183 |
| 184 std::string uber_token; |
| 185 if (!GetQueryParameter(request.content, "uberauth", &uber_token) || |
| 186 uber_token != fake_gaia_uber_token_) { |
| 187 LOG(ERROR) << "Missing or invalid 'uberauth' param in /MergeSession call"; |
| 188 return; |
| 189 } |
| 190 |
| 191 std::string continue_url; |
| 192 if (!GetQueryParameter(request.content, "continue", &continue_url)) { |
| 193 LOG(ERROR) << "Missing or invalid 'continue' param in /MergeSession call"; |
| 194 return; |
| 195 } |
| 196 |
| 197 std::string source; |
| 198 if (!GetQueryParameter(request.content, "source", &source)) { |
| 199 LOG(ERROR) << "Missing or invalid 'source' param in /MergeSession call"; |
| 200 return; |
| 201 } |
| 202 |
| 203 http_response->AddCustomHeader( |
| 204 "Set-Cookie", |
| 205 base::StringPrintf( |
| 206 "SID=%s; LSID=%s; Path=/; Secure; HttpOnly;", |
| 207 fake_session_sid_cookie_.c_str(), |
| 208 fake_session_lsid_cookie_.c_str())); |
| 209 // TODO(zelidrag): Not used now. |
| 210 http_response->set_content("OK"); |
| 211 http_response->set_code(net::HTTP_OK); |
| 212 } |
| 213 |
| 214 |
| 215 void FakeGaia::HandleServiceLoginAuth(const HttpRequest& request, |
| 216 BasicHttpResponse* http_response) { |
| 217 std::string continue_url = |
| 218 GaiaUrls::GetInstance()->service_login_url().spec(); |
| 219 GetQueryParameter(request.content, "continue", &continue_url); |
| 220 |
| 221 std::string redirect_url = continue_url; |
| 222 |
| 223 std::string email; |
| 224 if (GetQueryParameter(request.content, "Email", &email) && |
| 225 saml_account_idp_map_.find(email) != saml_account_idp_map_.end()) { |
| 226 GURL url(saml_account_idp_map_[email]); |
| 227 url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request"); |
| 228 url = net::AppendQueryParameter(url, "RelayState", continue_url); |
| 229 redirect_url = url.spec(); |
| 230 } |
| 231 |
| 232 http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); |
| 233 http_response->AddCustomHeader("Location", redirect_url); |
| 234 } |
| 235 |
| 236 void FakeGaia::HandleSSO(const HttpRequest& request, |
| 237 BasicHttpResponse* http_response) { |
| 238 std::string relay_state; |
| 239 GetQueryParameter(request.content, "RelayState", &relay_state); |
| 240 std::string redirect_url = relay_state; |
| 241 http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); |
| 242 http_response->AddCustomHeader("Location", redirect_url); |
| 243 } |
| 244 |
| 245 void FakeGaia::HandleAuthToken(const HttpRequest& request, |
| 246 BasicHttpResponse* http_response) { |
| 247 std::string grant_type; |
| 248 std::string refresh_token; |
| 249 std::string client_id; |
| 250 std::string scope; |
| 251 std::string auth_code; |
| 252 const AccessTokenInfo* token_info = NULL; |
| 253 GetQueryParameter(request.content, "scope", &scope); |
| 254 |
| 255 if (!GetQueryParameter(request.content, "grant_type", &grant_type)) { |
| 256 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 257 LOG(ERROR) << "No 'grant_type' param in /o/oauth2/token"; |
| 258 return; |
| 259 } |
| 260 |
| 261 if (grant_type == "authorization_code") { |
| 262 if (!GetQueryParameter(request.content, "code", &auth_code) || |
| 263 auth_code != fake_auth_code_) { |
| 264 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 265 LOG(ERROR) << "No 'code' param in /o/oauth2/token"; |
| 266 return; |
| 267 } |
| 268 |
| 269 if (GaiaUrls::GetInstance()->oauth1_login_scope() != scope) { |
| 270 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 271 LOG(ERROR) << "Invalid scope for /o/oauth2/token - " << scope; |
| 272 return; |
| 273 } |
| 274 |
| 275 base::DictionaryValue response_dict; |
| 276 response_dict.SetString("refresh_token", fake_refresh_token_); |
| 277 response_dict.SetString("access_token", fake_access_token_); |
| 278 response_dict.SetInteger("expires_in", 3600); |
| 279 FormatJSONResponse(response_dict, http_response); |
| 280 } else if (GetQueryParameter(request.content, |
| 281 "refresh_token", |
| 282 &refresh_token) && |
| 283 GetQueryParameter(request.content, |
| 284 "client_id", |
| 285 &client_id) && |
| 286 (token_info = FindAccessTokenInfo(refresh_token, |
| 287 client_id, |
| 288 scope))) { |
| 289 base::DictionaryValue response_dict; |
| 290 response_dict.SetString("access_token", token_info->token); |
| 291 response_dict.SetInteger("expires_in", 3600); |
| 292 FormatJSONResponse(response_dict, http_response); |
| 293 } else { |
| 294 LOG(ERROR) << "Bad request for /o/oauth2/token - " |
| 295 << "refresh_token = " << refresh_token |
| 296 << ", scope = " << scope |
| 297 << ", client_id = " << client_id; |
| 298 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 299 } |
| 300 } |
| 301 |
| 302 void FakeGaia::HandleTokenInfo(const HttpRequest& request, |
| 303 BasicHttpResponse* http_response) { |
| 304 const AccessTokenInfo* token_info = NULL; |
| 305 std::string access_token; |
| 306 if (GetQueryParameter(request.content, "access_token", &access_token)) { |
| 307 for (AccessTokenInfoMap::const_iterator entry( |
| 308 access_token_info_map_.begin()); |
| 309 entry != access_token_info_map_.end(); |
| 310 ++entry) { |
| 311 if (entry->second.token == access_token) { |
| 312 token_info = &(entry->second); |
| 313 break; |
| 314 } |
| 315 } |
| 316 } |
| 317 |
| 318 if (token_info) { |
| 319 base::DictionaryValue response_dict; |
| 320 response_dict.SetString("issued_to", token_info->issued_to); |
| 321 response_dict.SetString("audience", token_info->audience); |
| 322 response_dict.SetString("user_id", token_info->user_id); |
| 323 std::vector<std::string> scope_vector(token_info->scopes.begin(), |
| 324 token_info->scopes.end()); |
| 325 response_dict.SetString("scope", JoinString(scope_vector, " ")); |
| 326 response_dict.SetInteger("expires_in", token_info->expires_in); |
| 327 response_dict.SetString("email", token_info->email); |
| 328 FormatJSONResponse(response_dict, http_response); |
| 329 } else { |
| 330 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 331 } |
| 332 } |
| 333 |
| 334 void FakeGaia::HandleIssueToken(const HttpRequest& request, |
| 335 BasicHttpResponse* http_response) { |
| 336 std::string access_token; |
| 337 std::string scope; |
| 338 std::string client_id; |
| 339 const AccessTokenInfo* token_info = NULL; |
| 340 if (GetAccessToken(request, kAuthHeaderBearer, &access_token) && |
| 341 GetQueryParameter(request.content, "scope", &scope) && |
| 342 GetQueryParameter(request.content, "client_id", &client_id) && |
| 343 (token_info = FindAccessTokenInfo(access_token, client_id, scope))) { |
| 344 base::DictionaryValue response_dict; |
| 345 response_dict.SetString("issueAdvice", "auto"); |
| 346 response_dict.SetString("expiresIn", |
| 347 base::IntToString(token_info->expires_in)); |
| 348 response_dict.SetString("token", token_info->token); |
| 349 FormatJSONResponse(response_dict, http_response); |
| 350 } else { |
| 351 http_response->set_code(net::HTTP_BAD_REQUEST); |
| 352 } |
| 353 } |
| 354 |
| 355 |
48 scoped_ptr<HttpResponse> FakeGaia::HandleRequest(const HttpRequest& request) { | 356 scoped_ptr<HttpResponse> FakeGaia::HandleRequest(const HttpRequest& request) { |
49 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); | |
50 | |
51 // The scheme and host of the URL is actually not important but required to | 357 // The scheme and host of the URL is actually not important but required to |
52 // get a valid GURL in order to parse |request.relative_url|. | 358 // get a valid GURL in order to parse |request.relative_url|. |
53 GURL request_url = GURL("http://localhost").Resolve(request.relative_url); | 359 GURL request_url = GURL("http://localhost").Resolve(request.relative_url); |
54 std::string request_path = request_url.path(); | 360 std::string request_path = request_url.path(); |
55 | |
56 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); | 361 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); |
57 if (request_path == gaia_urls->service_login_url().path()) { | 362 RequestHandlerMap::iterator iter = request_handlers_.find(request_path); |
58 http_response->set_code(net::HTTP_OK); | 363 if (iter != request_handlers_.end()) { |
59 http_response->set_content(service_login_response_); | 364 LOG(WARNING) << "Serving request " << request_path; |
60 http_response->set_content_type("text/html"); | 365 iter->second.Run(request, http_response.get()); |
61 } else if (request_path == gaia_urls->service_login_auth_url().path()) { | 366 } else { |
62 std::string continue_url = gaia_urls->service_login_url().spec(); | 367 LOG(ERROR) << "Unhandled request " << request_path; |
63 GetQueryParameter(request.content, "continue", &continue_url); | 368 return scoped_ptr<HttpResponse>(); // Request not understood. |
64 std::string redirect_url = continue_url; | |
65 | |
66 std::string email; | |
67 if (GetQueryParameter(request.content, "Email", &email) && | |
68 saml_account_idp_map_.find(email) != saml_account_idp_map_.end()) { | |
69 GURL url(saml_account_idp_map_[email]); | |
70 url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request"); | |
71 url = net::AppendQueryParameter(url, "RelayState", continue_url); | |
72 redirect_url = url.spec(); | |
73 } | |
74 | |
75 http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); | |
76 http_response->AddCustomHeader("Location", redirect_url); | |
77 } else if (request_path == gaia_urls->oauth2_token_url().path()) { | |
78 std::string refresh_token; | |
79 std::string client_id; | |
80 std::string scope; | |
81 const AccessTokenInfo* token_info = NULL; | |
82 GetQueryParameter(request.content, "scope", &scope); | |
83 if (GetQueryParameter(request.content, "refresh_token", &refresh_token) && | |
84 GetQueryParameter(request.content, "client_id", &client_id) && | |
85 (token_info = GetAccessTokenInfo(refresh_token, client_id, scope))) { | |
86 base::DictionaryValue response_dict; | |
87 response_dict.SetString("access_token", token_info->token); | |
88 response_dict.SetInteger("expires_in", 3600); | |
89 FormatJSONResponse(response_dict, http_response.get()); | |
90 } else { | |
91 http_response->set_code(net::HTTP_BAD_REQUEST); | |
92 } | |
93 } else if (request_path == gaia_urls->oauth2_token_info_url().path()) { | |
94 const AccessTokenInfo* token_info = NULL; | |
95 std::string access_token; | |
96 if (GetQueryParameter(request.content, "access_token", &access_token)) { | |
97 for (AccessTokenInfoMap::const_iterator entry( | |
98 access_token_info_map_.begin()); | |
99 entry != access_token_info_map_.end(); | |
100 ++entry) { | |
101 if (entry->second.token == access_token) { | |
102 token_info = &(entry->second); | |
103 break; | |
104 } | |
105 } | |
106 } | |
107 | |
108 if (token_info) { | |
109 base::DictionaryValue response_dict; | |
110 response_dict.SetString("issued_to", token_info->issued_to); | |
111 response_dict.SetString("audience", token_info->audience); | |
112 response_dict.SetString("user_id", token_info->user_id); | |
113 std::vector<std::string> scope_vector(token_info->scopes.begin(), | |
114 token_info->scopes.end()); | |
115 response_dict.SetString("scope", JoinString(scope_vector, " ")); | |
116 response_dict.SetInteger("expires_in", token_info->expires_in); | |
117 response_dict.SetString("email", token_info->email); | |
118 FormatJSONResponse(response_dict, http_response.get()); | |
119 } else { | |
120 http_response->set_code(net::HTTP_BAD_REQUEST); | |
121 } | |
122 } else if (request_path == gaia_urls->oauth2_issue_token_url().path()) { | |
123 std::string access_token; | |
124 std::map<std::string, std::string>::const_iterator auth_header_entry = | |
125 request.headers.find("Authorization"); | |
126 if (auth_header_entry != request.headers.end()) { | |
127 if (StartsWithASCII(auth_header_entry->second, "Bearer ", true)) | |
128 access_token = auth_header_entry->second.substr(7); | |
129 } | |
130 | |
131 std::string scope; | |
132 std::string client_id; | |
133 const AccessTokenInfo* token_info = NULL; | |
134 if (GetQueryParameter(request.content, "scope", &scope) && | |
135 GetQueryParameter(request.content, "client_id", &client_id) && | |
136 (token_info = GetAccessTokenInfo(access_token, client_id, scope))) { | |
137 base::DictionaryValue response_dict; | |
138 response_dict.SetString("issueAdvice", "auto"); | |
139 response_dict.SetString("expiresIn", | |
140 base::IntToString(token_info->expires_in)); | |
141 response_dict.SetString("token", token_info->token); | |
142 FormatJSONResponse(response_dict, http_response.get()); | |
143 } else { | |
144 http_response->set_code(net::HTTP_BAD_REQUEST); | |
145 } | |
146 } else if (request_path == "/SSO") { | |
147 std::string relay_state; | |
148 GetQueryParameter(request.content, "RelayState", &relay_state); | |
149 std::string redirect_url = relay_state; | |
150 http_response->set_code(net::HTTP_TEMPORARY_REDIRECT); | |
151 http_response->AddCustomHeader("Location", redirect_url); | |
152 } else { | |
153 // Request not understood. | |
154 return scoped_ptr<HttpResponse>(); | |
155 } | 369 } |
156 | 370 |
157 return http_response.PassAs<HttpResponse>(); | 371 return http_response.PassAs<HttpResponse>(); |
158 } | 372 } |
159 | 373 |
160 void FakeGaia::IssueOAuthToken(const std::string& auth_token, | 374 void FakeGaia::IssueOAuthToken(const std::string& auth_token, |
161 const AccessTokenInfo& token_info) { | 375 const AccessTokenInfo& token_info) { |
162 access_token_info_map_.insert(std::make_pair(auth_token, token_info)); | 376 access_token_info_map_.insert(std::make_pair(auth_token, token_info)); |
163 } | 377 } |
164 | 378 |
165 void FakeGaia::RegisterSamlUser(const std::string& account_id, | 379 void FakeGaia::RegisterSamlUser(const std::string& account_id, |
166 const GURL& saml_idp) { | 380 const GURL& saml_idp) { |
167 saml_account_idp_map_[account_id] = saml_idp; | 381 saml_account_idp_map_[account_id] = saml_idp; |
168 } | 382 } |
169 | 383 |
170 // static | |
171 bool FakeGaia::GetQueryParameter(const std::string& query, | |
172 const std::string& key, | |
173 std::string* value) { | |
174 // Name and scheme actually don't matter, but are required to get a valid URL | |
175 // for parsing. | |
176 GURL query_url("http://localhost?" + query); | |
177 return net::GetValueForKeyInQuery(query_url, key, value); | |
178 } | |
179 | |
180 void FakeGaia::FormatJSONResponse(const base::DictionaryValue& response_dict, | 384 void FakeGaia::FormatJSONResponse(const base::DictionaryValue& response_dict, |
181 BasicHttpResponse* http_response) { | 385 BasicHttpResponse* http_response) { |
182 std::string response_json; | 386 std::string response_json; |
183 base::JSONWriter::Write(&response_dict, &response_json); | 387 base::JSONWriter::Write(&response_dict, &response_json); |
184 http_response->set_content(response_json); | 388 http_response->set_content(response_json); |
185 http_response->set_code(net::HTTP_OK); | 389 http_response->set_code(net::HTTP_OK); |
186 } | 390 } |
187 | 391 |
188 const FakeGaia::AccessTokenInfo* FakeGaia::GetAccessTokenInfo( | 392 const FakeGaia::AccessTokenInfo* FakeGaia::FindAccessTokenInfo( |
189 const std::string& auth_token, | 393 const std::string& auth_token, |
190 const std::string& client_id, | 394 const std::string& client_id, |
191 const std::string& scope_string) const { | 395 const std::string& scope_string) const { |
192 if (auth_token.empty() || client_id.empty()) | 396 if (auth_token.empty() || client_id.empty()) |
193 return NULL; | 397 return NULL; |
194 | 398 |
195 std::vector<std::string> scope_list; | 399 std::vector<std::string> scope_list; |
196 base::SplitString(scope_string, ' ', &scope_list); | 400 base::SplitString(scope_string, ' ', &scope_list); |
197 ScopeSet scopes(scope_list.begin(), scope_list.end()); | 401 ScopeSet scopes(scope_list.begin(), scope_list.end()); |
198 | 402 |
199 for (AccessTokenInfoMap::const_iterator entry( | 403 for (AccessTokenInfoMap::const_iterator entry( |
200 access_token_info_map_.lower_bound(auth_token)); | 404 access_token_info_map_.lower_bound(auth_token)); |
201 entry != access_token_info_map_.upper_bound(auth_token); | 405 entry != access_token_info_map_.upper_bound(auth_token); |
202 ++entry) { | 406 ++entry) { |
203 if (entry->second.audience == client_id && | 407 if (entry->second.audience == client_id && |
204 (scope_string.empty() || entry->second.scopes == scopes)) { | 408 (scope_string.empty() || entry->second.scopes == scopes)) { |
205 return &(entry->second); | 409 return &(entry->second); |
206 } | 410 } |
207 } | 411 } |
208 | 412 |
209 return NULL; | 413 return NULL; |
210 } | 414 } |
| 415 |
| 416 // static |
| 417 bool FakeGaia::GetQueryParameter(const std::string& query, |
| 418 const std::string& key, |
| 419 std::string* value) { |
| 420 // Name and scheme actually don't matter, but are required to get a valid URL |
| 421 // for parsing. |
| 422 GURL query_url("http://localhost?" + query); |
| 423 return net::GetValueForKeyInQuery(query_url, key, value); |
| 424 } |
| 425 |
| 426 // static |
| 427 bool FakeGaia::GetAccessToken(const HttpRequest& request, |
| 428 const char* auth_token_prefix, |
| 429 std::string* access_token) { |
| 430 std::map<std::string, std::string>::const_iterator auth_header_entry = |
| 431 request.headers.find("Authorization"); |
| 432 if (auth_header_entry != request.headers.end()) { |
| 433 if (StartsWithASCII(auth_header_entry->second, auth_token_prefix, true)) { |
| 434 *access_token = auth_header_entry->second.substr( |
| 435 strlen(auth_token_prefix)); |
| 436 return true; |
| 437 } |
| 438 } |
| 439 |
| 440 return false; |
| 441 } |
OLD | NEW |