File: gaia_web_auth_flow.h

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (136 lines) | stat: -rw-r--r-- 5,246 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_

#include "base/macros.h"
#include "chrome/browser/extensions/api/identity/extension_token_key.h"
#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
#include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
#include "google_apis/gaia/ubertoken_fetcher.h"
#include "net/http/http_cache.h"

namespace net {
class HttpNetworkSession;
class TrivialURLRequestContextGetter;
}

namespace extensions {

// Implements a web-based OAuth2 scope approval dialog. This flow has
// four parts:
// 1. Fetch an ubertoken for a signed-in user.
// 2. Use the ubertoken to get session cookies using MergeSession.
// 3. Start the OAuth flow and wait for final redirect.
// 4. Parse results from the fragment component of the final redirect URI.
//
// The OAuth flow is a special version of the OAuth2 out-of-band flow
// where the final response page's title contains the
// redirect_uri. The redirect URI has an unusual format to prevent its
// use in other contexts. The scheme of the URI is a reversed version
// of the OAuth client ID, and the path starts with the Chrome
// extension ID. For example, an app with the OAuth client ID
// "32610281651.apps.googleusercontent.com" and a Chrome app ID
// "kbinjhdkhikmpjoejcfofghmjjpidcnj", would get redirected to:
//
// com.googleusercontent.apps.32610281651:/kbinjhdkhikmpjoejcfofghmjjpidcnj
//
// Arriving at this URI completes the flow. The last response from
// gaia does a JavaScript redirect to the special URI, but also
// includes the same URI in its title. The navigation to this URI gets
// filtered out because of its unusual protocol scheme, so
// GaiaWebAuthFlow pulls it out of the window title instead.

class GaiaWebAuthFlow : public UbertokenConsumer, public WebAuthFlow::Delegate {
 public:
  enum Failure {
    WINDOW_CLOSED,  // Window closed by user.
    INVALID_REDIRECT,  // Redirect parse error.
    SERVICE_AUTH_ERROR,  // Non-OAuth related authentication error
    OAUTH_ERROR,  // Flow reached final redirect, which contained an error.
    LOAD_FAILED  // An auth flow page failed to load.
  };

  class Delegate {
   public:
    // Called when the flow fails prior to the final OAuth redirect,
    // TODO(courage): LOAD_FAILURE descriptions?
    virtual void OnGaiaFlowFailure(Failure failure,
                                   GoogleServiceAuthError service_error,
                                   const std::string& oauth_error) = 0;
    // Called when the OAuth2 flow completes.
    virtual void OnGaiaFlowCompleted(const std::string& access_token,
                                     const std::string& expiration) = 0;
  };

  GaiaWebAuthFlow(Delegate* delegate,
                  Profile* profile,
                  const ExtensionTokenKey* token_key,
                  const std::string& oauth2_client_id,
                  const std::string& locale);
  ~GaiaWebAuthFlow() override;

  // Starts the flow by fetching an ubertoken. Can override for testing.
  virtual void Start();

  // UbertokenConsumer implementation:
  void OnUbertokenSuccess(const std::string& token) override;
  void OnUbertokenFailure(const GoogleServiceAuthError& error) override;

  // WebAuthFlow::Delegate implementation.
  void OnAuthFlowFailure(WebAuthFlow::Failure failure) override;
  void OnAuthFlowURLChange(const GURL& redirect_url) override;
  void OnAuthFlowTitleChange(const std::string& title) override;

 private:
  // Creates a WebAuthFlow, which will navigate to |url|. Can override
  // for testing. Used to kick off the MergeSession (step #2).
  virtual std::unique_ptr<WebAuthFlow> CreateWebAuthFlow(GURL url);

  class IOHelper {
   public:
    IOHelper(base::WeakPtr<GaiaWebAuthFlow> gaia_web_auth_flow,
             net::URLRequestContextGetter* main_context);
    ~IOHelper();

    void PrepareRequestContext();
    void Cleanup();

    net::URLRequestContext* ubertoken_request_context() {
      return ubertoken_request_context_.get();
    }

   private:
    std::unique_ptr<net::HttpCache::BackendFactory> app_backend_;
    std::unique_ptr<net::HttpNetworkSession> http_network_session_;
    std::unique_ptr<net::HttpCache> app_http_cache_;
    std::unique_ptr<net::URLRequestContext> ubertoken_request_context_;

    base::WeakPtr<GaiaWebAuthFlow> gaia_web_auth_flow_;
    net::URLRequestContextGetter* main_context_;
  };

  void StartUberTokenFetch();

  Delegate* delegate_;
  Profile* profile_;
  std::string account_id_;
  std::string redirect_scheme_;
  std::string redirect_path_prefix_;
  GURL auth_url_;

  std::unique_ptr<IOHelper> io_helper_;
  std::unique_ptr<UbertokenFetcher> ubertoken_fetcher_;
  std::unique_ptr<WebAuthFlow> web_flow_;
  scoped_refptr<net::TrivialURLRequestContextGetter> context_getter_;

  base::WeakPtrFactory<GaiaWebAuthFlow> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GaiaWebAuthFlow);
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_