1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 01:02:42 +01:00

Make Oauth-registration flows a bit more resilient to failures from the providers

Summary: basically by validating we have good user data when we set the user data.

Test Plan: simulated a failure from a phabricator on phabricator oauth scenario. viewed ui that correctly told me there was an error with the provider and to try again.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Koolvin

Maniphest Tasks: T1077

Differential Revision: https://secure.phabricator.com/D2337
This commit is contained in:
Bob Trahan 2012-05-01 11:51:40 +02:00
parent 458563c68a
commit 8988667dcc
13 changed files with 77 additions and 11 deletions

View file

@ -713,6 +713,7 @@ phutil_register_library_map(array(
'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure', 'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure',
'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth', 'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth',
'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base', 'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
'PhabricatorOAuthProviderException' => 'applications/auth/oauth/provider/exception',
'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook', 'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github', 'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github',
'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google', 'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google',

View file

@ -64,8 +64,12 @@ final class PhabricatorOAuthLoginController
'access_token' => $this->accessToken, 'access_token' => $this->accessToken,
)); ));
try {
$user_data = @file_get_contents($userinfo_uri); $user_data = @file_get_contents($userinfo_uri);
$provider->setUserData($user_data); $provider->setUserData($user_data);
} catch (PhabricatorOAuthProviderException $e) {
return $this->buildErrorResponse(new PhabricatorOAuthFailureView());
}
$provider->setAccessToken($this->accessToken); $provider->setAccessToken($this->accessToken);
$user_id = $provider->retrieveUserID(); $user_id = $provider->retrieveUserID();

View file

@ -98,6 +98,19 @@ abstract class PhabricatorOAuthProvider {
return $this->accessToken; return $this->accessToken;
} }
/**
* Often used within setUserData to make sure $data is not completely
* junk. More granular validations of data might be necessary depending on
* the provider and are generally encouraged.
*/
final protected function validateUserData($data) {
if (empty($data) || !is_array($data)) {
throw new PhabricatorOAuthProviderException();
}
return true;
}
public static function newProvider($which) { public static function newProvider($which) {
switch ($which) { switch ($which) {
case self::PROVIDER_FACEBOOK: case self::PROVIDER_FACEBOOK:

View file

@ -6,6 +6,7 @@
phutil_require_module('phabricator', 'applications/auth/oauth/provider/exception');
phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phutil', 'symbols'); phutil_require_module('phutil', 'symbols');

View file

@ -0,0 +1,20 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorOAuthProviderException extends Exception {
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorOAuthProviderException.php');

View file

@ -82,7 +82,9 @@ final class PhabricatorOAuthProviderFacebook extends PhabricatorOAuthProvider {
} }
public function setUserData($data) { public function setUserData($data) {
$this->userData = json_decode($data, true); $data = json_decode($data, true);
$this->validateUserData($data);
$this->userData = $data;
return $this; return $this;
} }

View file

@ -79,7 +79,9 @@ final class PhabricatorOAuthProviderGitHub extends PhabricatorOAuthProvider {
} }
public function setUserData($data) { public function setUserData($data) {
$this->userData = idx(json_decode($data, true), 'user'); $data = idx(json_decode($data, true), 'user');
$this->validateUserData($data);
$this->userData = $data;
return $this; return $this;
} }

View file

@ -87,7 +87,14 @@ final class PhabricatorOAuthProviderGoogle extends PhabricatorOAuthProvider {
} }
public function setUserData($data) { public function setUserData($data) {
// SimpleXMLElement will throw if $data is unusably malformed, which to
// us is just a provider issue
try {
$xml = new SimpleXMLElement($data); $xml = new SimpleXMLElement($data);
} catch (Exception $e) {
throw new PhabricatorOAuthProviderException();
}
$id = (string)$xml->id; $id = (string)$xml->id;
$this->userData = array( $this->userData = array(
'id' => $id, 'id' => $id,

View file

@ -7,6 +7,7 @@
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base'); phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/auth/oauth/provider/exception');
phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -102,11 +102,9 @@ extends PhabricatorOAuthProvider {
public function setUserData($data) { public function setUserData($data) {
// need to strip the javascript shield from conduit // need to strip the javascript shield from conduit
$data = substr($data, 8); $data = substr($data, 8);
$data = json_decode($data, true); $data = idx(json_decode($data, true), 'result');
if (!is_array($data)) { $this->validateUserData($data);
throw new Exception('Invalid user data.'); $this->userData = $data;
}
$this->userData = $data['result'];
return $this; return $this;
} }

View file

@ -9,5 +9,7 @@
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base'); phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorOAuthProviderPhabricator.php'); phutil_require_source('PhabricatorOAuthProviderPhabricator.php');

View file

@ -226,8 +226,13 @@ final class PhabricatorUserOAuthSettingsPanelController
$error = 'Unable to retrieve image.'; $error = 'Unable to retrieve image.';
} }
} catch (Exception $e) { } catch (Exception $e) {
if ($e instanceof PhabricatorOAuthProviderException) {
$error = sprintf('Unable to retrieve image from %s',
$provider->getProviderName());
} else {
$error = 'Unable to save image.'; $error = 'Unable to save image.';
} }
}
$notice = new AphrontErrorView(); $notice = new AphrontErrorView();
if ($error) { if ($error) {
$notice $notice