Allow the rotation of tokens
This for example will allow rotating the apptoken for oauth Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
parent
0011bfb64b
commit
aba255997a
|
@ -30,9 +30,7 @@ use OCP\AppFramework\Db\Entity;
|
||||||
* @method void setId(int $id)
|
* @method void setId(int $id)
|
||||||
* @method void setUid(string $uid);
|
* @method void setUid(string $uid);
|
||||||
* @method void setLoginName(string $loginname)
|
* @method void setLoginName(string $loginname)
|
||||||
* @method void setPassword(string $password)
|
|
||||||
* @method void setName(string $name)
|
* @method void setName(string $name)
|
||||||
* @method void setToken(string $token)
|
|
||||||
* @method string getToken()
|
* @method string getToken()
|
||||||
* @method void setType(int $type)
|
* @method void setType(int $type)
|
||||||
* @method int getType()
|
* @method int getType()
|
||||||
|
@ -173,4 +171,12 @@ class DefaultToken extends Entity implements IToken {
|
||||||
public function getRemember(): int {
|
public function getRemember(): int {
|
||||||
return parent::getRemember();
|
return parent::getRemember();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setToken(string $token) {
|
||||||
|
parent::setToken($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPassword(string $password = null) {
|
||||||
|
parent::setPassword($password);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,28 @@ class DefaultTokenProvider implements IProvider {
|
||||||
$this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
|
$this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate the token. Usefull for for example oauth tokens
|
||||||
|
*
|
||||||
|
* @param IToken $token
|
||||||
|
* @param string $oldTokenId
|
||||||
|
* @param string $newTokenId
|
||||||
|
* @return IToken
|
||||||
|
*/
|
||||||
|
public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
|
||||||
|
try {
|
||||||
|
$password = $this->getPassword($token, $oldTokenId);
|
||||||
|
$token->setPassword($this->encryptPassword($password, $newTokenId));
|
||||||
|
} catch (PasswordlessTokenException $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$token->setToken($this->hashToken($newTokenId));
|
||||||
|
$this->updateToken($token);
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $token
|
* @param string $token
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
@ -145,4 +145,14 @@ interface IProvider {
|
||||||
* @throws InvalidTokenException
|
* @throws InvalidTokenException
|
||||||
*/
|
*/
|
||||||
public function setPassword(IToken $token, string $tokenId, string $password);
|
public function setPassword(IToken $token, string $tokenId, string $password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate the token. Usefull for for example oauth tokens
|
||||||
|
*
|
||||||
|
* @param IToken $token
|
||||||
|
* @param string $oldTokenId
|
||||||
|
* @param string $newTokenId
|
||||||
|
* @return IToken
|
||||||
|
*/
|
||||||
|
public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,30 @@ interface IToken extends JsonSerializable {
|
||||||
*/
|
*/
|
||||||
public function setScope($scope);
|
public function setScope($scope);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the token
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getName(): string;
|
public function getName(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remember state of the token
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getRemember(): int;
|
public function getRemember(): int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the token
|
||||||
|
*
|
||||||
|
* @param string $token
|
||||||
|
*/
|
||||||
|
public function setToken(string $token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the password
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
*/
|
||||||
|
public function setPassword(string $password);
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,4 +416,46 @@ class DefaultTokenProviderTest extends TestCase {
|
||||||
|
|
||||||
$this->tokenProvider->getTokenById(42);
|
$this->tokenProvider->getTokenById(42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRotate() {
|
||||||
|
$token = new DefaultToken();
|
||||||
|
$token->setPassword('oldencryptedpassword');
|
||||||
|
|
||||||
|
$this->config->method('getSystemValue')
|
||||||
|
->with('secret')
|
||||||
|
->willReturn('mysecret');
|
||||||
|
|
||||||
|
$this->crypto->method('decrypt')
|
||||||
|
->with('oldencryptedpassword', 'oldtokenmysecret')
|
||||||
|
->willReturn('mypassword');
|
||||||
|
$this->crypto->method('encrypt')
|
||||||
|
->with('mypassword', 'newtokenmysecret')
|
||||||
|
->willReturn('newencryptedpassword');
|
||||||
|
|
||||||
|
$this->mapper->expects($this->once())
|
||||||
|
->method('update')
|
||||||
|
->with($this->callback(function (DefaultToken $token) {
|
||||||
|
return $token->getPassword() === 'newencryptedpassword' &&
|
||||||
|
$token->getToken() === hash('sha512', 'newtokenmysecret');
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->tokenProvider->rotate($token, 'oldtoken', 'newtoken');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRotateNoPassword() {
|
||||||
|
$token = new DefaultToken();
|
||||||
|
|
||||||
|
$this->config->method('getSystemValue')
|
||||||
|
->with('secret')
|
||||||
|
->willReturn('mysecret');
|
||||||
|
|
||||||
|
$this->mapper->expects($this->once())
|
||||||
|
->method('update')
|
||||||
|
->with($this->callback(function (DefaultToken $token) {
|
||||||
|
return $token->getPassword() === null &&
|
||||||
|
$token->getToken() === hash('sha512', 'newtokenmysecret');
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->tokenProvider->rotate($token, 'oldtoken', 'newtoken');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue