mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +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:
parent
458563c68a
commit
8988667dcc
13 changed files with 77 additions and 11 deletions
|
@ -713,6 +713,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure',
|
||||
'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth',
|
||||
'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
|
||||
'PhabricatorOAuthProviderException' => 'applications/auth/oauth/provider/exception',
|
||||
'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
|
||||
'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github',
|
||||
'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google',
|
||||
|
|
|
@ -64,8 +64,12 @@ final class PhabricatorOAuthLoginController
|
|||
'access_token' => $this->accessToken,
|
||||
));
|
||||
|
||||
$user_data = @file_get_contents($userinfo_uri);
|
||||
$provider->setUserData($user_data);
|
||||
try {
|
||||
$user_data = @file_get_contents($userinfo_uri);
|
||||
$provider->setUserData($user_data);
|
||||
} catch (PhabricatorOAuthProviderException $e) {
|
||||
return $this->buildErrorResponse(new PhabricatorOAuthFailureView());
|
||||
}
|
||||
$provider->setAccessToken($this->accessToken);
|
||||
|
||||
$user_id = $provider->retrieveUserID();
|
||||
|
|
|
@ -98,6 +98,19 @@ abstract class PhabricatorOAuthProvider {
|
|||
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) {
|
||||
switch ($which) {
|
||||
case self::PROVIDER_FACEBOOK:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/auth/oauth/provider/exception');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
phutil_require_module('phutil', 'symbols');
|
||||
|
|
|
@ -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 {
|
||||
}
|
10
src/applications/auth/oauth/provider/exception/__init__.php
Normal file
10
src/applications/auth/oauth/provider/exception/__init__.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorOAuthProviderException.php');
|
|
@ -82,7 +82,9 @@ final class PhabricatorOAuthProviderFacebook extends PhabricatorOAuthProvider {
|
|||
}
|
||||
|
||||
public function setUserData($data) {
|
||||
$this->userData = json_decode($data, true);
|
||||
$data = json_decode($data, true);
|
||||
$this->validateUserData($data);
|
||||
$this->userData = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,9 @@ final class PhabricatorOAuthProviderGitHub extends PhabricatorOAuthProvider {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,14 @@ final class PhabricatorOAuthProviderGoogle extends PhabricatorOAuthProvider {
|
|||
}
|
||||
|
||||
public function setUserData($data) {
|
||||
$xml = new SimpleXMLElement($data);
|
||||
// SimpleXMLElement will throw if $data is unusably malformed, which to
|
||||
// us is just a provider issue
|
||||
try {
|
||||
$xml = new SimpleXMLElement($data);
|
||||
} catch (Exception $e) {
|
||||
throw new PhabricatorOAuthProviderException();
|
||||
}
|
||||
|
||||
$id = (string)$xml->id;
|
||||
$this->userData = array(
|
||||
'id' => $id,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
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('phutil', 'utils');
|
||||
|
|
|
@ -102,11 +102,9 @@ extends PhabricatorOAuthProvider {
|
|||
public function setUserData($data) {
|
||||
// need to strip the javascript shield from conduit
|
||||
$data = substr($data, 8);
|
||||
$data = json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('Invalid user data.');
|
||||
}
|
||||
$this->userData = $data['result'];
|
||||
$data = idx(json_decode($data, true), 'result');
|
||||
$this->validateUserData($data);
|
||||
$this->userData = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,5 +9,7 @@
|
|||
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorOAuthProviderPhabricator.php');
|
||||
|
|
|
@ -226,7 +226,12 @@ final class PhabricatorUserOAuthSettingsPanelController
|
|||
$error = 'Unable to retrieve image.';
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = 'Unable to save image.';
|
||||
if ($e instanceof PhabricatorOAuthProviderException) {
|
||||
$error = sprintf('Unable to retrieve image from %s',
|
||||
$provider->getProviderName());
|
||||
} else {
|
||||
$error = 'Unable to save image.';
|
||||
}
|
||||
}
|
||||
$notice = new AphrontErrorView();
|
||||
if ($error) {
|
||||
|
|
Loading…
Reference in a new issue