Skip to content

Commit

Permalink
feat: kill inactive access tokens (#32)
Browse files Browse the repository at this point in the history
* feat: kill inactive access tokens

* Apply fixes from StyleCI

* fix: typo

* chore: update README

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
imorland and StyleCIBot committed Jun 15, 2024
1 parent a695c9d commit b43ff41
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This extension requires a minimum of PHP 8.1, due to a 3rd party library constra
- 2FA Enabled/Disabled notifications
- 2FA Status page
- Backup/recovery codes
- Option to revoke dormant access tokens after X days of no usage

## Permissions

Expand All @@ -41,6 +42,14 @@ php flarum cache:clear

## Usage

### CLI
Independantly of the setting, you may remove dormant access tokens using the CLI. The days setting defaults to 30 days, and the CLI will still respect this value from the extension settings, as well as the developer token setting:
```bash
php flarum twofactor:kill-inactive-tokens
```

![cli](https://private-user-images.githubusercontent.com/16573496/339968512-ef914d1e-cc65-4621-9484-4b8eeb7642f9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTg0NDE1ODQsIm5iZiI6MTcxODQ0MTI4NCwicGF0aCI6Ii8xNjU3MzQ5Ni8zMzk5Njg1MTItZWY5MTRkMWUtY2M2NS00NjIxLTk0ODQtNGI4ZWViNzY0MmY5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA2MTUlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNjE1VDA4NDgwNFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTYyMjA5NmMzMzg1ZjJhMzdjMDRmNGI1ZGQyNDVjM2U4NjRlYjIxZWE3NDQ2ODI5NDkyNzk0ZjE4YjE4NWI0ZTMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Bb8Wgml7ohvCF7m89EXhRhNBS7zo95tDx777g5gj8vg)

TODO

## Screenshots
Expand Down
9 changes: 8 additions & 1 deletion extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,14 @@

(new Extend\Settings())
->default('ianm-twofactor.admin.settings.forum_logo_qr', true)
->default('ianm-twofactor.admin.settings.forum_logo_qr_width', 100),
->default('ianm-twofactor.admin.settings.forum_logo_qr_width', 100)
->default('ianm-twofactor.kill_inactive_tokens', true)
->default('ianm-twofactor.kill_inactive_tokens_age_days', 30)
->default('ianm-twofactor.also_kill_developer_tokens', false),

(new Extend\Console())
->command(Console\KillInactiveTokensCommand::class)
->schedule(Console\KillInactiveTokensCommand::class, Console\InactiveTokensSchedule::class),

(new Extend\Conditional())
->whenExtensionEnabled('fof-oauth', fn () => [
Expand Down
21 changes: 21 additions & 0 deletions js/src/admin/components/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ export default class SettingsPage extends ExtensionPage {
help: app.translator.trans('ianm-twofactor.admin.settings.forum_logo_qr_width_help'),
max: 200,
})}
<h3>{app.translator.trans('ianm-twofactor.admin.settings.tokens.heading')}</h3>
<p className="helpText">{app.translator.trans('ianm-twofactor.admin.settings.tokens.help')}</p>
{this.buildSettingComponent({
setting: 'ianm-twofactor.kill_inactive_tokens',
type: 'boolean',
label: app.translator.trans('ianm-twofactor.admin.settings.tokens.kill_inactive_tokens'),
help: app.translator.trans('ianm-twofactor.admin.settings.tokens.kill_inactive_tokens_help'),
})}
{this.buildSettingComponent({
setting: 'ianm-twofactor.kill_inactive_tokens_age_days',
type: 'number',
min: 1,
label: app.translator.trans('ianm-twofactor.admin.settings.tokens.kill_inactive_tokens_age_days'),
help: app.translator.trans('ianm-twofactor.admin.settings.tokens.kill_inactive_tokens_age_days_help'),
})}
{this.buildSettingComponent({
setting: 'ianm-twofactor.also_kill_developer_tokens',
type: 'boolean',
label: app.translator.trans('ianm-twofactor.admin.settings.tokens.also_kill_developer_tokens'),
help: app.translator.trans('ianm-twofactor.admin.settings.tokens.also_kill_developer_tokens_help'),
})}
{this.submitButton()}
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ ianm-twofactor:
forum_logo_qr_width_help: The width of the forum logo embedded on the QR code displayed when enabling 2FA. Max 200.
logo_qr: Logo on QR Code
logo_qr_help: If logo has been uploaded, this logo will be embedded on the QR code. Leave blank to use the forum logo.
tokens:
heading: Access Tokens
help: For extended security, you can manage additional behaviour here related to access tokens.
kill_inactive_tokens: Kill Inactive Tokens
kill_inactive_tokens_help: Automatically kill access tokens that have been inactive for a specified period of time.
kill_inactive_tokens_age_days: Kill Inactive Tokens After (Days)
kill_inactive_tokens_age_days_help: The number of days of inactivity after which access tokens will be deleted.
also_kill_developer_tokens: Also Kill Developer Tokens
also_kill_developer_tokens_help: Also kill developer access tokens that have been inactive for the specified period of time.


forum:
user_2fa.alert_message: You must enable 2FA to continue accessing your account.
Expand Down
32 changes: 32 additions & 0 deletions src/Console/InactiveTokensSchedule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of ianm/twofactor.
*
* Copyright (c) 2023 IanM.
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace IanM\TwoFactor\Console;

use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Console\Scheduling\Event;

class InactiveTokensSchedule
{
public function __construct(
protected SettingsRepositoryInterface $settings
) {
}

public function __invoke(Event $event)
{
if (! (bool) $this->settings->get('ianm-twofactor.kill_inactive_tokens')) {
return;
}

$event->twiceDaily();
}
}
59 changes: 59 additions & 0 deletions src/Console/KillInactiveTokensCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/*
* This file is part of ianm/twofactor.
*
* Copyright (c) 2023 IanM.
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace IanM\TwoFactor\Console;

use Carbon\Carbon;
use Flarum\Http\AccessToken;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Console\Command;

class KillInactiveTokensCommand extends Command
{
protected $signature = 'twofactor:kill-inactive-tokens';
protected $description = 'Kill all inactive tokens';

public function __construct(
protected SettingsRepositoryInterface $settings
) {
parent::__construct();
}

public function handle(): void
{
$age = (int) $this->settings->get('ianm-twofactor.kill_inactive_tokens_age_days');
$maxAge = Carbon::now()->subDays($age);

$query = AccessToken::query()
->where('last_activity_at', '<', $maxAge);

if (! (bool) $this->settings->get('ianm-twofactor.also_kill_developer_tokens')) {
$this->info('Not deleting any developer tokens.');
$query->where('type', '!=', 'developer');
}

$count = $query->count();

if ($count === 0) {
$this->info("No tokens found which have not been used in $age+ days.");

return;
}

$this->info("Found $count tokens which have not been used in $age+ days. Deleting...");

$this->output->progressStart($count);

$query->delete();

$this->output->progressFinish();
}
}

0 comments on commit b43ff41

Please sign in to comment.