This repository has been archived by the owner on Nov 25, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding OAuth Wrapper to the core access for Oauth2 authentification
- Loading branch information
Showing
9 changed files
with
281 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
196 changes: 196 additions & 0 deletions
196
core/src/plugins/core.access/src/Stream/OAuthWrapper.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
<?php | ||
/* | ||
* Copyright 2007-2016 Abstrium SAS <team (at) pyd.io> | ||
* This file is part of the Pydio Enterprise Distribution. | ||
* It is subject to the End User License Agreement that you should have | ||
* received and accepted along with this distribution. | ||
*/ | ||
|
||
namespace Pydio\Access\Core\Stream; | ||
|
||
defined('AJXP_EXEC') or die('Access not allowed'); | ||
|
||
require_once(AJXP_BIN_FOLDER . '/guzzle/vendor/autoload.php'); | ||
|
||
use AJXP_SchemeTranslatorWrapper; | ||
use AJXP_Safe; | ||
use AJXP_Utils; | ||
use AuthService; | ||
use CacheService; | ||
use CommerceGuys\Guzzle\Oauth2\GrantType\AuthorizationCode; | ||
use CommerceGuys\Guzzle\Oauth2\AccessToken; | ||
use CommerceGuys\Guzzle\Oauth2\GrantType\RefreshToken; | ||
use CommerceGuys\Guzzle\Oauth2\Oauth2Subscriber; | ||
use GuzzleHttp\Client as GuzzleClient; | ||
use ConfService; | ||
use AJXP_UserAlertException; | ||
use Exception; | ||
use GuzzleHttp\Event\ErrorEvent; | ||
use GuzzleHttp\Exception\RequestException; | ||
|
||
class OAuthWrapper extends AJXP_SchemeTranslatorWrapper | ||
{ | ||
/** | ||
* @param $url | ||
* @return bool|void | ||
* @throws AJXP_UserAlertException | ||
* @throws Exception | ||
*/ | ||
public static function applyInitPathHook($url) { | ||
|
||
// Repository information | ||
$urlParts = AJXP_Utils::safeParseUrl($url); | ||
$repository = ConfService::getRepositoryById($urlParts["host"]); | ||
|
||
if ($repository == null) { | ||
throw new Exception("Cannot find repository"); | ||
} | ||
|
||
$repositoryId = $repository->getId(); | ||
|
||
if(AuthService::usersEnabled()) { | ||
$u = AuthService::getLoggedUser(); | ||
$userId = $u->getId(); | ||
if($u->getResolveAsParent()){ | ||
$userId = $u->getParent(); | ||
} | ||
} else { | ||
$userId = 'shared'; | ||
} | ||
|
||
// User information | ||
|
||
// Repository params | ||
$clientId = $repository->getOption('CLIENT_ID'); | ||
$clientSecret = $repository->getOption('CLIENT_SECRET'); | ||
$scope = $repository->getOption('SCOPE'); | ||
$authUrl = $repository->getOption('AUTH_URL'); | ||
$tokenUrl = $repository->getOption('TOKEN_URL'); | ||
$redirectUrl = $repository->getOption('REDIRECT_URL'); | ||
|
||
$authUrl .= '?client_id=' . $clientId . | ||
'&scope=' . $scope . | ||
'&redirect_uri=' . urlencode($redirectUrl) . | ||
'&response_type=code'; | ||
|
||
// Retrieving context | ||
$repoData = self::actualRepositoryWrapperData($urlParts["host"]); | ||
$repoProtocol = $repoData['protocol']; | ||
|
||
$default = stream_context_get_options(stream_context_get_default()); | ||
|
||
// Retrieving subscriber | ||
$oauth2 = $default[$repoProtocol]['oauth2_subscriber']; | ||
|
||
if (!empty($oauth2)) { | ||
// Authentication already made for this request - move on | ||
return true; | ||
} | ||
|
||
// Retrieving tokens | ||
$tokensKey = self::getTokenKey($repositoryId, $userId); | ||
$tokens = self::getTokens($tokensKey); | ||
|
||
$accessToken = $tokens[0]; | ||
$refreshToken = $tokens[1]; | ||
|
||
// OAuth 2 Tokens | ||
$oauth2Client = new GuzzleClient(['base_url' => $tokenUrl]); | ||
|
||
$config = [ | ||
'client_id' => $clientId, | ||
'client_secret' => $clientSecret, | ||
'scope' => $scope, | ||
'redirect_uri' => $redirectUrl, | ||
'token_url' => '', | ||
'auth_location' => 'body', | ||
]; | ||
|
||
// Setting up the subscriber | ||
if (empty($refreshToken) || !empty($_SESSION['oauth_code'])) { | ||
// Authorization code | ||
$config['code'] = $_SESSION['oauth_code']; | ||
|
||
$accessToken = new AuthorizationCode($oauth2Client, $config); | ||
$refreshToken = new RefreshToken($oauth2Client, $config); | ||
|
||
$oauth2 = new Oauth2Subscriber($accessToken, $refreshToken); | ||
|
||
unset($_SESSION['oauth_code']); | ||
} else { | ||
// Refresh Token | ||
$config['refresh_token'] = $refreshToken; | ||
|
||
$oauth2 = new Oauth2Subscriber(null, new RefreshToken($oauth2Client, $config)); | ||
|
||
$oauth2->setAccessToken($accessToken); | ||
$oauth2->setRefreshToken($refreshToken); | ||
} | ||
|
||
// Retrieving access token and checking access | ||
try { | ||
$accessToken = $oauth2->getAccessToken(); | ||
$refreshToken = $oauth2->getRefreshToken(); | ||
} catch (\Exception $e) { | ||
throw new AJXP_UserAlertException("Please go to <a style=\"text-decoration:underline;\" target=\"_blank\" href=\"" . $authUrl . "\">" . $authUrl . "</a> to authorize the access to your onedrive. Then try again to switch to this workspace"); | ||
} | ||
|
||
// Saving tokens for later use | ||
self::setTokens($tokensKey, $accessToken->getToken(), $refreshToken->getToken()); | ||
|
||
// Saving subscriber in context | ||
$default[$repoProtocol]['oauth2_subscriber'] = $oauth2; | ||
|
||
// Retrieving client | ||
$client = $default[$repoProtocol]['client']; | ||
$httpClient = $client->getHttpClient(); | ||
$httpClient->getEmitter()->attach($oauth2); | ||
|
||
stream_context_set_default($default); | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* @return string key | ||
*/ | ||
private static function getTokenKey($repositoryId, $userId) { | ||
return 'OAUTH_ONEDRIVE_' . $repositoryId . '_' . $userId . '_TOKENS'; | ||
} | ||
/** | ||
* @return Array | ||
*/ | ||
private static function getTokens($key) | ||
{ | ||
// TOKENS IN SESSION? | ||
if (!empty($_SESSION[$key])) return $_SESSION[$key]; | ||
|
||
// TOKENS IN CACHE? | ||
if ($tokens = CacheService::fetch($key)) return $tokens; | ||
|
||
// TOKENS IN FILE ? | ||
return AJXP_Utils::loadSerialFile(AJXP_DATA_PATH . '/plugins/access.onedrive/' . $key); | ||
} | ||
|
||
/** | ||
* @param $oauth_tokens | ||
* @return bool | ||
* @throws Exception | ||
*/ | ||
private function setTokens($key, $accessToken, $refreshToken) | ||
{ | ||
$value = [$accessToken, $refreshToken]; | ||
|
||
// Save in file | ||
AJXP_Utils::saveSerialFile(AJXP_DATA_PATH . '/plugins/access.onedrive/' . $key, $value, true); | ||
|
||
// Save in cache | ||
CacheService::save($key, $value); | ||
|
||
// Save in session | ||
$_SESSION["OAUTH_ONEDRIVE_TOKENS"] = $value; | ||
|
||
return true; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.