OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 // Use this class to authenticate users with Gaia and access cookies sent | |
6 // by the Gaia servers. This class cannot be used on its own becaue it relies | |
7 // on a subclass to provide the virtual Post and GetBackoffDelaySeconds methods. | |
8 // | |
9 // Sample usage: | |
10 // class ActualGaiaAuthenticator : public gaia::GaiaAuthenticator { | |
11 // Provides actual implementation of Post and GetBackoffDelaySeconds. | |
12 // }; | |
13 // ActualGaiaAuthenticator gaia_auth("User-Agent", SERVICE_NAME, kGaiaUrl); | |
14 // if (gaia_auth.Authenticate("email", "passwd", SAVE_IN_MEMORY_ONLY, | |
15 // true)) { // Synchronous | |
16 // // Do something with: gaia_auth.auth_token(), or gaia_auth.sid(), | |
17 // // or gaia_auth.lsid() | |
18 // } | |
19 // | |
20 // Credentials can also be preserved for subsequent requests, though these are | |
21 // saved in plain-text in memory, and not very secure on client systems. The | |
22 // email address associated with the Gaia account can be read; the password is | |
23 // write-only. | |
24 | |
25 // TODO(sanjeevr): This class has been moved here from the bookmarks sync code. | |
26 // While it is a generic class that handles GAIA authentication, there are some | |
27 // artifacts of the sync code which needs to be cleaned up. | |
28 #ifndef CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_ | |
29 #define CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_ | |
30 | |
31 #include <string> | |
32 | |
33 #include "base/basictypes.h" | |
34 #include "base/gtest_prod_util.h" | |
35 #include "base/message_loop.h" | |
36 #include "googleurl/src/gurl.h" | |
37 | |
38 namespace gaia { | |
39 | |
40 // Error codes from Gaia. These will be set correctly for both Gaia V1 | |
41 // (/ClientAuth) and V2 (/ClientLogin) | |
42 enum AuthenticationError { | |
43 None = 0, | |
44 BadAuthentication = 1, | |
45 NotVerified = 2, | |
46 TermsNotAgreed = 3, | |
47 Unknown = 4, | |
48 AccountDeleted = 5, | |
49 AccountDisabled = 6, | |
50 CaptchaRequired = 7, | |
51 ServiceUnavailable = 8, | |
52 // Errors generated by this class not Gaia. | |
53 CredentialsNotSet = 9, | |
54 ConnectionUnavailable = 10 | |
55 }; | |
56 | |
57 class GaiaAuthenticator; | |
58 | |
59 // GaiaAuthenticator can be used to pass user credentials to Gaia and obtain | |
60 // cookies set by the Gaia servers. | |
61 class GaiaAuthenticator { | |
62 FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticatorTest, | |
63 TestNewlineAtEndOfAuthTokenRemoved); | |
64 public: | |
65 | |
66 // Since GaiaAuthenticator can be used for any service, or by any client, you | |
67 // must include a user-agent and a service-id when creating one. The | |
68 // user_agent is a short string used for simple log analysis. gaia_url is used | |
69 // to choose the server to authenticate with (e.g. | |
70 // http://accounts.google.com/ClientLogin). | |
71 GaiaAuthenticator(const std::string& user_agent, | |
72 const std::string& service_id, | |
73 const std::string& gaia_url); | |
74 | |
75 virtual ~GaiaAuthenticator(); | |
76 | |
77 // This object should only be invoked from the AuthWatcherThread message | |
78 // loop, which is injected here. | |
79 void set_message_loop(const MessageLoop* loop) { | |
80 message_loop_ = loop; | |
81 } | |
82 | |
83 // Pass credentials to authenticate with, or use saved credentials via an | |
84 // overload. If authentication succeeds, you can retrieve the authentication | |
85 // token via the respective accessors. Returns a boolean indicating whether | |
86 // authentication succeeded or not. | |
87 bool Authenticate(const std::string& user_name, const std::string& password, | |
88 const std::string& captcha_token, | |
89 const std::string& captcha_value); | |
90 | |
91 bool Authenticate(const std::string& user_name, const std::string& password); | |
92 | |
93 // Pass the LSID to authenticate with. If the authentication succeeds, you can | |
94 // retrieve the authetication token via the respective accessors. Returns a | |
95 // boolean indicating whether authentication succeeded or not. | |
96 // Always returns a long lived token. | |
97 bool AuthenticateWithLsid(const std::string& lsid); | |
98 | |
99 // Resets all stored cookies to their default values. | |
100 void ResetCredentials(); | |
101 | |
102 void SetUsernamePassword(const std::string& username, | |
103 const std::string& password); | |
104 | |
105 void SetUsername(const std::string& username); | |
106 | |
107 // Virtual for testing | |
108 virtual void RenewAuthToken(const std::string& auth_token); | |
109 void SetAuthToken(const std::string& auth_token); | |
110 | |
111 struct AuthResults { | |
112 AuthResults(); | |
113 AuthResults(const AuthResults& other); | |
114 ~AuthResults(); | |
115 | |
116 std::string email; | |
117 std::string password; | |
118 | |
119 // Fields that store various cookies. | |
120 std::string sid; | |
121 std::string lsid; | |
122 std::string auth_token; | |
123 | |
124 std::string primary_email; | |
125 | |
126 // Fields for items returned when authentication fails. | |
127 std::string error_msg; | |
128 enum AuthenticationError auth_error; | |
129 std::string auth_error_url; | |
130 std::string captcha_token; | |
131 std::string captcha_url; | |
132 }; | |
133 | |
134 protected: | |
135 | |
136 struct AuthParams { | |
137 AuthParams(); | |
138 ~AuthParams(); | |
139 | |
140 GaiaAuthenticator* authenticator; | |
141 uint32 request_id; | |
142 std::string email; | |
143 std::string password; | |
144 std::string captcha_token; | |
145 std::string captcha_value; | |
146 }; | |
147 | |
148 // mutex_ must be entered before calling this function. | |
149 AuthParams MakeParams(const std::string& user_name, | |
150 const std::string& password, | |
151 const std::string& captcha_token, | |
152 const std::string& captcha_value); | |
153 | |
154 // The real Authenticate implementations. | |
155 bool AuthenticateImpl(const AuthParams& params); | |
156 bool AuthenticateImpl(const AuthParams& params, AuthResults* results); | |
157 | |
158 // virtual for testing purposes. | |
159 virtual bool PerformGaiaRequest(const AuthParams& params, | |
160 AuthResults* results); | |
161 virtual bool Post(const GURL& url, const std::string& post_body, | |
162 unsigned long* response_code, std::string* response_body); | |
163 | |
164 // Caller should fill in results->LSID before calling. Result in | |
165 // results->primary_email. | |
166 virtual bool LookupEmail(AuthResults* results); | |
167 | |
168 // Subclasses must override to provide a backoff delay. It is virtual instead | |
169 // of pure virtual for testing purposes. | |
170 // TODO(sanjeevr): This should be made pure virtual. But this class is | |
171 // currently directly being used in sync/engine/authenticator.cc, which is | |
172 // wrong. | |
173 virtual int GetBackoffDelaySeconds(int current_backoff_delay); | |
174 | |
175 public: | |
176 // Retrieve email. | |
177 inline std::string email() const { | |
178 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
179 return auth_results_.email; | |
180 } | |
181 | |
182 // Retrieve password. | |
183 inline std::string password() const { | |
184 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
185 return auth_results_.password; | |
186 } | |
187 | |
188 // Retrieve AuthToken, if previously authenticated; otherwise returns "". | |
189 inline std::string auth_token() const { | |
190 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
191 return auth_results_.auth_token; | |
192 } | |
193 | |
194 // Retrieve SID cookie. For details, see the Google Accounts documentation. | |
195 inline std::string sid() const { | |
196 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
197 return auth_results_.sid; | |
198 } | |
199 | |
200 // Retrieve LSID cookie. For details, see the Google Accounts documentation. | |
201 inline std::string lsid() const { | |
202 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
203 return auth_results_.lsid; | |
204 } | |
205 | |
206 // Get last authentication error. | |
207 inline enum AuthenticationError auth_error() const { | |
208 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
209 return auth_results_.auth_error; | |
210 } | |
211 | |
212 inline std::string auth_error_url() const { | |
213 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
214 return auth_results_.auth_error_url; | |
215 } | |
216 | |
217 inline std::string captcha_token() const { | |
218 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
219 return auth_results_.captcha_token; | |
220 } | |
221 | |
222 inline std::string captcha_url() const { | |
223 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
224 return auth_results_.captcha_url; | |
225 } | |
226 | |
227 inline AuthResults results() const { | |
228 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
229 return auth_results_; | |
230 } | |
231 | |
232 private: | |
233 bool IssueAuthToken(AuthResults* results, const std::string& service_id); | |
234 | |
235 // Helper method to parse response when authentication succeeds. | |
236 void ExtractTokensFrom(const std::string& response, AuthResults* results); | |
237 // Helper method to parse response when authentication fails. | |
238 void ExtractAuthErrorFrom(const std::string& response, AuthResults* results); | |
239 | |
240 // Fields for the obvious data items. | |
241 const std::string user_agent_; | |
242 const std::string service_id_; | |
243 const std::string gaia_url_; | |
244 | |
245 AuthResults auth_results_; | |
246 | |
247 // When multiple async requests are running, only the one that started most | |
248 // recently updates the values. | |
249 // | |
250 // Note that even though this code was written to handle multiple requests | |
251 // simultaneously, the sync code issues auth requests one at a time. | |
252 uint32 request_count_; | |
253 | |
254 // Used to compute backoff time for next allowed authentication. | |
255 int delay_; // In seconds. | |
256 // On Windows, time_t is 64-bit by default. Even though we have defined the | |
257 // _USE_32BIT_TIME_T preprocessor flag, other libraries including this header | |
258 // may not have that preprocessor flag defined resulting in mismatched class | |
259 // sizes. So we explicitly define it as 32-bit on Windows. | |
260 // TODO(sanjeevr): Change this to to use base::Time | |
261 #if defined(OS_WIN) | |
262 __time32_t next_allowed_auth_attempt_time_; | |
263 #else // defined(OS_WIN) | |
264 time_t next_allowed_auth_attempt_time_; | |
265 #endif // defined(OS_WIN) | |
266 int early_auth_attempt_count_; | |
267 | |
268 // The message loop all our methods are invoked on. | |
269 const MessageLoop* message_loop_; | |
270 }; | |
271 | |
272 } // namespace gaia | |
273 #endif // CHROME_COMMON_NET_GAIA_GAIA_AUTHENTICATOR_H_ | |
OLD | NEW |