Rotate token

On a refresh token request:
* rorate
* reset expire

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
Roeland Jago Douma 2018-05-16 15:09:03 +02:00
parent c28b25c4f0
commit f7ecec855b
No known key found for this signature in database
GPG Key ID: F941078878347C0C
1 changed files with 43 additions and 11 deletions

View File

@ -21,13 +21,17 @@
namespace OCA\OAuth2\Controller; namespace OCA\OAuth2\Controller;
use OC\Authentication\Token\DefaultTokenMapper; use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\ExpiredTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
use OCA\OAuth2\Db\AccessTokenMapper; use OCA\OAuth2\Db\AccessTokenMapper;
use OCA\OAuth2\Db\ClientMapper; use OCA\OAuth2\Db\ClientMapper;
use OCA\OAuth2\Exceptions\AccessTokenNotFoundException; use OCA\OAuth2\Exceptions\AccessTokenNotFoundException;
use OCA\OAuth2\Exceptions\ClientNotFoundException;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest; use OCP\IRequest;
use OCP\Security\ICrypto; use OCP\Security\ICrypto;
use OCP\Security\ISecureRandom; use OCP\Security\ISecureRandom;
@ -39,10 +43,12 @@ class OauthApiController extends Controller {
private $clientMapper; private $clientMapper;
/** @var ICrypto */ /** @var ICrypto */
private $crypto; private $crypto;
/** @var DefaultTokenMapper */ /** @var TokenProvider */
private $defaultTokenMapper; private $tokenProvider;
/** @var ISecureRandom */ /** @var ISecureRandom */
private $secureRandom; private $secureRandom;
/** @var ITimeFactory */
private $time;
/** /**
* @param string $appName * @param string $appName
@ -50,22 +56,25 @@ class OauthApiController extends Controller {
* @param ICrypto $crypto * @param ICrypto $crypto
* @param AccessTokenMapper $accessTokenMapper * @param AccessTokenMapper $accessTokenMapper
* @param ClientMapper $clientMapper * @param ClientMapper $clientMapper
* @param DefaultTokenMapper $defaultTokenMapper * @param TokenProvider $tokenProvider
* @param ISecureRandom $secureRandom * @param ISecureRandom $secureRandom
* @param ITimeFactory $time
*/ */
public function __construct($appName, public function __construct($appName,
IRequest $request, IRequest $request,
ICrypto $crypto, ICrypto $crypto,
AccessTokenMapper $accessTokenMapper, AccessTokenMapper $accessTokenMapper,
ClientMapper $clientMapper, ClientMapper $clientMapper,
DefaultTokenMapper $defaultTokenMapper, TokenProvider $tokenProvider,
ISecureRandom $secureRandom) { ISecureRandom $secureRandom,
ITimeFactory $time) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->crypto = $crypto; $this->crypto = $crypto;
$this->accessTokenMapper = $accessTokenMapper; $this->accessTokenMapper = $accessTokenMapper;
$this->clientMapper = $clientMapper; $this->clientMapper = $clientMapper;
$this->defaultTokenMapper = $defaultTokenMapper; $this->tokenProvider = $tokenProvider;
$this->secureRandom = $secureRandom; $this->secureRandom = $secureRandom;
$this->time = $time;
} }
/** /**
@ -115,18 +124,41 @@ class OauthApiController extends Controller {
} }
$decryptedToken = $this->crypto->decrypt($accessToken->getEncryptedToken(), $code); $decryptedToken = $this->crypto->decrypt($accessToken->getEncryptedToken(), $code);
$newCode = $this->secureRandom->generate(128);
try {
$appToken = $this->tokenProvider->getTokenById($accessToken->getTokenId());
} catch (ExpiredTokenException $e) {
$appToken = $e->getToken();
} catch (InvalidTokenException $e) {
//We can't do anything...
$this->accessTokenMapper->delete($accessToken);
return new JSONResponse([
'error' => 'invalid_request',
], Http::STATUS_BAD_REQUEST);
}
$newToken = $this->secureRandom->generate(72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS);
$appToken = $this->tokenProvider->rotate(
$appToken,
$decryptedToken,
$newToken
);
$appToken->setExpires($this->time->getTime() + 3600);
$this->tokenProvider->updateToken($appToken);
$newCode = $this->secureRandom->generate(128, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS);
$accessToken->setHashedCode(hash('sha512', $newCode)); $accessToken->setHashedCode(hash('sha512', $newCode));
$accessToken->setEncryptedToken($this->crypto->encrypt($decryptedToken, $newCode)); $accessToken->setEncryptedToken($this->crypto->encrypt($newToken, $newCode));
$this->accessTokenMapper->update($accessToken); $this->accessTokenMapper->update($accessToken);
return new JSONResponse( return new JSONResponse(
[ [
'access_token' => $decryptedToken, 'access_token' => $newToken,
'token_type' => 'Bearer', 'token_type' => 'Bearer',
'expires_in' => 3600, 'expires_in' => 3600,
'refresh_token' => $newCode, 'refresh_token' => $newCode,
'user_id' => $this->defaultTokenMapper->getTokenById($accessToken->getTokenId())->getUID(), 'user_id' => $appToken->getUID(),
] ]
); );
} }