Compare commits

...

7 Commits

Author SHA1 Message Date
jc21
47b367d61e Merge pull request #5276 from NginxProxyManager/develop
v2.13.7
2026-02-06 07:11:49 +10:00
Jamie Curnow
d19f5c1960 Fix upgrade problem with otplib existing secrets
All checks were successful
Close stale issues and PRs / stale (push) Successful in 39s
2026-02-05 13:12:54 +10:00
Jamie Curnow
77662b4e7f Use better-sqlite3 package for sqlite databases 2026-02-05 13:11:57 +10:00
Jamie Curnow
c88de65d3a Fix #5274 2fa backup codes not validating properly 2026-02-05 10:51:15 +10:00
jc21
ac4efd2333 Merge branch 'master' into develop 2026-02-05 08:27:41 +10:00
Jamie Curnow
eab38d8934 Bump version 2026-02-05 08:26:49 +10:00
jc21
f3efaae320 Merge pull request #5141 from NginxProxyManager/develop
v2.13.6
2026-01-14 14:30:49 +10:00
9 changed files with 42 additions and 18 deletions

View File

@@ -1 +1 @@
2.13.6
2.13.7

View File

@@ -1,7 +1,7 @@
<p align="center">
<img src="https://nginxproxymanager.com/github.png">
<br><br>
<img src="https://img.shields.io/badge/version-2.13.6-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.13.7-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a>

View File

@@ -1,6 +1,6 @@
import crypto from "node:crypto";
import bcrypt from "bcrypt";
import { generateSecret, generateURI, verify } from "otplib";
import { createGuardrails, generateSecret, generateURI, verify } from "otplib";
import errs from "../lib/error.js";
import authModel from "../models/auth.js";
import internalUser from "./user.js";
@@ -198,20 +198,30 @@ const internal2fa = {
return false;
}
// Try TOTP code first
const result = await verify({
token,
secret,
});
// Try TOTP code first, if it's 6 chars. it will throw errors if it's not 6 chars
// and the backup codes are 8 chars.
if (token.length === 6) {
const result = await verify({
token,
secret,
// These guardrails lower the minimum length requirement for secrets.
// In v12 of otplib the default minimum length is 10 and in v13 it is 16.
// Since there are 2fa secrets in the wild generated with v12 we need to allow shorter secrets
// so people won't be locked out when upgrading.
guardrails: createGuardrails({
MIN_SECRET_BYTES: 10,
}),
});
if (result.valid) {
return true;
if (result.valid) {
return true;
}
}
// Try backup codes
const backupCodes = auth?.meta?.backup_codes || [];
for (let i = 0; i < backupCodes.length; i++) {
const match = await bcrypt.compare(code.toUpperCase(), backupCodes[i]);
const match = await bcrypt.compare(token.toUpperCase(), backupCodes[i]);
if (match) {
// Remove used backup code
const updatedCodes = [...backupCodes];
@@ -275,7 +285,11 @@ const internal2fa = {
},
getUserPasswordAuth: async (userId) => {
const auth = await authModel.query().where("user_id", userId).andWhere("type", "password").first();
const auth = await authModel
.query()
.where("user_id", userId)
.andWhere("type", "password")
.first();
if (!auth) {
throw new errs.ItemNotFoundError("Auth not found");

View File

@@ -5,7 +5,7 @@ import { global as logger } from "../logger.js";
const keysFile = '/data/keys.json';
const mysqlEngine = 'mysql2';
const postgresEngine = 'pg';
const sqliteClientName = 'sqlite3';
const sqliteClientName = 'better-sqlite3';
let instance = null;
@@ -84,6 +84,7 @@ const configure = () => {
}
const envSqliteFile = process.env.DB_SQLITE_FILE || "/data/database.sqlite";
logger.info(`Using Sqlite: ${envSqliteFile}`);
instance = {
database: {

View File

@@ -17,6 +17,7 @@
"archiver": "^7.0.1",
"batchflow": "^0.4.0",
"bcrypt": "^6.0.0",
"better-sqlite3": "^12.6.2",
"body-parser": "^2.2.2",
"compression": "^1.7.4",
"express": "^5.2.1",

View File

@@ -17,7 +17,7 @@
},
"code": {
"minLength": 6,
"maxLength": 6,
"maxLength": 8,
"type": "string",
"example": "012345"
}

View File

@@ -16,7 +16,7 @@
}
],
"requestBody": {
"description": "Verififcation Payload",
"description": "Verification Payload",
"required": true,
"content": {
"application/json": {
@@ -25,7 +25,7 @@
"properties": {
"code": {
"minLength": 6,
"maxLength": 6,
"maxLength": 8,
"type": "string",
"example": "123456"
}

View File

@@ -16,7 +16,7 @@
}
],
"requestBody": {
"description": "Verififcation Payload",
"description": "Verification Payload",
"required": true,
"content": {
"application/json": {
@@ -25,7 +25,7 @@
"properties": {
"code": {
"minLength": 6,
"maxLength": 6,
"maxLength": 8,
"type": "string",
"example": "123456"
}

View File

@@ -414,6 +414,14 @@ bcrypt@^6.0.0:
node-addon-api "^8.3.0"
node-gyp-build "^4.8.4"
better-sqlite3@^12.6.2:
version "12.6.2"
resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-12.6.2.tgz#770649f28a62e543a360f3dfa1afe4cc944b1937"
integrity sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==
dependencies:
bindings "^1.5.0"
prebuild-install "^7.1.1"
binary-extensions@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"