diff --git a/src/auth.test.ts b/src/auth.test.ts index 346428f..5a0a39f 100644 --- a/src/auth.test.ts +++ b/src/auth.test.ts @@ -31,6 +31,13 @@ describe('Auth', async () => { expect(await validateAt(user, await generatePassAt(user + 'a', 1), 1)).toBe(false); }); + it('rejects missing signature', async () => { + let pass = await generatePassAt(user, 1); + // pass is ts:hex-sig, remove the signature + pass = pass.substring(0, pass.indexOf(':')); + expect(await validateAt(user, pass, 11)).toBe(false); + }); + it('rejects long signature', async () => { let pass = await generatePassAt(user, 1); // pass is ts:hex-sig, change the sig length diff --git a/src/auth.ts b/src/auth.ts index 894b24a..e898633 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,6 +34,9 @@ export async function createAuthWithClock(secret: string, maxAgeSeconds: number, const truncatedSignatureLength = 10; const [ts, sig] = password.split(':'); + if (!ts || !sig) { + return false; + } const actual = Buffer.from(sig, 'hex'); if (actual.length !== truncatedSignatureLength) { // timingSafeEqual throws if the buffers are not the same length @@ -56,4 +59,3 @@ export async function createAuthWithClock(secret: string, maxAgeSeconds: number, export async function createAuth(secret: string, maxAgeSeconds: number): Promise { return await createAuthWithClock(secret, maxAgeSeconds, () => Math.floor(new Date().getTime() / 1000)); } - diff --git a/src/index.ts b/src/index.ts index de9b84d..0ac87e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -312,7 +312,7 @@ function parseBasicAuth(auth: string): Credentials | ParseError { const [username, ...rest] = decoded.split(':'); const password = rest.join(':'); - if (!password) { + if (!username || !password) { return {state: 'error', error: error(400, 'invalid auth format')}; } return {state: 'success', user: username, password: password}; diff --git a/tsconfig.json b/tsconfig.json index 138318c..b3e739e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -107,7 +107,8 @@ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + /* Include 'undefined' in index signature results */ + "noUncheckedIndexedAccess": true, // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */