Merge pull request 'store plaintext secret key in .env, hash at startup' (#6) from dev into release

Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
2026-06-25 16:44:19 +03:00
4 changed files with 14 additions and 10 deletions
+2 -2
View File
@@ -11,5 +11,5 @@ POSTGRES_USER="user"
POSTGRES_PASSWORD="pwd" POSTGRES_PASSWORD="pwd"
# TOKEN_LIFETIME in minutes # TOKEN_LIFETIME in minutes
TOKEN_LIFETIME=600 TOKEN_LIFETIME=600
# Secret key for registration (bcrypt hash, client sends plaintext key) # Secret key for registration (plaintext, hashed with bcrypt at startup)
REGISTRATION_SECRET_KEY=$2a$10$example.bcrypt.hash.here REGISTRATION_SECRET_KEY=your-registration-key
+2 -2
View File
@@ -11,5 +11,5 @@ POSTGRES_USER="postgres"
POSTGRES_PASSWORD="postgres" POSTGRES_PASSWORD="postgres"
# TOKEN_LIFETIME in minutes # TOKEN_LIFETIME in minutes
TOKEN_LIFETIME=600 TOKEN_LIFETIME=600
# Secret key for registration (bcrypt hash, client sends plaintext) # Secret key for registration (plaintext, hashed with bcrypt at startup)
REGISTRATION_SECRET_KEY=$2a$10$mSo1MvV6U7GazfxceLFDl.gBNPm6lnjClWYsFQesx0SalObvBLIF6 REGISTRATION_SECRET_KEY=FtracKer*1405.
+9 -5
View File
@@ -12,8 +12,15 @@ import 'dart:io';
class AuthRoutes { class AuthRoutes {
final DatabaseProvider database; final DatabaseProvider database;
final Map<String, DateTime> _lastRequest = {}; final Map<String, DateTime> _lastRequest = {};
final String _registrationKeyHash;
AuthRoutes(this.database); AuthRoutes(this.database) : _registrationKeyHash = _loadRegistrationKeyHash();
static String _loadRegistrationKeyHash() {
final dotenv = DotEnv();
final key = dotenv['REGISTRATION_SECRET_KEY'] ?? '';
return BCrypt.hashpw(key, BCrypt.gensalt());
}
Router get routes { Router get routes {
final router = Router(); final router = Router();
@@ -112,10 +119,7 @@ class AuthRoutes {
return response; return response;
} }
final envDotenv = DotEnv(); if (!BCrypt.checkpw(secretKey, _registrationKeyHash)) {
final storedHash = envDotenv['REGISTRATION_SECRET_KEY'] ?? '';
if (!BCrypt.checkpw(secretKey, storedHash)) {
stopwatch.stop(); stopwatch.stop();
final response = Response(403, body: jsonEncode({'error': 'Invalid registration key'}), headers: {'Content-Type': 'application/json'}); final response = Response(403, body: jsonEncode({'error': 'Invalid registration key'}), headers: {'Content-Type': 'application/json'});
logRequest(method: 'POST', url: '/reg', status: 403, duration: stopwatch.elapsed, body: body, responseHeaders: response.headers); logRequest(method: 'POST', url: '/reg', status: 403, duration: stopwatch.elapsed, body: body, responseHeaders: response.headers);
+1 -1
View File
@@ -41,7 +41,7 @@ void main() {
setUpAll(() async { setUpAll(() async {
final env = DotEnv(); final env = DotEnv();
env.load(['bin/.env']); env.load(['bin/.env']);
registrationSecretKey = 'FtracKer*1405.'; registrationSecretKey = env['REGISTRATION_SECRET_KEY'] ?? 'FtracKer*1405.';
stdout.writeln("Starting server..."); stdout.writeln("Starting server...");
p = await Process.start( p = await Process.start(