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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_
8 #include "chrome/browser/extensions/api/identity/extension_token_key.h"
9 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
10 #include "chrome/browser/ui/host_desktop.h"
11 #include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
12 #include "google_apis/gaia/ubertoken_fetcher.h"
14 namespace extensions
{
16 // Implements a web-based OAuth2 scope approval dialog. This flow has
18 // 1. Fetch an ubertoken for a signed-in user.
19 // 2. Use the ubertoken to get session cookies using MergeSession.
20 // 3. Start the OAuth flow and wait for final redirect.
21 // 4. Parse results from the fragment component of the final redirect URI.
23 // The OAuth flow is a special version of the OAuth2 out-of-band flow
24 // where the final response page's title contains the
25 // redirect_uri. The redirect URI has an unusual format to prevent its
26 // use in other contexts. The scheme of the URI is a reversed version
27 // of the OAuth client ID, and the path starts with the Chrome
28 // extension ID. For example, an app with the OAuth client ID
29 // "32610281651.apps.googleusercontent.com" and a Chrome app ID
30 // "kbinjhdkhikmpjoejcfofghmjjpidcnj", would get redirected to:
32 // com.googleusercontent.apps.32610281651:/kbinjhdkhikmpjoejcfofghmjjpidcnj
34 // Arriving at this URI completes the flow. The last response from
35 // gaia does a JavaScript redirect to the special URI, but also
36 // includes the same URI in its title. The navigation to this URI gets
37 // filtered out because of its unusual protocol scheme, so
38 // GaiaWebAuthFlow pulls it out of the window title instead.
40 class GaiaWebAuthFlow
: public UbertokenConsumer
, public WebAuthFlow::Delegate
{
43 WINDOW_CLOSED
, // Window closed by user.
44 INVALID_REDIRECT
, // Redirect parse error.
45 SERVICE_AUTH_ERROR
, // Non-OAuth related authentication error
46 OAUTH_ERROR
, // Flow reached final redirect, which contained an error.
47 LOAD_FAILED
// An auth flow page failed to load.
52 // Called when the flow fails prior to the final OAuth redirect,
53 // TODO(courage): LOAD_FAILURE descriptions?
54 virtual void OnGaiaFlowFailure(Failure failure
,
55 GoogleServiceAuthError service_error
,
56 const std::string
& oauth_error
) = 0;
57 // Called when the OAuth2 flow completes.
58 virtual void OnGaiaFlowCompleted(const std::string
& access_token
,
59 const std::string
& expiration
) = 0;
62 GaiaWebAuthFlow(Delegate
* delegate
,
64 const ExtensionTokenKey
* token_key
,
65 const std::string
& oauth2_client_id
,
66 const std::string
& locale
);
67 ~GaiaWebAuthFlow() override
;
69 // Starts the flow by fetching an ubertoken. Can override for testing.
72 // UbertokenConsumer implementation:
73 void OnUbertokenSuccess(const std::string
& token
) override
;
74 void OnUbertokenFailure(const GoogleServiceAuthError
& error
) override
;
76 // WebAuthFlow::Delegate implementation.
77 void OnAuthFlowFailure(WebAuthFlow::Failure failure
) override
;
78 void OnAuthFlowURLChange(const GURL
& redirect_url
) override
;
79 void OnAuthFlowTitleChange(const std::string
& title
) override
;
82 // Creates a WebAuthFlow, which will navigate to |url|. Can override
83 // for testing. Used to kick off the MergeSession (step #2).
84 virtual scoped_ptr
<WebAuthFlow
> CreateWebAuthFlow(GURL url
);
88 std::string account_id_
;
89 chrome::HostDesktopType host_desktop_type_
;
90 std::string redirect_scheme_
;
91 std::string redirect_path_prefix_
;
93 scoped_ptr
<UbertokenFetcher
> ubertoken_fetcher_
;
94 scoped_ptr
<WebAuthFlow
> web_flow_
;
96 DISALLOW_COPY_AND_ASSIGN(GaiaWebAuthFlow
);
99 } // namespace extensions
101 #endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_