PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 1.6.0
JetBackup – Backup, Restore & Migrate v1.6.0
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / com / lib / Dropbox / WebAuth.php
backup / com / lib / Dropbox Last commit date
Exception 8 years ago WebAuthException 8 years ago certs 8 years ago AppInfo.php 8 years ago AppInfoLoadException.php 8 years ago ArrayEntryStore.php 8 years ago AuthBase.php 8 years ago AuthInfo.php 8 years ago AuthInfoLoadException.php 8 years ago Checker.php 8 years ago Client.php 8 years ago Curl.php 8 years ago CurlStreamRelay.php 8 years ago DeserializeException.php 8 years ago DropboxMetadataHeaderCatcher.php 8 years ago Exception.php 8 years ago Host.php 8 years ago HttpResponse.php 8 years ago OAuth1AccessToken.php 8 years ago OAuth1Upgrader.php 8 years ago Path.php 8 years ago RequestUtil.php 8 years ago RootCertificates.php 8 years ago SSLTester.php 8 years ago Security.php 8 years ago StreamReadException.php 8 years ago Util.php 8 years ago ValueStore.php 8 years ago WebAuth.php 5 years ago WebAuthBase.php 8 years ago WebAuthNoRedirect.php 8 years ago WriteMode.php 8 years ago autoload.php 8 years ago strict.php 8 years ago
WebAuth.php
275 lines
1 <?php
2 namespace Dropbox;
3
4 /**
5 * OAuth 2 "authorization code" flow. (This SDK does not support the "token" flow.)
6 *
7 * Use {@link WebAuth::start()} and {@link WebAuth::finish()} to guide your
8 * user through the process of giving your app access to their Dropbox account.
9 * At the end, you will have an access token, which you can pass to {@link Client}
10 * and start making API calls.
11 *
12 * Example:
13 *
14 * <code>
15 * use \Dropbox as dbx;
16 *
17 * function getWebAuth()
18 * {
19 * $appInfo = dbx\AppInfo::loadFromJsonFile(...);
20 * $clientIdentifier = "my-app/1.0";
21 * $redirectUri = "https://example.org/dropbox-auth-finish";
22 * $csrfTokenStore = new dbx\ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token');
23 * return new dbx\WebAuth($appInfo, $clientIdentifier, $redirectUri, $csrfTokenStore, ...);
24 * }
25 *
26 * // ----------------------------------------------------------
27 * // In the URL handler for "/dropbox-auth-start"
28 *
29 * $authorizeUrl = getWebAuth()->start();
30 * header("Location: $authorizeUrl");
31 *
32 * // ----------------------------------------------------------
33 * // In the URL handler for "/dropbox-auth-finish"
34 *
35 * try {
36 * list($accessToken, $userId, $urlState) = getWebAuth()->finish($_GET);
37 * assert($urlState === null); // Since we didn't pass anything in start()
38 * }
39 * catch (dbx\WebAuthException_BadRequest $ex) {
40 * error_log("/dropbox-auth-finish: bad request: " . $ex->getMessage());
41 * // Respond with an HTTP 400 and display error page...
42 * }
43 * catch (dbx\WebAuthException_BadState $ex) {
44 * // Auth session expired. Restart the auth process.
45 * header('Location: /dropbox-auth-start');
46 * }
47 * catch (dbx\WebAuthException_Csrf $ex) {
48 * error_log("/dropbox-auth-finish: CSRF mismatch: " . $ex->getMessage());
49 * // Respond with HTTP 403 and display error page...
50 * }
51 * catch (dbx\WebAuthException_NotApproved $ex) {
52 * error_log("/dropbox-auth-finish: not approved: " . $ex->getMessage());
53 * }
54 * catch (dbx\WebAuthException_Provider $ex) {
55 * error_log("/dropbox-auth-finish: error redirect from Dropbox: " . $ex->getMessage());
56 * }
57 * catch (dbx\Exception $ex) {
58 * error_log("/dropbox-auth-finish: error communicating with Dropbox API: " . $ex->getMessage());
59 * }
60 *
61 * // We can now use $accessToken to make API requests.
62 * $client = dbx\Client($accessToken, ...);
63 * </code>
64 *
65 */
66 class WebAuth extends WebAuthBase
67 {
68 /**
69 * The URI that the Dropbox server will redirect the user to after the user finishes
70 * authorizing your app. This URI must be HTTPS-based and
71 * <a href="https://www.dropbox.com/developers/apps">pre-registered with Dropbox</a>,
72 * though "localhost"-based and "127.0.0.1"-based URIs are allowed without pre-registration
73 * and can be either HTTP or HTTPS.
74 *
75 * @return string
76 */
77 function getRedirectUri() { return $this->redirectUri; }
78
79 /** @var string */
80 private $redirectUri;
81
82 /**
83 * A object that lets us save CSRF token string to the user's session. If you're using the
84 * standard PHP <code>$_SESSION</code>, you can pass in something like
85 * <code>new ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token')</code>.
86 *
87 * If you're not using $_SESSION, you might have to create your own class that provides
88 * the same <code>get()</code>/<code>set()</code>/<code>clear()</code> methods as
89 * {@link ArrayEntryStore}.
90 *
91 * @return ValueStore
92 */
93 function getCsrfTokenStore() { return $this->csrfTokenStore; }
94
95 /** @var object */
96 private $csrfTokenStore;
97
98 /**
99 * Constructor.
100 *
101 * @param AppInfo $appInfo
102 * See {@link getAppInfo()}
103 * @param string $clientIdentifier
104 * See {@link getClientIdentifier()}
105 * @param null|string $redirectUri
106 * See {@link getRedirectUri()}
107 * @param null|ValueStore $csrfTokenStore
108 * See {@link getCsrfTokenStore()}
109 * @param null|string $userLocale
110 * See {@link getUserLocale()}
111 */
112 function __construct($appInfo, $clientIdentifier, $redirectUri, $csrfTokenStore, $userLocale = null)
113 {
114 parent::__construct($appInfo, $clientIdentifier, $userLocale);
115
116 Checker::argStringNonEmpty("redirectUri", $redirectUri);
117
118 $this->csrfTokenStore = $csrfTokenStore;
119 $this->redirectUri = $redirectUri;
120 }
121
122 /**
123 * Starts the OAuth 2 authorization process, which involves redirecting the user to the
124 * returned authorization URL (a URL on the Dropbox website). When the user then
125 * either approves or denies your app access, Dropbox will redirect them to the
126 * <code>$redirectUri</code> given to constructor, at which point you should
127 * call {@link finish()} to complete the authorization process.
128 *
129 * This function will also save a CSRF token using the <code>$csrfTokenStore</code> given to
130 * the constructor. This CSRF token will be checked on {@link finish()} to prevent
131 * request forgery.
132 *
133 * See <a href="https://www.dropbox.com/developers/core/docs#oa2-authorize">/oauth2/authorize</a>.
134 *
135 * @param string|null $urlState
136 * Any data you would like to keep in the URL through the authorization process.
137 * This exact state will be returned to you by {@link finish()}.
138 *
139 * @return array
140 * The URL to redirect the user to.
141 *
142 * @throws Exception
143 */
144 function start($urlState = null)
145 {
146 Checker::argStringOrNull("urlState", $urlState);
147
148 $csrfToken = self::encodeCsrfToken(Security::getRandomBytes(16));
149 \SGConfig::set('SG_DROPBOX_CONNECTION_CSRF_TOKEN', $csrfToken);
150 $state = $csrfToken;
151 if ($urlState !== null) {
152 $state .= "|";
153 $state .= $urlState;
154 }
155 $this->csrfTokenStore->set($csrfToken);
156
157 return $this->_getAuthorizeUrl($this->redirectUri, $state);
158 }
159
160 private static function encodeCsrfToken($string)
161 {
162 return strtr(base64_encode($string), '+/', '-_');
163 }
164
165 /**
166 * Call this after the user has visited the authorize URL ({@link start()}), approved your app,
167 * and was redirected to your redirect URI.
168 *
169 * See <a href="https://www.dropbox.com/developers/core/docs#oa2-token">/oauth2/token</a>.
170 *
171 * @param array $queryParams
172 * The query parameters on the GET request to your redirect URI.
173 *
174 * @return array
175 * A <code>list(string $accessToken, string $userId, string $urlState)</code>, where
176 * <code>$accessToken</code> can be used to construct a {@link Client}, <code>$userId</code>
177 * is the user ID of the user's Dropbox account, and <code>$urlState</code> is the
178 * value you originally passed in to {@link start()}.
179 *
180 * @throws Exception
181 * Thrown if there's an error getting the access token from Dropbox.
182 * @throws WebAuthException_BadRequest
183 * @throws WebAuthException_BadState
184 * @throws WebAuthException_Csrf
185 * @throws WebAuthException_NotApproved
186 * @throws WebAuthException_Provider
187 */
188 function finish($queryParams)
189 {
190 Checker::argArray("queryParams", $queryParams);
191
192 $csrfTokenFromSession = $this->csrfTokenStore->get();
193 Checker::argStringOrNull("this->csrfTokenStore->get()", $csrfTokenFromSession);
194
195 // Check well-formedness of request.
196
197 if (!isset($queryParams['state'])) {
198 throw new WebAuthException_BadRequest("Missing query parameter 'state'.");
199 }
200 $state = $queryParams['state'];
201 Checker::argString("queryParams['state']", $state);
202
203 $error = null;
204 $errorDescription = null;
205 if (isset($queryParams['error'])) {
206 $error = $queryParams['error'];
207 Checker::argString("queryParams['error']", $error);
208 if (isset($queryParams['error_description'])) {
209 $errorDescription = $queryParams['error_description'];
210 Checker::argString("queryParams['error_description']", $errorDescription);
211 }
212 }
213
214 $code = null;
215 if (isset($queryParams['code'])) {
216 $code = $queryParams['code'];
217 Checker::argString("queryParams['code']", $code);
218 }
219
220 if ($code !== null && $error !== null) {
221 throw new WebAuthException_BadRequest("Query parameters 'code' and 'error' are both set;".
222 " only one must be set.");
223 }
224 if ($code === null && $error === null) {
225 throw new WebAuthException_BadRequest("Neither query parameter 'code' or 'error' is set.");
226 }
227
228 // Check CSRF token
229
230 if ($csrfTokenFromSession === null) {
231 throw new WebAuthException_BadState();
232 }
233
234 $splitPos = strpos($state, "|");
235 if ($splitPos === false) {
236 $givenCsrfToken = $state;
237 $urlState = null;
238 } else {
239 $givenCsrfToken = substr($state, 0, $splitPos);
240 $urlState = substr($state, $splitPos + 1);
241 }
242 if (!Security::stringEquals($csrfTokenFromSession, $givenCsrfToken)) {
243 throw new WebAuthException_Csrf("Expected ".Util::q($csrfTokenFromSession) .
244 ", got ".Util::q($givenCsrfToken) .".");
245 }
246 $this->csrfTokenStore->clear();
247
248 // Check for error identifier
249
250 if ($error !== null) {
251 if ($error === 'access_denied') {
252 // When the user clicks "Deny".
253 if ($errorDescription === null) {
254 throw new WebAuthException_NotApproved("No additional description from Dropbox.");
255 } else {
256 throw new WebAuthException_NotApproved("Additional description from Dropbox: $errorDescription");
257 }
258 } else {
259 // All other errors.
260 $fullMessage = $error;
261 if ($errorDescription !== null) {
262 $fullMessage .= ": ";
263 $fullMessage .= $errorDescription;
264 }
265 throw new WebAuthException_Provider($fullMessage);
266 }
267 }
268
269 // If everything went ok, make the network call to get an access token.
270
271 list($accessToken, $userId) = $this->_finish($code, $this->redirectUri);
272 return array($accessToken, $userId, $urlState);
273 }
274 }
275