Upgrade dependencies
- Add a new migration to fix password hash length `IncreaseMagicLinkTokenLengthMigration` - Fix types
This commit is contained in:
parent
bbd9480000
commit
8ae520aa07
@ -38,7 +38,7 @@
|
|||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/mjml": "^4.0.4",
|
"@types/mjml": "^4.0.4",
|
||||||
"@types/mysql": "^2.15.10",
|
"@types/mysql": "^2.15.10",
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^20.15.0",
|
||||||
"@types/nodemailer": "^6.4.0",
|
"@types/nodemailer": "^6.4.0",
|
||||||
"@types/nunjucks": "^3.1.3",
|
"@types/nunjucks": "^3.1.3",
|
||||||
"@types/on-finished": "^2.3.1",
|
"@types/on-finished": "^2.3.1",
|
||||||
@ -58,7 +58,7 @@
|
|||||||
"jest": "^27.3.1",
|
"jest": "^27.3.1",
|
||||||
"jest-resolve": "^27.3.1",
|
"jest-resolve": "^27.3.1",
|
||||||
"jest-ts-webcompat-resolver": "^1.0.0",
|
"jest-ts-webcompat-resolver": "^1.0.0",
|
||||||
"maildev": "^1.1.0",
|
"maildev": "^2.1.0",
|
||||||
"node-fetch": "^3.0.0",
|
"node-fetch": "^3.0.0",
|
||||||
"nodemon": "^2.0.6",
|
"nodemon": "^2.0.6",
|
||||||
"sass": "^1.32.12",
|
"sass": "^1.32.12",
|
||||||
|
@ -326,8 +326,8 @@ export default abstract class Application implements Extendable<ApplicationCompo
|
|||||||
for (const file of fs.readdirSync(configDir)) {
|
for (const file of fs.readdirSync(configDir)) {
|
||||||
const fullPath = path.resolve(configDir, file);
|
const fullPath = path.resolve(configDir, file);
|
||||||
const stats = fs.lstatSync(fullPath);
|
const stats = fs.lstatSync(fullPath);
|
||||||
if (stats.uid !== process.getuid())
|
if (stats.uid !== process.getuid?.())
|
||||||
throw new SecurityError(`${fullPath} is not owned by this process (${process.getuid()}).`);
|
throw new SecurityError(`${fullPath} is not owned by this process (${process.getuid?.()}).`);
|
||||||
|
|
||||||
const mode = (stats.mode & parseInt('777', 8)).toString(8);
|
const mode = (stats.mode & parseInt('777', 8)).toString(8);
|
||||||
if (mode !== '400')
|
if (mode !== '400')
|
||||||
|
@ -4,12 +4,12 @@ import Application from "./Application.js";
|
|||||||
import AccountController from "./auth/AccountController.js";
|
import AccountController from "./auth/AccountController.js";
|
||||||
import AuthComponent from "./auth/AuthComponent.js";
|
import AuthComponent from "./auth/AuthComponent.js";
|
||||||
import AuthController from "./auth/AuthController.js";
|
import AuthController from "./auth/AuthController.js";
|
||||||
import AddUsedToMagicLinksMigration from "./auth/magic_link/AddUsedToMagicLinksMigration.js";
|
import AddUsedToMagicLinksMigration from "./auth/magic_link/migrations/AddUsedToMagicLinksMigration.js";
|
||||||
import CreateMagicLinksTableMigration from "./auth/magic_link/CreateMagicLinksTableMigration.js";
|
import CreateMagicLinksTableMigration from "./auth/magic_link/migrations/CreateMagicLinksTableMigration.js";
|
||||||
import MagicLinkAuthMethod from "./auth/magic_link/MagicLinkAuthMethod.js";
|
import MagicLinkAuthMethod from "./auth/magic_link/MagicLinkAuthMethod.js";
|
||||||
import MagicLinkController from "./auth/magic_link/MagicLinkController.js";
|
import MagicLinkController from "./auth/magic_link/MagicLinkController.js";
|
||||||
import MagicLinkWebSocketListener from "./auth/magic_link/MagicLinkWebSocketListener.js";
|
import MagicLinkWebSocketListener from "./auth/magic_link/MagicLinkWebSocketListener.js";
|
||||||
import MakeMagicLinksSessionNotUniqueMigration from "./auth/magic_link/MakeMagicLinksSessionNotUniqueMigration.js";
|
import MakeMagicLinksSessionNotUniqueMigration from "./auth/magic_link/migrations/MakeMagicLinksSessionNotUniqueMigration.js";
|
||||||
import AddApprovedFieldToUsersTableMigration from "./auth/migrations/AddApprovedFieldToUsersTableMigration.js";
|
import AddApprovedFieldToUsersTableMigration from "./auth/migrations/AddApprovedFieldToUsersTableMigration.js";
|
||||||
import AddNameChangedAtToUsersMigration from "./auth/migrations/AddNameChangedAtToUsersMigration.js";
|
import AddNameChangedAtToUsersMigration from "./auth/migrations/AddNameChangedAtToUsersMigration.js";
|
||||||
import AddNameToUsersMigration from "./auth/migrations/AddNameToUsersMigration.js";
|
import AddNameToUsersMigration from "./auth/migrations/AddNameToUsersMigration.js";
|
||||||
@ -42,6 +42,7 @@ import BackendController from "./helpers/BackendController.js";
|
|||||||
import MailController from "./mail/MailController.js";
|
import MailController from "./mail/MailController.js";
|
||||||
import {MAGIC_LINK_MAIL} from "./Mails.js";
|
import {MAGIC_LINK_MAIL} from "./Mails.js";
|
||||||
import CreateMigrationsTable from "./migrations/CreateMigrationsTable.js";
|
import CreateMigrationsTable from "./migrations/CreateMigrationsTable.js";
|
||||||
|
import IncreaseMagicLinkTokenLengthMigration from "./auth/magic_link/migrations/IncreaseMagicLinkTokenLengthMigration.js";
|
||||||
|
|
||||||
export const MIGRATIONS = [
|
export const MIGRATIONS = [
|
||||||
CreateMigrationsTable,
|
CreateMigrationsTable,
|
||||||
@ -52,6 +53,7 @@ export const MIGRATIONS = [
|
|||||||
MakeMagicLinksSessionNotUniqueMigration,
|
MakeMagicLinksSessionNotUniqueMigration,
|
||||||
AddUsedToMagicLinksMigration,
|
AddUsedToMagicLinksMigration,
|
||||||
AddNameChangedAtToUsersMigration,
|
AddNameChangedAtToUsersMigration,
|
||||||
|
IncreaseMagicLinkTokenLengthMigration,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class TestApp extends Application {
|
export default class TestApp extends Application {
|
||||||
|
@ -83,7 +83,7 @@ export default class MagicLinkAuthMethod implements AuthMethod<MagicLink> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async auth(req: Request, res: Response, isRegistration: boolean, email: string): Promise<void> {
|
private async auth(req: Request, res: Response, isRegistration: boolean, email: string): Promise<void> {
|
||||||
const geo = geoip.lookup(req.ip);
|
const geo = req.ip ? geoip.lookup(req.ip) : null;
|
||||||
const actionType = isRegistration ? AuthMagicLinkActionType.REGISTER : AuthMagicLinkActionType.LOGIN;
|
const actionType = isRegistration ? AuthMagicLinkActionType.REGISTER : AuthMagicLinkActionType.LOGIN;
|
||||||
|
|
||||||
if (isRegistration) {
|
if (isRegistration) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Migration from "../../db/Migration.js";
|
import Migration from "../../../db/Migration.js";
|
||||||
|
|
||||||
export default class AddUsedToMagicLinksMigration extends Migration {
|
export default class AddUsedToMagicLinksMigration extends Migration {
|
||||||
public async install(): Promise<void> {
|
public async install(): Promise<void> {
|
@ -1,6 +1,6 @@
|
|||||||
import Migration from "../../db/Migration.js";
|
import Migration from "../../../db/Migration.js";
|
||||||
import ModelFactory from "../../db/ModelFactory.js";
|
import ModelFactory from "../../../db/ModelFactory.js";
|
||||||
import MagicLink from "../models/MagicLink.js";
|
import MagicLink from "../../models/MagicLink.js";
|
||||||
|
|
||||||
export default class CreateMagicLinksTableMigration extends Migration {
|
export default class CreateMagicLinksTableMigration extends Migration {
|
||||||
public async install(): Promise<void> {
|
public async install(): Promise<void> {
|
@ -0,0 +1,13 @@
|
|||||||
|
import Migration from "../../../db/Migration.js";
|
||||||
|
|
||||||
|
export default class IncreaseMagicLinkTokenLengthMigration extends Migration {
|
||||||
|
public async install(): Promise<void> {
|
||||||
|
await this.query(`ALTER TABLE magic_links
|
||||||
|
MODIFY COLUMN token VARCHAR(128)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async rollback(): Promise<void> {
|
||||||
|
await this.query(`ALTER TABLE magic_links
|
||||||
|
MODIFY COLUMN token CHAR(96)`);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import Migration from "../../db/Migration.js";
|
import Migration from "../../../db/Migration.js";
|
||||||
|
|
||||||
export default class MakeMagicLinksSessionNotUniqueMigration extends Migration {
|
export default class MakeMagicLinksSessionNotUniqueMigration extends Migration {
|
||||||
public async install(): Promise<void> {
|
public async install(): Promise<void> {
|
@ -26,7 +26,7 @@ export default class MagicLink extends Model implements AuthProof<User> {
|
|||||||
protected init(): void {
|
protected init(): void {
|
||||||
this.setValidation('session_id').defined().length(32);
|
this.setValidation('session_id').defined().length(32);
|
||||||
this.setValidation('email').defined().regexp(EMAIL_REGEX);
|
this.setValidation('email').defined().regexp(EMAIL_REGEX);
|
||||||
this.setValidation('token').defined().length(96);
|
this.setValidation('token').defined().maxLength(128);
|
||||||
this.setValidation('action_type').defined().maxLength(64);
|
this.setValidation('action_type').defined().maxLength(64);
|
||||||
this.setValidation('original_url').defined().maxLength(1745);
|
this.setValidation('original_url').defined().maxLength(1745);
|
||||||
this.setValidation('authorized').defined();
|
this.setValidation('authorized').defined();
|
||||||
|
@ -74,7 +74,7 @@ export default class PasswordAuthMethod implements AuthMethod<PasswordAuthProof>
|
|||||||
Throttler.throttle('login_failed_attempts_user', 3, 3 * 60 * 1000, // 3min
|
Throttler.throttle('login_failed_attempts_user', 3, 3 * 60 * 1000, // 3min
|
||||||
user.getOrFail('id').toString(), 1000, 60 * 1000); // 1min
|
user.getOrFail('id').toString(), 1000, 60 * 1000); // 1min
|
||||||
Throttler.throttle('login_failed_attempts_ip', 50, 60 * 1000, // 1min
|
Throttler.throttle('login_failed_attempts_ip', 50, 60 * 1000, // 1min
|
||||||
req.ip, 1000, 3600 * 1000); // 1h
|
req.ip || "", 1000, 3600 * 1000); // 1h
|
||||||
|
|
||||||
if (e instanceof PendingApprovalAuthError) {
|
if (e instanceof PendingApprovalAuthError) {
|
||||||
req.flash('error', 'Your account is still being reviewed.');
|
req.flash('error', 'Your account is still being reviewed.');
|
||||||
@ -98,7 +98,7 @@ export default class PasswordAuthMethod implements AuthMethod<PasswordAuthProof>
|
|||||||
if (!ModelFactory.get(User).hasComponent(UserNameComponent))
|
if (!ModelFactory.get(User).hasComponent(UserNameComponent))
|
||||||
throw new ServerError('Cannot register with password without UserNameComponent.');
|
throw new ServerError('Cannot register with password without UserNameComponent.');
|
||||||
|
|
||||||
Throttler.throttle('register_password', 10, 30000, req.ip);
|
Throttler.throttle('register_password', 10, 30000, req.ip || "");
|
||||||
|
|
||||||
req.body.identifier = identifier;
|
req.body.identifier = identifier;
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ export default abstract class Model implements Extendable<ModelComponent<Model>>
|
|||||||
|
|
||||||
[key: string]: ModelFieldData;
|
[key: string]: ModelFieldData;
|
||||||
|
|
||||||
public constructor(factory: ModelFactory<never>, isNew: boolean) {
|
public constructor(isNew: boolean) {
|
||||||
if (!(factory instanceof ModelFactory)) throw new Error('Cannot instantiate model directly.');
|
const factory = ModelFactory.get(this.constructor as ModelType<Model>);
|
||||||
this._factory = factory;
|
this._factory = factory;
|
||||||
this.init?.();
|
this.init?.();
|
||||||
this._exists = !isNew;
|
this._exists = !isNew;
|
||||||
@ -245,10 +245,10 @@ export default abstract class Model implements Extendable<ModelComponent<Model>>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelType<M extends Model> extends Type<M> {
|
export interface ModelType<M extends Model> {
|
||||||
table: string;
|
table: string;
|
||||||
|
|
||||||
new(factory: ModelFactory<never>, isNew: boolean): M;
|
new(isNew: boolean): M;
|
||||||
|
|
||||||
getPrimaryKeyFields(): (keyof M & string)[];
|
getPrimaryKeyFields(): (keyof M & string)[];
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ export default class ModelFactory<M extends Model> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public create(data: Pick<M, keyof M>, isNewModel: boolean): M {
|
public create(data: Pick<M, keyof M>, isNewModel: boolean): M {
|
||||||
const model = new this.modelType(this as unknown as ModelFactory<never>, isNewModel);
|
const model = new this.modelType(isNewModel);
|
||||||
for (const component of this.components) {
|
for (const component of this.components) {
|
||||||
model.addComponent(new component(model));
|
model.addComponent(new component(model));
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ import {Connection} from "mysql";
|
|||||||
|
|
||||||
import {ServerError} from "../HttpError.js";
|
import {ServerError} from "../HttpError.js";
|
||||||
import Model, {ModelType} from "./Model.js";
|
import Model, {ModelType} from "./Model.js";
|
||||||
import ModelQuery, {WhereTest} from "./ModelQuery.js";
|
import ModelQuery, {ModelFieldData, WhereTest} from "./ModelQuery.js";
|
||||||
|
|
||||||
export const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
|
export const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
|
||||||
|
|
||||||
export default class Validator<V> {
|
export default class Validator<V extends ModelFieldData> {
|
||||||
public static async validate(
|
public static async validate(
|
||||||
validationMap: { [p: string]: Validator<unknown> },
|
validationMap: { [p: string]: Validator<ModelFieldData> },
|
||||||
body: { [p: string]: unknown },
|
body: { [p: string]: ModelFieldData },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const bag = new ValidationBag();
|
const bag = new ValidationBag();
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
|
|
||||||
test('General case', async () => {
|
test('General case', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') ?? [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
// Register user
|
// Register user
|
||||||
@ -90,7 +90,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
.count()).toStrictEqual(0);
|
.count()).toStrictEqual(0);
|
||||||
|
|
||||||
const res1 = await agent.get('/csrf').expect(200);
|
const res1 = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res1.get('Set-Cookie');
|
const cookies = res1.get('Set-Cookie') || [];
|
||||||
const csrf = res1.text;
|
const csrf = res1.text;
|
||||||
|
|
||||||
// Register user
|
// Register user
|
||||||
@ -139,7 +139,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
describe('Register with email (magic_link)', () => {
|
describe('Register with email (magic_link)', () => {
|
||||||
test('General case', async () => {
|
test('General case', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
await agent.post('/auth/register?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
||||||
@ -180,7 +180,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Cannot register without specifying username', async () => {
|
test('Cannot register without specifying username', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
res = await agent.post('/auth/register')
|
res = await agent.post('/auth/register')
|
||||||
@ -198,7 +198,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Cannot register taken username', async () => {
|
test('Cannot register taken username', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -240,7 +240,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Cannot register taken email', async () => {
|
test('Cannot register taken email', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -284,7 +284,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
describe('Authenticate with username and password (password)', () => {
|
describe('Authenticate with username and password (password)', () => {
|
||||||
test('Force auth_method', async () => {
|
test('Force auth_method', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -319,7 +319,7 @@ describe('Authenticate with username and password (password)', () => {
|
|||||||
|
|
||||||
test('Automatic auth_method', async () => {
|
test('Automatic auth_method', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -352,7 +352,7 @@ describe('Authenticate with username and password (password)', () => {
|
|||||||
|
|
||||||
test('Non-existing username', async () => {
|
test('Non-existing username', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -385,7 +385,7 @@ describe('Authenticate with username and password (password)', () => {
|
|||||||
|
|
||||||
test('No password user', async () => {
|
test('No password user', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -440,13 +440,14 @@ describe('Authenticate with username and password (password)', () => {
|
|||||||
describe('Authenticate with email (magic_link)', () => {
|
describe('Authenticate with email (magic_link)', () => {
|
||||||
test('Force auth_method', async () => {
|
test('Force auth_method', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
await agent.get('/is-auth').set('Cookie', cookies).expect(401);
|
await agent.get('/is-auth').set('Cookie', cookies).expect(401);
|
||||||
|
|
||||||
// Authenticate
|
// Authenticate
|
||||||
|
// TODO deprecated querystring => URLSearchParams
|
||||||
await agent.post('/auth/login?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
await agent.post('/auth/login?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
||||||
.set('Cookie', cookies)
|
.set('Cookie', cookies)
|
||||||
.send({
|
.send({
|
||||||
@ -464,7 +465,7 @@ describe('Authenticate with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Automatic auth_method', async () => {
|
test('Automatic auth_method', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -487,7 +488,7 @@ describe('Authenticate with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Non-existing email (forced auth_method)', async () => {
|
test('Non-existing email (forced auth_method)', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -508,7 +509,7 @@ describe('Authenticate with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Non-existing email (automatic auth_method)', async () => {
|
test('Non-existing email (automatic auth_method)', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -530,7 +531,7 @@ describe('Authenticate with email (magic_link)', () => {
|
|||||||
describe('Authenticate with email and password (password)', () => {
|
describe('Authenticate with email and password (password)', () => {
|
||||||
test('Prepare user', async () => {
|
test('Prepare user', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -569,7 +570,7 @@ describe('Authenticate with email and password (password)', () => {
|
|||||||
|
|
||||||
test('Force auth_method', async () => {
|
test('Force auth_method', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -604,7 +605,7 @@ describe('Authenticate with email and password (password)', () => {
|
|||||||
|
|
||||||
test('Automatic auth_method', async () => {
|
test('Automatic auth_method', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -641,7 +642,7 @@ describe('Change password', () => {
|
|||||||
let cookies: string[], csrf: string;
|
let cookies: string[], csrf: string;
|
||||||
test('Prepare user', async () => {
|
test('Prepare user', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -821,7 +822,7 @@ describe('Change password', () => {
|
|||||||
|
|
||||||
test('Can\'t remove password without contact email', async () => {
|
test('Can\'t remove password without contact email', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -863,7 +864,7 @@ describe('Change username', () => {
|
|||||||
let cookies: string[], csrf: string;
|
let cookies: string[], csrf: string;
|
||||||
test('Prepare user', async () => {
|
test('Prepare user', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -962,7 +963,7 @@ describe('Manage email addresses', () => {
|
|||||||
let cookies: string[], csrf: string;
|
let cookies: string[], csrf: string;
|
||||||
test('Prepare user', async () => {
|
test('Prepare user', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -1169,7 +1170,7 @@ describe('Session persistence', () => {
|
|||||||
|
|
||||||
test('Not persistent at registration', async () => {
|
test('Not persistent at registration', async () => {
|
||||||
let res = await agent.get('/csrf').expect(200);
|
let res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -1190,7 +1191,7 @@ describe('Session persistence', () => {
|
|||||||
res = await agent.get('/csrf')
|
res = await agent.get('/csrf')
|
||||||
.set('Cookie', cookies)
|
.set('Cookie', cookies)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(res.get('Set-Cookie')[0]).toMatch(/^connect\.sid=.+; Path=\/; Expires=.+; SameSite=Strict$/);
|
expect(res.get('Set-Cookie')?.[0]).toMatch(/^connect\.sid=.+; Path=\/; Expires=.+; SameSite=Strict$/);
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
await agent.post('/auth/logout')
|
await agent.post('/auth/logout')
|
||||||
@ -1217,7 +1218,7 @@ describe('Session persistence', () => {
|
|||||||
const res = await agent.get('/csrf')
|
const res = await agent.get('/csrf')
|
||||||
.set('Cookie', cookies)
|
.set('Cookie', cookies)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(res.get('Set-Cookie')[0]).toMatch(/^connect\.sid=.+; Path=\/; Expires=.+; SameSite=Strict$/);
|
expect(res.get('Set-Cookie')?.[0]).toMatch(/^connect\.sid=.+; Path=\/; Expires=.+; SameSite=Strict$/);
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
await agent.post('/auth/logout')
|
await agent.post('/auth/logout')
|
||||||
@ -1244,7 +1245,7 @@ describe('Session persistence', () => {
|
|||||||
const res = await agent.get('/csrf')
|
const res = await agent.get('/csrf')
|
||||||
.set('Cookie', cookies)
|
.set('Cookie', cookies)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(res.get('Set-Cookie')[0]).toMatch(/^connect\.sid=.+; Path=\/; SameSite=Strict$/);
|
expect(res.get('Set-Cookie')?.[0]).toMatch(/^connect\.sid=.+; Path=\/; SameSite=Strict$/);
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
await agent.post('/auth/logout')
|
await agent.post('/auth/logout')
|
||||||
|
@ -25,7 +25,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
|
|
||||||
test('General case', async () => {
|
test('General case', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
csrf = res.text;
|
csrf = res.text;
|
||||||
|
|
||||||
// Register user
|
// Register user
|
||||||
@ -63,7 +63,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
describe('Register with email (magic_link)', () => {
|
describe('Register with email (magic_link)', () => {
|
||||||
test('General case', async () => {
|
test('General case', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
await agent.post('/auth/register?' + querystring.stringify({redirect_uri: '/redirect-uri'}))
|
||||||
@ -106,7 +106,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
describe('Authenticate with username and password (password)', () => {
|
describe('Authenticate with username and password (password)', () => {
|
||||||
test('Force auth_method', async () => {
|
test('Force auth_method', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
@ -134,7 +134,7 @@ describe('Authenticate with username and password (password)', () => {
|
|||||||
describe('Authenticate with email (magic_link)', () => {
|
describe('Authenticate with email (magic_link)', () => {
|
||||||
test('Force auth_method', async () => {
|
test('Force auth_method', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Not authenticated
|
// Not authenticated
|
||||||
|
@ -22,7 +22,7 @@ test('Approval Mode', () => {
|
|||||||
describe('Register with username and password (password)', () => {
|
describe('Register with username and password (password)', () => {
|
||||||
test('Must be disabled', async () => {
|
test('Must be disabled', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
// Register user
|
// Register user
|
||||||
@ -43,7 +43,7 @@ describe('Register with username and password (password)', () => {
|
|||||||
describe('Register with email (magic_link)', () => {
|
describe('Register with email (magic_link)', () => {
|
||||||
test('General case', async () => {
|
test('General case', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -77,7 +77,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
|
|
||||||
test('Cannot register taken email', async () => {
|
test('Cannot register taken email', async () => {
|
||||||
const res = await agent.get('/csrf').expect(200);
|
const res = await agent.get('/csrf').expect(200);
|
||||||
const cookies = res.get('Set-Cookie');
|
const cookies = res.get('Set-Cookie') || [];
|
||||||
const csrf = res.text;
|
const csrf = res.text;
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
@ -106,7 +106,7 @@ describe('Register with email (magic_link)', () => {
|
|||||||
const res2 = await agent.get('/csrf').expect(200);
|
const res2 = await agent.get('/csrf').expect(200);
|
||||||
|
|
||||||
await agent.post('/auth/register')
|
await agent.post('/auth/register')
|
||||||
.set('Cookie', res2.get('Set-Cookie'))
|
.set('Cookie', res2.get('Set-Cookie') || [])
|
||||||
.send({
|
.send({
|
||||||
csrf: res2.text,
|
csrf: res2.text,
|
||||||
auth_method: 'magic_link',
|
auth_method: 'magic_link',
|
||||||
|
@ -39,7 +39,7 @@ describe('Test CSRF protection', () => {
|
|||||||
.expect(401)
|
.expect(401)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
expect(res.text).toContain(`You weren't assigned any CSRF token.`);
|
expect(res.text).toContain(`You weren't assigned any CSRF token.`);
|
||||||
cookies = res.get('Set-Cookie');
|
cookies = res.get('Set-Cookie') || [];
|
||||||
|
|
||||||
agent.get('/')
|
agent.get('/')
|
||||||
.set('Cookie', cookies)
|
.set('Cookie', cookies)
|
||||||
|
Loading…
Reference in New Issue
Block a user