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

Side by Side Diff: google_apis/gaia/gaia_auth_fetcher.cc

Issue 973953002: Implement the calls to GAIA for the IDP IFrame protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « google_apis/gaia/gaia_auth_fetcher.h ('k') | google_apis/gaia/gaia_urls.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/gaia_auth_fetcher.h" 5 #include "google_apis/gaia/gaia_auth_fetcher.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 23 matching lines...) Expand all
34 static bool CookiePartsContains(const std::vector<std::string>& parts, 34 static bool CookiePartsContains(const std::vector<std::string>& parts,
35 const char* part) { 35 const char* part) {
36 for (std::vector<std::string>::const_iterator it = parts.begin(); 36 for (std::vector<std::string>::const_iterator it = parts.begin();
37 it != parts.end(); ++it) { 37 it != parts.end(); ++it) {
38 if (LowerCaseEqualsASCII(*it, part)) 38 if (LowerCaseEqualsASCII(*it, part))
39 return true; 39 return true;
40 } 40 }
41 return false; 41 return false;
42 } 42 }
43 43
44 bool ExtractOAuth2TokenPairResponse(base::DictionaryValue* dict, 44 // From the JSON string |data|, extract the |access_token| and |expires_in_secs|
45 // both of which must exist. If the |refresh_token| is non-NULL, then it also
46 // must exist and is extraced; if it's NULL, then no extraction is attempted.
47 bool ExtractOAuth2TokenPairResponse(const std::string& data,
45 std::string* refresh_token, 48 std::string* refresh_token,
46 std::string* access_token, 49 std::string* access_token,
47 int* expires_in_secs) { 50 int* expires_in_secs) {
48 DCHECK(refresh_token);
49 DCHECK(access_token); 51 DCHECK(access_token);
50 DCHECK(expires_in_secs); 52 DCHECK(expires_in_secs);
51 53
52 if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token) || 54 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
53 !dict->GetStringWithoutPathExpansion("access_token", access_token) || 55 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY)
56 return false;
57
58 base::DictionaryValue* dict =
59 static_cast<base::DictionaryValue*>(value.get());
60
61 if (!dict->GetStringWithoutPathExpansion("access_token", access_token) ||
54 !dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) { 62 !dict->GetIntegerWithoutPathExpansion("expires_in", expires_in_secs)) {
55 return false; 63 return false;
56 } 64 }
57 65
66 // Refresh token may not be required.
67 if (refresh_token) {
68 if (!dict->GetStringWithoutPathExpansion("refresh_token", refresh_token))
69 return false;
70 }
58 return true; 71 return true;
59 } 72 }
60 73
74 const char* kListIdpServiceRequested = "list_idp";
75 const char* kGetTokenResponseRequested = "get_token";
76
61 } // namespace 77 } // namespace
62 78
63 // TODO(chron): Add sourceless version of this formatter. 79 // TODO(chron): Add sourceless version of this formatter.
64 // static 80 // static
65 const char GaiaAuthFetcher::kClientLoginFormat[] = 81 const char GaiaAuthFetcher::kClientLoginFormat[] =
66 "Email=%s&" 82 "Email=%s&"
67 "Passwd=%s&" 83 "Passwd=%s&"
68 "PersistentCookie=%s&" 84 "PersistentCookie=%s&"
69 "accountType=%s&" 85 "accountType=%s&"
70 "source=%s&" 86 "source=%s&"
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), 203 merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()),
188 uberauth_token_gurl_(GaiaUrls::GetInstance()->oauth1_login_url().Resolve( 204 uberauth_token_gurl_(GaiaUrls::GetInstance()->oauth1_login_url().Resolve(
189 base::StringPrintf(kUberAuthTokenURLFormat, source.c_str()))), 205 base::StringPrintf(kUberAuthTokenURLFormat, source.c_str()))),
190 oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()), 206 oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()),
191 list_accounts_gurl_( 207 list_accounts_gurl_(
192 GaiaUrls::GetInstance()->ListAccountsURLWithSource(source)), 208 GaiaUrls::GetInstance()->ListAccountsURLWithSource(source)),
193 get_check_connection_info_url_( 209 get_check_connection_info_url_(
194 GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(source)), 210 GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(source)),
195 client_login_to_oauth2_gurl_( 211 client_login_to_oauth2_gurl_(
196 GaiaUrls::GetInstance()->client_login_to_oauth2_url()), 212 GaiaUrls::GetInstance()->client_login_to_oauth2_url()),
213 oauth2_iframe_url_(GaiaUrls::GetInstance()->oauth2_iframe_url()),
197 fetch_pending_(false) {} 214 fetch_pending_(false) {}
198 215
199 GaiaAuthFetcher::~GaiaAuthFetcher() {} 216 GaiaAuthFetcher::~GaiaAuthFetcher() {}
200 217
201 bool GaiaAuthFetcher::HasPendingFetch() { 218 bool GaiaAuthFetcher::HasPendingFetch() {
202 return fetch_pending_; 219 return fetch_pending_;
203 } 220 }
204 221
205 void GaiaAuthFetcher::CancelRequest() { 222 void GaiaAuthFetcher::CancelRequest() {
206 fetcher_.reset(); 223 fetcher_.reset();
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service, 432 std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service,
416 const std::string& source) { 433 const std::string& source) {
417 std::string encoded_service = net::EscapeUrlEncodedData(service, true); 434 std::string encoded_service = net::EscapeUrlEncodedData(service, true);
418 std::string encoded_source = net::EscapeUrlEncodedData(source, true); 435 std::string encoded_source = net::EscapeUrlEncodedData(source, true);
419 return base::StringPrintf(kOAuthLoginFormat, 436 return base::StringPrintf(kOAuthLoginFormat,
420 encoded_service.c_str(), 437 encoded_service.c_str(),
421 encoded_source.c_str()); 438 encoded_source.c_str());
422 } 439 }
423 440
424 // static 441 // static
442 std::string GaiaAuthFetcher::MakeListIDPSessionsBody(
443 const std::string& scopes,
444 const std::string& domain) {
445 static const char getTokenResponseBodyFormat[] =
446 "action=listSessions&"
447 "client_id=%s&"
448 "e=3100087&" // temporarily enable the experiment.
449 "ss_domain=%s&"
guibinkong 2015/03/09 18:26:50 remove ss_domain, since ss_domain is same as origi
Mike Lerman 2015/03/09 18:59:56 Done.
450 "origin=%s&"
451 "scope=%s";
452 std::string encoded_client_id = net::EscapeUrlEncodedData(
453 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true);
454 return base::StringPrintf(getTokenResponseBodyFormat,
455 encoded_client_id.c_str(),
456 domain.c_str(),
457 domain.c_str(),
458 scopes.c_str());
459 }
460
461 std::string GaiaAuthFetcher::MakeGetTokenResponseBody(
462 const std::string& scopes,
463 const std::string& domain,
464 const std::string& login_hint) {
465 static const char getTokenResponseBodyFormat[] =
466 "action=issueToken&"
467 "client_id=%s&"
468 "login_hint=%s&"
469 "origin=%s&"
470 "e=3100087&" // temporarily enable the experiment.
471 "response_type=token+id_token&"
guibinkong 2015/03/09 18:26:50 remove '+id_token', since you don't need the ID To
Mike Lerman 2015/03/09 18:59:56 Done.
472 "scope=%s";
473 std::string encoded_client_id = net::EscapeUrlEncodedData(
474 GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true);
475 return base::StringPrintf(getTokenResponseBodyFormat,
476 encoded_client_id.c_str(),
477 login_hint.c_str(),
478 domain.c_str(),
479 scopes.c_str());
480 }
481
482 // static
425 void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, 483 void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data,
426 std::string* error, 484 std::string* error,
427 std::string* error_url, 485 std::string* error_url,
428 std::string* captcha_url, 486 std::string* captcha_url,
429 std::string* captcha_token) { 487 std::string* captcha_token) {
430 using std::vector; 488 using std::vector;
431 using std::pair; 489 using std::pair;
432 using std::string; 490 using std::string;
433 491
434 vector<pair<string, string> > tokens; 492 vector<pair<string, string> > tokens;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 if (StartsWithASCII( 535 if (StartsWithASCII(
478 part, kClientLoginToOAuth2CookiePartCodePrefix, false)) { 536 part, kClientLoginToOAuth2CookiePartCodePrefix, false)) {
479 auth_code->assign(part.substr( 537 auth_code->assign(part.substr(
480 kClientLoginToOAuth2CookiePartCodePrefixLength)); 538 kClientLoginToOAuth2CookiePartCodePrefixLength));
481 return true; 539 return true;
482 } 540 }
483 } 541 }
484 return false; 542 return false;
485 } 543 }
486 544
545 // static
546 bool GaiaAuthFetcher::ParseListIdpSessionsResponse(const std::string& data,
547 std::string* login_hint) {
548 DCHECK(login_hint);
549
550 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
551 if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY)
552 return false;
553
554 base::DictionaryValue* dict =
555 static_cast<base::DictionaryValue*>(value.get());
556
557 base::ListValue* sessionsList;
558 if (!dict->GetList("sessions", &sessionsList))
559 return false;
560
561 // Find the first login_hint present in any session.
562 for (base::ListValue::iterator iter = sessionsList->begin();
563 iter != sessionsList->end();
564 iter++) {
565 base::DictionaryValue* sessionDictionary;
566 if (!(*iter)->GetAsDictionary(&sessionDictionary))
567 continue;
568
569 if (sessionDictionary->GetString("login_hint", login_hint))
570 break;
571 }
572
573 if (login_hint->empty())
574 return false;
575 return true;
576 }
577
487 void GaiaAuthFetcher::StartClientLogin( 578 void GaiaAuthFetcher::StartClientLogin(
488 const std::string& username, 579 const std::string& username,
489 const std::string& password, 580 const std::string& password,
490 const char* const service, 581 const char* const service,
491 const std::string& login_token, 582 const std::string& login_token,
492 const std::string& login_captcha, 583 const std::string& login_captcha,
493 HostedAccountsSetting allow_hosted_accounts) { 584 HostedAccountsSetting allow_hosted_accounts) {
494 585
495 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; 586 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
496 587
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 fetcher_.reset(CreateGaiaFetcher(getter_, 808 fetcher_.reset(CreateGaiaFetcher(getter_,
718 std::string(), 809 std::string(),
719 std::string(), 810 std::string(),
720 get_check_connection_info_url_, 811 get_check_connection_info_url_,
721 kLoadFlagsIgnoreCookies, 812 kLoadFlagsIgnoreCookies,
722 this)); 813 this));
723 fetch_pending_ = true; 814 fetch_pending_ = true;
724 fetcher_->Start(); 815 fetcher_->Start();
725 } 816 }
726 817
818 void GaiaAuthFetcher::StartListIDPSessions(const std::string& scopes,
819 const std::string& domain) {
820 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
821
822 request_body_ = MakeListIDPSessionsBody(scopes, domain);
823 fetcher_.reset(CreateGaiaFetcher(getter_,
824 request_body_,
825 std::string(),
826 oauth2_iframe_url_,
827 net::LOAD_NORMAL,
828 this));
829 requested_service_ = kListIdpServiceRequested;
830 fetch_pending_ = true;
831 fetcher_->Start();
832 }
833
834 void GaiaAuthFetcher::StartGetTokenResponse(const std::string& scopes,
835 const std::string& domain,
836 const std::string& login_hint) {
837 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
838
839 request_body_ = MakeGetTokenResponseBody(scopes, domain, login_hint);
840 fetcher_.reset(CreateGaiaFetcher(getter_,
841 request_body_,
842 std::string(),
843 oauth2_iframe_url_,
844 net::LOAD_NORMAL,
845 this));
846
847 requested_service_ = kGetTokenResponseRequested;
848 fetch_pending_ = true;
849 fetcher_->Start();
850 }
851
727 // static 852 // static
728 GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( 853 GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError(
729 const std::string& data, 854 const std::string& data,
730 const net::URLRequestStatus& status) { 855 const net::URLRequestStatus& status) {
731 if (!status.is_success()) { 856 if (!status.is_success()) {
732 if (status.status() == net::URLRequestStatus::CANCELED) { 857 if (status.status() == net::URLRequestStatus::CANCELED) {
733 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); 858 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
734 } 859 }
735 DLOG(WARNING) << "Could not reach Google Accounts servers: errno " 860 DLOG(WARNING) << "Could not reach Google Accounts servers: errno "
736 << status.error(); 861 << status.error();
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 void GaiaAuthFetcher::OnOAuth2TokenPairFetched( 952 void GaiaAuthFetcher::OnOAuth2TokenPairFetched(
828 const std::string& data, 953 const std::string& data,
829 const net::URLRequestStatus& status, 954 const net::URLRequestStatus& status,
830 int response_code) { 955 int response_code) {
831 std::string refresh_token; 956 std::string refresh_token;
832 std::string access_token; 957 std::string access_token;
833 int expires_in_secs = 0; 958 int expires_in_secs = 0;
834 959
835 bool success = false; 960 bool success = false;
836 if (status.is_success() && response_code == net::HTTP_OK) { 961 if (status.is_success() && response_code == net::HTTP_OK) {
837 scoped_ptr<base::Value> value(base::JSONReader::Read(data)); 962 success = ExtractOAuth2TokenPairResponse(data, &refresh_token,
838 if (value.get() && value->GetType() == base::Value::TYPE_DICTIONARY) {
839 base::DictionaryValue* dict =
840 static_cast<base::DictionaryValue*>(value.get());
841 success = ExtractOAuth2TokenPairResponse(dict, &refresh_token,
842 &access_token, &expires_in_secs); 963 &access_token, &expires_in_secs);
843 }
844 } 964 }
845 965
846 if (success) { 966 if (success) {
847 consumer_->OnClientOAuthSuccess( 967 consumer_->OnClientOAuthSuccess(
848 GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token, 968 GaiaAuthConsumer::ClientOAuthResult(refresh_token, access_token,
849 expires_in_secs)); 969 expires_in_secs));
850 } else { 970 } else {
851 consumer_->OnClientOAuthFailure(GenerateAuthError(data, status)); 971 consumer_->OnClientOAuthFailure(GenerateAuthError(data, status));
852 } 972 }
853 } 973 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 const std::string& data, 1047 const std::string& data,
928 const net::URLRequestStatus& status, 1048 const net::URLRequestStatus& status,
929 int response_code) { 1049 int response_code) {
930 if (status.is_success() && response_code == net::HTTP_OK) { 1050 if (status.is_success() && response_code == net::HTTP_OK) {
931 consumer_->OnGetCheckConnectionInfoSuccess(data); 1051 consumer_->OnGetCheckConnectionInfoSuccess(data);
932 } else { 1052 } else {
933 consumer_->OnGetCheckConnectionInfoError(GenerateAuthError(data, status)); 1053 consumer_->OnGetCheckConnectionInfoError(GenerateAuthError(data, status));
934 } 1054 }
935 } 1055 }
936 1056
1057 void GaiaAuthFetcher::OnListIdpSessionsFetched(
1058 const std::string& data,
1059 const net::URLRequestStatus& status,
1060 int response_code) {
1061 if (status.is_success() && response_code == net::HTTP_OK) {
1062 DVLOG(1) << "ListIdpSessions successful!";
1063 std::string login_hint;
1064 ParseListIdpSessionsResponse(data, &login_hint);
1065 consumer_->OnListIdpSessionsSuccess(login_hint);
1066 } else {
1067 consumer_->OnListIdpSessionsError(GenerateAuthError(data, status));
1068 }
1069 }
1070
1071 void GaiaAuthFetcher::OnGetTokenResponseFetched(
1072 const std::string& data,
1073 const net::URLRequestStatus& status,
1074 int response_code) {
1075 std::string access_token;
1076 int expires_in_secs = 0;
1077 bool success = false;
1078 if (status.is_success() && response_code == net::HTTP_OK) {
1079 DVLOG(1) << "GetTokenResponse successful!";
1080 success = ExtractOAuth2TokenPairResponse(data, NULL,
1081 &access_token, &expires_in_secs);
1082 }
1083
1084 if (success) {
1085 consumer_->OnGetTokenResponseSuccess(
1086 GaiaAuthConsumer::ClientOAuthResult(std::string(), access_token,
1087 expires_in_secs));
1088 } else {
1089 consumer_->OnGetTokenResponseError(GenerateAuthError(data, status));
1090 }
1091 }
1092
937 void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 1093 void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
938 fetch_pending_ = false; 1094 fetch_pending_ = false;
939 // Some of the GAIA requests perform redirects, which results in the final 1095 // Some of the GAIA requests perform redirects, which results in the final
940 // URL of the fetcher not being the original URL requested. Therefore use 1096 // URL of the fetcher not being the original URL requested. Therefore use
941 // the original URL when determining which OnXXX function to call. 1097 // the original URL when determining which OnXXX function to call.
942 const GURL& url = source->GetOriginalURL(); 1098 const GURL& url = source->GetOriginalURL();
943 const net::URLRequestStatus& status = source->GetStatus(); 1099 const net::URLRequestStatus& status = source->GetStatus();
944 int response_code = source->GetResponseCode(); 1100 int response_code = source->GetResponseCode();
945 std::string data; 1101 std::string data;
946 source->GetResponseAsString(&data); 1102 source->GetResponseAsString(&data);
(...skipping 23 matching lines...) Expand all
970 } else if (url == uberauth_token_gurl_) { 1126 } else if (url == uberauth_token_gurl_) {
971 OnUberAuthTokenFetch(data, status, response_code); 1127 OnUberAuthTokenFetch(data, status, response_code);
972 } else if (url == oauth_login_gurl_) { 1128 } else if (url == oauth_login_gurl_) {
973 OnOAuthLoginFetched(data, status, response_code); 1129 OnOAuthLoginFetched(data, status, response_code);
974 } else if (url == oauth2_revoke_gurl_) { 1130 } else if (url == oauth2_revoke_gurl_) {
975 OnOAuth2RevokeTokenFetched(data, status, response_code); 1131 OnOAuth2RevokeTokenFetched(data, status, response_code);
976 } else if (url == list_accounts_gurl_) { 1132 } else if (url == list_accounts_gurl_) {
977 OnListAccountsFetched(data, status, response_code); 1133 OnListAccountsFetched(data, status, response_code);
978 } else if (url == get_check_connection_info_url_) { 1134 } else if (url == get_check_connection_info_url_) {
979 OnGetCheckConnectionInfoFetched(data, status, response_code); 1135 OnGetCheckConnectionInfoFetched(data, status, response_code);
1136 } else if (url == oauth2_iframe_url_) {
1137 if (requested_service_ == kListIdpServiceRequested)
1138 OnListIdpSessionsFetched(data, status, response_code);
1139 else if (requested_service_ == kGetTokenResponseRequested)
1140 OnGetTokenResponseFetched(data, status, response_code);
1141 else
1142 NOTREACHED();
980 } else { 1143 } else {
981 NOTREACHED(); 1144 NOTREACHED();
982 } 1145 }
983 } 1146 }
984 1147
985 // static 1148 // static
986 bool GaiaAuthFetcher::IsSecondFactorSuccess( 1149 bool GaiaAuthFetcher::IsSecondFactorSuccess(
987 const std::string& alleged_error) { 1150 const std::string& alleged_error) {
988 return alleged_error.find(kSecondFactor) != 1151 return alleged_error.find(kSecondFactor) !=
989 std::string::npos; 1152 std::string::npos;
990 } 1153 }
991 1154
992 // static 1155 // static
993 bool GaiaAuthFetcher::IsWebLoginRequiredSuccess( 1156 bool GaiaAuthFetcher::IsWebLoginRequiredSuccess(
994 const std::string& alleged_error) { 1157 const std::string& alleged_error) {
995 return alleged_error.find(kWebLoginRequired) != 1158 return alleged_error.find(kWebLoginRequired) !=
996 std::string::npos; 1159 std::string::npos;
997 } 1160 }
OLDNEW
« no previous file with comments | « google_apis/gaia/gaia_auth_fetcher.h ('k') | google_apis/gaia/gaia_urls.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698