Skip to content

Commit 76229b6

Browse files
committed
Add implementation of ReplayDetectorInterface to handle JTI storage.
1 parent c61e306 commit 76229b6

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

solid/lib/JtiReplayDetector.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace OCA\Solid;
4+
5+
use DateInterval;
6+
use DateTime;
7+
use OCP\DB\QueryBuilder\IQueryBuilder;
8+
use OCP\IDBConnection;
9+
use Pdsinterop\Solid\Auth\ReplayDetectorInterface;
10+
11+
class JtiReplayDetector implements ReplayDetectorInterface
12+
{
13+
14+
////////////////////////////// CLASS PROPERTIES \\\\\\\\\\\\\\\\\\\\\\\\\\\\
15+
16+
private string $table = 'solid_jti';
17+
18+
//////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
19+
20+
public function __construct(private DateInterval $interval, private IDBConnection $connection) {}
21+
22+
public function detect(string $jti, string $targetUri): bool
23+
{
24+
// @TODO: $this->rotateBuckets();
25+
26+
$has = $this->has($jti, $targetUri);
27+
28+
$detected = $has === false;
29+
30+
if ($has === false) {
31+
$this->store($jti, $targetUri);
32+
}
33+
34+
return $detected;
35+
}
36+
37+
////////////////////////////// UTILITY METHODS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\
38+
39+
private function has(string $jti, string $uri): bool
40+
{
41+
$queryBuilder = $this->connection->getQueryBuilder();
42+
43+
$notOlderThan = (new DateTime())->sub($this->interval);
44+
45+
$cursor = $queryBuilder->select('*')
46+
->from($this->table)
47+
->where(
48+
$queryBuilder->expr()->eq('jti', $queryBuilder->createNamedParameter($jti,IQueryBuilder::PARAM_STR))
49+
)
50+
->andWhere(
51+
$queryBuilder->expr()->eq('uri', $queryBuilder->createNamedParameter($uri, IQueryBuilder::PARAM_STR))
52+
)
53+
->andWhere(
54+
$queryBuilder->expr()->gt('request_time', $queryBuilder->createParameter('notOlderThan'))
55+
)->setParameter('notOlderThan', $notOlderThan, 'datetime')
56+
->execute()
57+
;
58+
59+
$row = $cursor->fetch();
60+
61+
$cursor->closeCursor();
62+
63+
return ! empty($row);
64+
}
65+
66+
private function store(string $jti, string $uri): void
67+
{
68+
$queryBuilder = $this->connection->getQueryBuilder();
69+
70+
$queryBuilder->insert($this->table)
71+
->values([
72+
'jti' => $queryBuilder->createNamedParameter($jti),
73+
'uri' => $queryBuilder->createNamedParameter($uri),
74+
])
75+
->executeStatement()
76+
;
77+
}
78+
}

0 commit comments

Comments
 (0)