summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoeland Jago Douma <roeland@famdouma.nl>2018-05-15 21:10:43 +0200
committerRoeland Jago Douma <roeland@famdouma.nl>2018-05-16 19:27:19 +0200
commitaba255997aa82981c6b1fa3ce5e32bc0077156d1 (patch)
tree80245f04d3f7b400723ca4c3fd55b90ecedcb8cc
parent0011bfb64bedbfa412ffd2190433fe0b51830ce9 (diff)
downloadnextcloud-server-aba255997aa82981c6b1fa3ce5e32bc0077156d1.tar.gz
nextcloud-server-aba255997aa82981c6b1fa3ce5e32bc0077156d1.zip
Allow the rotation of tokens
This for example will allow rotating the apptoken for oauth Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
-rw-r--r--lib/private/Authentication/Token/DefaultToken.php10
-rw-r--r--lib/private/Authentication/Token/DefaultTokenProvider.php22
-rw-r--r--lib/private/Authentication/Token/IProvider.php10
-rw-r--r--lib/private/Authentication/Token/IToken.php23
-rw-r--r--tests/lib/Authentication/Token/DefaultTokenProviderTest.php42
5 files changed, 105 insertions, 2 deletions
diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php
index e2753ba979c..993dc7580ce 100644
--- a/lib/private/Authentication/Token/DefaultToken.php
+++ b/lib/private/Authentication/Token/DefaultToken.php
@@ -30,9 +30,7 @@ use OCP\AppFramework\Db\Entity;
* @method void setId(int $id)
* @method void setUid(string $uid);
* @method void setLoginName(string $loginname)
- * @method void setPassword(string $password)
* @method void setName(string $name)
- * @method void setToken(string $token)
* @method string getToken()
* @method void setType(int $type)
* @method int getType()
@@ -173,4 +171,12 @@ class DefaultToken extends Entity implements IToken {
public function getRemember(): int {
return parent::getRemember();
}
+
+ public function setToken(string $token) {
+ parent::setToken($token);
+ }
+
+ public function setPassword(string $password = null) {
+ parent::setPassword($password);
+ }
}
diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php
index 747fb8ef6ea..5167361449b 100644
--- a/lib/private/Authentication/Token/DefaultTokenProvider.php
+++ b/lib/private/Authentication/Token/DefaultTokenProvider.php
@@ -274,6 +274,28 @@ class DefaultTokenProvider implements IProvider {
}
/**
+ * 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
* @return string
*/
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index 9b9048b1635..5215b61613e 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -145,4 +145,14 @@ interface IProvider {
* @throws InvalidTokenException
*/
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;
}
diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php
index b40f55fb6ca..b5a1d47640d 100644
--- a/lib/private/Authentication/Token/IToken.php
+++ b/lib/private/Authentication/Token/IToken.php
@@ -96,7 +96,30 @@ interface IToken extends JsonSerializable {
*/
public function setScope($scope);
+ /**
+ * Get the name of the token
+ * @return string
+ */
public function getName(): string;
+ /**
+ * Get the remember state of the token
+ *
+ * @return 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);
}
diff --git a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
index a2128e0fd4c..ee98f649443 100644
--- a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
+++ b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
@@ -416,4 +416,46 @@ class DefaultTokenProviderTest extends TestCase {
$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');
+ }
}