trips) add local auth provider and login picker
Some checks failed
PR Checks / lint-test-and-docker-build (pull_request) Failing after 23s
Some checks failed
PR Checks / lint-test-and-docker-build (pull_request) Failing after 23s
This commit is contained in:
84
src/lib/server/local-auth.test.ts
Normal file
84
src/lib/server/local-auth.test.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { setupTestDb } from '../../tests/helpers.js';
|
||||
import type { Database } from './db/types.js';
|
||||
import { setLocalCredentialPassword } from './local-credentials.js';
|
||||
import { resetLocalAuthRateLimits, verifyLocalCredentials } from './local-auth.js';
|
||||
import { upsertUserFromAuth } from './users.js';
|
||||
|
||||
let database: Database;
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.LOCAL_AUTH_ENABLED = 'true';
|
||||
process.env.LOCAL_AUTH_ARGON2_MEMORY_KB = '8192';
|
||||
process.env.LOCAL_AUTH_ARGON2_TIME_COST = '2';
|
||||
process.env.LOCAL_AUTH_ARGON2_PARALLELISM = '1';
|
||||
process.env.LOCAL_AUTH_MAX_ATTEMPTS = '2';
|
||||
process.env.LOCAL_AUTH_WINDOW_SECONDS = '60';
|
||||
process.env.LOCAL_AUTH_LOCKOUT_SECONDS = '10';
|
||||
database = setupTestDb();
|
||||
resetLocalAuthRateLimits();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
resetLocalAuthRateLimits();
|
||||
database.close();
|
||||
});
|
||||
|
||||
describe('verifyLocalCredentials', () => {
|
||||
it('authenticates valid local credentials', async () => {
|
||||
upsertUserFromAuth({
|
||||
id: 'user-1',
|
||||
username: 'jdoe',
|
||||
fullName: 'Jane Doe',
|
||||
email: 'jane@example.com',
|
||||
authSource: 'Local'
|
||||
});
|
||||
await setLocalCredentialPassword('user-1', 'averysecurepassword');
|
||||
|
||||
const result = await verifyLocalCredentials('jdoe', 'averysecurepassword', '127.0.0.1');
|
||||
|
||||
expect(result.status).toBe('success');
|
||||
if (result.status === 'success') {
|
||||
expect(result.user.id).toBe('user-1');
|
||||
expect(result.user.email).toBe('jane@example.com');
|
||||
}
|
||||
});
|
||||
|
||||
it('returns invalid for bad credentials and locks after max attempts', async () => {
|
||||
upsertUserFromAuth({ id: 'user-2', username: 'sally', fullName: 'Sally Sample' });
|
||||
await setLocalCredentialPassword('user-2', 'averysecurepassword');
|
||||
|
||||
const first = await verifyLocalCredentials('sally', 'wrong-password', '10.0.0.1');
|
||||
const second = await verifyLocalCredentials('sally', 'wrong-password', '10.0.0.1');
|
||||
const third = await verifyLocalCredentials('sally', 'wrong-password', '10.0.0.1');
|
||||
|
||||
expect(first.status).toBe('invalid');
|
||||
expect(second.status).toBe('invalid');
|
||||
expect(third.status).toBe('locked');
|
||||
});
|
||||
|
||||
it('clears lockout after window expires', async () => {
|
||||
upsertUserFromAuth({ id: 'user-3', username: 'morgan', fullName: 'Morgan West' });
|
||||
await setLocalCredentialPassword('user-3', 'averysecurepassword');
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2024-01-01T00:00:00Z'));
|
||||
|
||||
await verifyLocalCredentials('morgan', 'wrong-password', '10.0.0.2');
|
||||
await verifyLocalCredentials('morgan', 'wrong-password', '10.0.0.2');
|
||||
const locked = await verifyLocalCredentials('morgan', 'averysecurepassword', '10.0.0.2');
|
||||
|
||||
expect(locked.status).toBe('locked');
|
||||
|
||||
vi.advanceTimersByTime(11_000);
|
||||
const after = await verifyLocalCredentials('morgan', 'averysecurepassword', '10.0.0.2');
|
||||
|
||||
expect(after.status).toBe('success');
|
||||
});
|
||||
|
||||
it('rejects when local auth is disabled', async () => {
|
||||
process.env.LOCAL_AUTH_ENABLED = 'false';
|
||||
const result = await verifyLocalCredentials('anyone', 'password', '10.0.0.3');
|
||||
expect(result.status).toBe('disabled');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user