Skip to content

Commit 72e8aab

Browse files
feat(auth): support permanent OCM refresh tokens and bearer login
Co-authored-by: Micke Nordin <kano@sunet.se> Signed-off-by: Micke Nordin <kano@sunet.se> Signed-off-by: Enrique Pérez Arnaud <enrique@cazalla.net>
1 parent 1e8b4a0 commit 72e8aab

5 files changed

Lines changed: 43 additions & 5 deletions

File tree

lib/private/Authentication/Token/PublicKeyToken.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ public function getRemember(): int {
204204
return parent::getRemember();
205205
}
206206

207+
#[\Override]
208+
public function getType(): int {
209+
return $this->getter('type');
210+
}
211+
207212
#[\Override]
208213
public function setToken(string $token): void {
209214
parent::setToken($token);

lib/private/User/Session.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,10 @@ public function tryTokenLogin(IRequest $request) {
838838
return false;
839839
}
840840

841-
if ($dbToken instanceof PublicKeyToken && $dbToken->getType() === IToken::TEMPORARY_TOKEN && !$tokenFromCookie) {
841+
if ($dbToken instanceof PublicKeyToken
842+
&& $dbToken->getType() === IToken::TEMPORARY_TOKEN
843+
&& !$tokenFromCookie
844+
&& $dbToken->getName() !== IToken::OCM_ACCESS_TOKEN_NAME) {
842845
// Session token but from Bearer header, not allowed
843846
return false;
844847
}

lib/public/Authentication/Token/IToken.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ interface IToken extends JsonSerializable {
4747
*/
4848
public const SCOPE_SKIP_PASSWORD_VALIDATION = 'password-unconfirmable';
4949

50+
/**
51+
* Token name used for OCM access tokens issued via the
52+
* federated token endpoint. Marks a TEMPORARY_TOKEN as legitimate
53+
* Bearer-header auth (vs. a browser session id leaked into a header).
54+
*
55+
* @since 33.0.0
56+
*/
57+
public const OCM_ACCESS_TOKEN_NAME = 'OCM Access Token';
58+
5059
/**
5160
* Get the token ID
5261
* @since 28.0.0
@@ -130,4 +139,11 @@ public function setPassword(string $password): void;
130139
* @since 28.0.0
131140
*/
132141
public function setExpires(?int $expires): void;
142+
143+
/**
144+
* Get the type of the token
145+
* @return int One of IToken::TEMPORARY_TOKEN, IToken::PERMANENT_TOKEN, or IToken::WIPE_TOKEN
146+
* @since 32.0.0
147+
*/
148+
public function getType(): int;
133149
}

tests/lib/Authentication/Token/PublicKeyTokenProviderTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ public function testRenewSessionTokenWithPassword(): void {
452452

453453
public function testGetToken(): void {
454454
$token = new PublicKeyToken();
455+
$token->setType(IToken::TEMPORARY_TOKEN);
455456

456457
$this->config->method('getSystemValue')
457458
->with('secret')

tests/lib/User/SessionTest.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,17 @@ public function testPasswordlessLoginNoLastCheckUpdate(): void {
332332
->getMock();
333333
$userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
334334

335-
$session->expects($this->never())
336-
->method('set');
335+
$user = $this->createMock(IUser::class);
336+
$user->method('getUID')->willReturn('foo');
337+
$user->method('isEnabled')->willReturn(true);
338+
$manager->method('get')
339+
->with('foo')
340+
->willReturn($user);
341+
337342
$session->expects($this->once())
338343
->method('regenerateId');
339344
$token = new PublicKeyToken();
345+
$token->setId(1);
340346
$token->setLoginName('foo');
341347
$token->setLastCheck(0); // Never
342348
$token->setUid('foo');
@@ -370,11 +376,17 @@ public function testLoginLastCheckUpdate(): void {
370376
->getMock();
371377
$userSession = new Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random, $this->lockdownManager, $this->logger, $this->dispatcher);
372378

373-
$session->expects($this->never())
374-
->method('set');
379+
$user = $this->createMock(IUser::class);
380+
$user->method('getUID')->willReturn('foo');
381+
$user->method('isEnabled')->willReturn(true);
382+
$manager->method('get')
383+
->with('foo')
384+
->willReturn($user);
385+
375386
$session->expects($this->once())
376387
->method('regenerateId');
377388
$token = new PublicKeyToken();
389+
$token->setId(1);
378390
$token->setLoginName('foo');
379391
$token->setLastCheck(0); // Never
380392
$token->setUid('foo');
@@ -1325,4 +1337,5 @@ public function testLogClientInThrottlerEmail(): void {
13251337

13261338
$this->assertFalse($userSession->logClientIn('john@foo.bar', 'I-AM-A-PASSWORD', $request, $this->throttler));
13271339
}
1340+
13281341
}

0 commit comments

Comments
 (0)