Skip to content

Commit

Permalink
fix(oauth2): adjust db schemas when migrating from owncloud
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Steinmetz <[email protected]>
  • Loading branch information
st3iny committed Jan 15, 2025
1 parent 9cb57a4 commit 4e866bd
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
3 changes: 2 additions & 1 deletion lib/private/Repair.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
use OCP\Notification\IManager as INotificationManager;
use OCP\Security\ICrypto;
use Psr\Log\LoggerInterface;
use Throwable;

Expand Down Expand Up @@ -167,7 +168,7 @@ public static function getRepairSteps(): array {
\OC::$server->getUserManager(),
\OC::$server->getConfig()
),
new MigrateOauthTables(\OC::$server->get(Connection::class)),
new MigrateOauthTables(\OC::$server->get(Connection::class), \OC::$server->get(ICrypto::class)),
new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
new AddLogRotateJob(\OC::$server->getJobList()),
new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OCP\Server::get(JSCombiner::class)),
Expand Down
61 changes: 58 additions & 3 deletions lib/private/Repair/Owncloud/MigrateOauthTables.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
use OCP\Security\ICrypto;

class MigrateOauthTables implements IRepairStep {
/** @var Connection */
Expand All @@ -18,7 +19,10 @@ class MigrateOauthTables implements IRepairStep {
/**
* @param Connection $db
*/
public function __construct(Connection $db) {
public function __construct(
Connection $db,
private readonly ICrypto $crypto,
) {
$this->db = $db;
}

Expand Down Expand Up @@ -56,6 +60,22 @@ public function run(IOutput $output) {
if (!$table->hasIndex('oauth2_access_client_id_idx')) {
$table->addIndex(['client_id'], 'oauth2_access_client_id_idx');
}
if (!$table->hasColumn('token_id')) {
$table->addColumn('token_id', 'integer', [
'notnull' => true,
]);
}
if ($table->hasColumn('user_id')) {
$table->dropColumn('user_id');
}
if ($table->hasColumn('expires')) {
$table->dropColumn('expires');
}
if ($table->hasColumn('token')) {
// Warning: We are dropping auth tokens. However, they should only be valid for an hour,
// and we can't really migrate them to oc_authtoken anyway.
$table->dropColumn('token');
}

$output->info('Update the oauth2_clients table schema.');
$table = $schema->getTable('oauth2_clients');
Expand Down Expand Up @@ -99,10 +119,10 @@ public function run(IOutput $output) {
$table->addIndex(['client_identifier'], 'oauth2_client_id_idx');
}

$this->db->migrateToSchema($schema->getWrappedSchema());

// Regenerate schema after migrating to it
$this->db->migrateToSchema($schema->getWrappedSchema());
$schema = new SchemaWrapper($this->db);

if ($schema->getTable('oauth2_clients')->hasColumn('identifier')) {
$output->info("Move identifier column's data to the new client_identifier column.");
// 1. Fetch all [id, identifier] couple.
Expand All @@ -124,7 +144,10 @@ public function run(IOutput $output) {
$output->info('Drop the identifier column.');
$table = $schema->getTable('oauth2_clients');
$table->dropColumn('identifier');

// Regenerate schema after migrating to it
$this->db->migrateToSchema($schema->getWrappedSchema());
$schema = new SchemaWrapper($this->db);
}

$output->info('Delete clients (and their related access tokens) with the redirect_uri starting with oc:// or ending with *');
Expand Down Expand Up @@ -157,5 +180,37 @@ public function run(IOutput $output) {
$qbDeleteClients->expr()->iLike('redirect_uri', $qbDeleteClients->createNamedParameter('%*', IQueryBuilder::PARAM_STR))
);
$qbDeleteClients->executeStatement();

// Migrate plain client secrets and widen the column
$clientsTable = $schema->getTable('oauth2_clients');
if ($clientsTable->getColumn('secret')->getLength() === 64) {
$output->info("Migrate client secrets.");

// Widen the column first
$clientsTable->getColumn('secret')->setLength(512);

// Regenerate schema after migrating to it
$this->db->migrateToSchema($schema->getWrappedSchema());
$schema = new SchemaWrapper($this->db);

$qb = $this->db->getQueryBuilder();
$qb->update('oauth2_clients')
->set('secret', $qb->createParameter('secret'))
->where($qb->expr()->eq('id', $qb->createParameter('id')));

$qbSelect = $this->db->getQueryBuilder();
$qbSelect->select('id', 'secret')
->from('oauth2_clients');
$result = $qbSelect->executeQuery();
while ($row = $result->fetch()) {
$id = $row['id'];
$secret = $row['secret'];
$encryptedSecret = bin2hex($this->crypto->calculateHMAC($secret));
$qb->setParameter('id', $id);
$qb->setParameter('secret', $encryptedSecret);
$qb->executeStatement();
}
$result->closeCursor();
}
}
}

0 comments on commit 4e866bd

Please sign in to comment.