PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 1.4.2
JetBackup – Backup, Restore & Migrate v1.4.2
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 5 years ago WebAuthException 5 years ago certs 5 years ago AppInfo.php 5 years ago AppInfoLoadException.php 5 years ago ArrayEntryStore.php 5 years ago AuthBase.php 5 years ago AuthInfo.php 5 years ago AuthInfoLoadException.php 5 years ago Checker.php 5 years ago Client.php 5 years ago Curl.php 5 years ago CurlStreamRelay.php 5 years ago DeserializeException.php 5 years ago DropboxMetadataHeaderCatcher.php 5 years ago Exception.php 5 years ago Host.php 5 years ago HttpResponse.php 5 years ago OAuth1AccessToken.php 5 years ago OAuth1Upgrader.php 5 years ago Path.php 5 years ago RequestUtil.php 5 years ago RootCertificates.php 5 years ago SSLTester.php 5 years ago Security.php 5 years ago StreamReadException.php 5 years ago Util.php 5 years ago ValueStore.php 5 years ago WebAuth.php 5 years ago WebAuthBase.php 5 years ago WebAuthNoRedirect.php 5 years ago WriteMode.php 5 years ago autoload.php 5 years ago strict.php 5 years ago
WebAuth.php
274 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 $state = $csrfToken;
150 if ($urlState !== null) {
151 $state .= "|";
152 $state .= $urlState;
153 }
154 $this->csrfTokenStore->set($csrfToken);
155
156 return $this->_getAuthorizeUrl($this->redirectUri, $state);
157 }
158
159 private static function encodeCsrfToken($string)
160 {
161 return strtr(base64_encode($string), '+/', '-_');
162 }
163
164 /**
165 * Call this after the user has visited the authorize URL ({@link start()}), approved your app,
166 * and was redirected to your redirect URI.
167 *
168 * See <a href="https://www.dropbox.com/developers/core/docs#oa2-token">/oauth2/token</a>.
169 *
170 * @param array $queryParams
171 * The query parameters on the GET request to your redirect URI.
172 *
173 * @return array
174 * A <code>list(string $accessToken, string $userId, string $urlState)</code>, where
175 * <code>$accessToken</code> can be used to construct a {@link Client}, <code>$userId</code>
176 * is the user ID of the user's Dropbox account, and <code>$urlState</code> is the
177 * value you originally passed in to {@link start()}.
178 *
179 * @throws Exception
180 * Thrown if there's an error getting the access token from Dropbox.
181 * @throws WebAuthException_BadRequest
182 * @throws WebAuthException_BadState
183 * @throws WebAuthException_Csrf
184 * @throws WebAuthException_NotApproved
185 * @throws WebAuthException_Provider
186 */
187 function finish($queryParams)
188 {
189 Checker::argArray("queryParams", $queryParams);
190
191 $csrfTokenFromSession = $this->csrfTokenStore->get();
192 Checker::argStringOrNull("this->csrfTokenStore->get()", $csrfTokenFromSession);
193
194 // Check well-formedness of request.
195
196 if (!isset($queryParams['state'])) {
197 throw new WebAuthException_BadRequest("Missing query parameter 'state'.");
198 }
199 $state = $queryParams['state'];
200 Checker::argString("queryParams['state']", $state);
201
202 $error = null;
203 $errorDescription = null;
204 if (isset($queryParams['error'])) {
205 $error = $queryParams['error'];
206 Checker::argString("queryParams['error']", $error);
207 if (isset($queryParams['error_description'])) {
208 $errorDescription = $queryParams['error_description'];
209 Checker::argString("queryParams['error_description']", $errorDescription);
210 }
211 }
212
213 $code = null;
214 if (isset($queryParams['code'])) {
215 $code = $queryParams['code'];
216 Checker::argString("queryParams['code']", $code);
217 }
218
219 if ($code !== null && $error !== null) {
220 throw new WebAuthException_BadRequest("Query parameters 'code' and 'error' are both set;".
221 " only one must be set.");
222 }
223 if ($code === null && $error === null) {
224 throw new WebAuthException_BadRequest("Neither query parameter 'code' or 'error' is set.");
225 }
226
227 // Check CSRF token
228
229 if ($csrfTokenFromSession === null) {
230 throw new WebAuthException_BadState();
231 }
232
233 $splitPos = strpos($state, "|");
234 if ($splitPos === false) {
235 $givenCsrfToken = $state;
236 $urlState = null;
237 } else {
238 $givenCsrfToken = substr($state, 0, $splitPos);
239 $urlState = substr($state, $splitPos + 1);
240 }
241 if (!Security::stringEquals($csrfTokenFromSession, $givenCsrfToken)) {
242 throw new WebAuthException_Csrf("Expected ".Util::q($csrfTokenFromSession) .
243 ", got ".Util::q($givenCsrfToken) .".");
244 }
245 $this->csrfTokenStore->clear();
246
247 // Check for error identifier
248
249 if ($error !== null) {
250 if ($error === 'access_denied') {
251 // When the user clicks "Deny".
252 if ($errorDescription === null) {
253 throw new WebAuthException_NotApproved("No additional description from Dropbox.");
254 } else {
255 throw new WebAuthException_NotApproved("Additional description from Dropbox: $errorDescription");
256 }
257 } else {
258 // All other errors.
259 $fullMessage = $error;
260 if ($errorDescription !== null) {
261 $fullMessage .= ": ";
262 $fullMessage .= $errorDescription;
263 }
264 throw new WebAuthException_Provider($fullMessage);
265 }
266 }
267
268 // If everything went ok, make the network call to get an access token.
269
270 list($accessToken, $userId) = $this->_finish($code, $this->redirectUri);
271 return array($accessToken, $userId, $urlState);
272 }
273 }
274