OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" | |
6 | |
7 #include "base/string_util.h" | |
8 #include "base/stringprintf.h" | |
9 #include "base/strings/string_number_conversions.h" | |
10 #include "base/strings/string_split.h" | |
11 #include "google_apis/gaia/gaia_urls.h" | |
12 #include "net/base/escape.h" | |
13 | |
14 namespace extensions { | |
15 | |
16 GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate, | |
17 Profile* profile, | |
18 chrome::HostDesktopType host_desktop_type, | |
19 const std::string& extension_id, | |
20 const OAuth2Info& oauth2_info) | |
21 : delegate_(delegate), | |
22 profile_(profile), | |
23 host_desktop_type_(host_desktop_type) { | |
24 const char kOAuth2RedirectPathFormat[] = "/%s#"; | |
25 const char kOAuth2AuthorizeFormat[] = | |
26 "%s?response_type=token&approval_prompt=force&authuser=0&" | |
27 "client_id=%s&" | |
28 "scope=%s&" | |
29 "origin=chrome-extension://%s/&" | |
30 "redirect_uri=%s:/%s"; | |
31 | |
32 std::vector<std::string> client_id_parts; | |
33 base::SplitString(oauth2_info.client_id, '.', &client_id_parts); | |
34 std::reverse(client_id_parts.begin(), client_id_parts.end()); | |
35 redirect_scheme_ = JoinString(client_id_parts, '.'); | |
36 | |
37 redirect_path_prefix_ = | |
38 base::StringPrintf(kOAuth2RedirectPathFormat, extension_id.c_str()); | |
39 | |
40 auth_url_ = base::StringPrintf( | |
41 kOAuth2AuthorizeFormat, | |
42 GaiaUrls::GetInstance()->oauth2_auth_url().c_str(), | |
43 oauth2_info.client_id.c_str(), | |
44 net::EscapeUrlEncodedData(JoinString(oauth2_info.scopes, ' '), true) | |
45 .c_str(), | |
46 extension_id.c_str(), | |
47 redirect_scheme_.c_str(), | |
48 extension_id.c_str()); | |
49 } | |
50 | |
51 GaiaWebAuthFlow::~GaiaWebAuthFlow() {} | |
52 | |
53 void GaiaWebAuthFlow::Start() { | |
54 ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this)); | |
55 ubertoken_fetcher_->StartFetchingToken(); | |
56 } | |
57 | |
58 void GaiaWebAuthFlow::OnUbertokenSuccess(const std::string& token) { | |
59 const char kMergeSessionQueryFormat[] = "?uberauth=%s&" | |
60 "continue=%s&" | |
61 "source=appsv2"; | |
62 | |
63 std::string merge_query = | |
64 base::StringPrintf(kMergeSessionQueryFormat, | |
65 net::EscapeUrlEncodedData(token, true).c_str(), | |
66 net::EscapeUrlEncodedData(auth_url_, true).c_str()); | |
67 GURL merge_url(GaiaUrls::GetInstance()->merge_session_url() + merge_query); | |
68 | |
69 web_flow_ = CreateWebAuthFlow(merge_url); | |
70 web_flow_->Start(); | |
71 } | |
72 | |
73 void GaiaWebAuthFlow::OnUbertokenFailure(const GoogleServiceAuthError& error) { | |
74 delegate_->OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error); | |
75 } | |
76 | |
77 void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { | |
78 DCHECK(failure == WebAuthFlow::WINDOW_CLOSED); | |
79 delegate_->OnGaiaFlowFailure( | |
80 GaiaWebAuthFlow::WINDOW_CLOSED, | |
81 GoogleServiceAuthError(GoogleServiceAuthError::NONE)); | |
82 } | |
83 | |
84 void GaiaWebAuthFlow::OnAuthFlowURLChange(const GURL& url) { | |
85 const char kOAuth2RedirectAccessTokenKey[] = "access_token="; | |
86 const char kOAuth2RedirectErrorKey[] = "error="; | |
87 const char kOAuth2ExpiresInKey[] = "expires_in="; | |
88 | |
89 // The format of the target URL is: | |
90 // reversed.oauth.client.id:/extensionid#access_token=TOKEN | |
91 // | |
92 // Because there is no double slash, everything after the scheme is | |
93 // interpreted as a path, including the fragment. | |
94 | |
95 if (url.scheme() == redirect_scheme_ && !url.has_host() && !url.has_port() && | |
96 StartsWithASCII(url.path(), redirect_path_prefix_, true)) { | |
97 web_flow_.reset(); | |
98 | |
99 std::string fragment = | |
100 url.path().substr(redirect_path_prefix_.length(), std::string::npos); | |
101 std::vector<std::string> parts; | |
102 base::SplitString(fragment, '&', &parts); | |
103 std::string token_key(kOAuth2RedirectAccessTokenKey); | |
Roger Tawa OOO till Jul 10th
2013/05/16 16:06:15
Better to use:
std::vector<std::pair<std::strin
Michael Courage
2013/05/16 20:39:02
Done. That's so much nicer, thanks!
| |
104 std::string error_key(kOAuth2RedirectErrorKey); | |
105 std::string expiration_key(kOAuth2ExpiresInKey); | |
106 std::string access_token; | |
107 std::string error; | |
108 std::string expiration; | |
109 | |
110 for (std::vector<std::string>::iterator it = parts.begin(); | |
111 it != parts.end(); | |
112 ++it) { | |
113 if (StartsWithASCII(*it, token_key, true)) | |
114 access_token = it->substr(token_key.length(), std::string::npos); | |
115 else if (StartsWithASCII(*it, error_key, true)) | |
116 error = it->substr(error_key.length(), std::string::npos); | |
117 else if (StartsWithASCII(*it, expiration_key, true)) | |
118 expiration = it->substr(expiration_key.length(), std::string::npos); | |
119 } | |
120 | |
121 if (access_token.empty() && error.empty()) { | |
122 delegate_->OnGaiaFlowFailure( | |
123 GaiaWebAuthFlow::INVALID_REDIRECT, | |
124 GoogleServiceAuthError(GoogleServiceAuthError::NONE)); | |
125 } else { | |
126 delegate_->OnGaiaFlowCompleted(access_token, expiration, error); | |
127 } | |
128 } | |
129 } | |
130 | |
131 void GaiaWebAuthFlow::OnAuthFlowTitleChange(const std::string& title) { | |
132 // On the final page the title will be "Loading <redirect-url>". | |
133 // Treat it as though we'd really been redirected to <redirect-url>. | |
134 const char kRedirectPrefix[] = "Loading "; | |
135 std::string prefix(kRedirectPrefix); | |
136 | |
137 if (StartsWithASCII(title, prefix, true)) { | |
138 GURL url(title.substr(prefix.length(), std::string::npos)); | |
139 if (url.is_valid()) | |
140 OnAuthFlowURLChange(url); | |
141 } | |
142 } | |
143 | |
144 scoped_ptr<WebAuthFlow> GaiaWebAuthFlow::CreateWebAuthFlow(GURL url) { | |
145 gfx::Rect initial_bounds; | |
146 return scoped_ptr<WebAuthFlow>(new WebAuthFlow(this, | |
147 profile_, | |
148 url, | |
149 WebAuthFlow::INTERACTIVE, | |
150 initial_bounds, | |
151 host_desktop_type_)); | |
152 } | |
153 | |
154 } // extensions | |
OLD | NEW |