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

Side by Side Diff: chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc

Issue 15148007: Identity API: web-based scope approval dialogs for getAuthToken (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: better protocol description Created 7 years, 7 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 (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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698