MotorSignal-App/server/waze_relay/test/auth_and_appcheck.test.js

207 lines
5.9 KiB
JavaScript

const { describe, it } = require('node:test');
const assert = require('node:assert');
const { requireAuth, admin } = require('../middleware/firebase_auth');
const { requireAppCheck } = require('../middleware/app_check');
describe('Auth Middleware', () => {
it('rejects missing Authorization header with 401 authenticationRequired', async () => {
const req = { headers: {} };
let statusCode = null;
let responseBody = null;
const res = {
status: (c) => {
statusCode = c;
return {
json: (b) => {
responseBody = b;
}
};
}
};
let nextCalled = false;
await requireAuth(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, false);
assert.strictEqual(statusCode, 401);
assert.strictEqual(responseBody?.error, 'authenticationRequired');
});
it('rejects malformed Authorization header with 401 authenticationRequired', async () => {
const req = { headers: { authorization: 'Basic 12345' } };
let statusCode = null;
let responseBody = null;
const res = {
status: (c) => {
statusCode = c;
return {
json: (b) => {
responseBody = b;
}
};
}
};
let nextCalled = false;
await requireAuth(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, false);
assert.strictEqual(statusCode, 401);
assert.strictEqual(responseBody?.error, 'authenticationRequired');
});
it('rejects empty Bearer token with 401 invalidToken', async () => {
const req = { headers: { authorization: 'Bearer ' } };
let statusCode = null;
let responseBody = null;
const res = {
status: (c) => {
statusCode = c;
return {
json: (b) => {
responseBody = b;
}
};
}
};
let nextCalled = false;
await requireAuth(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, false);
assert.strictEqual(statusCode, 401);
assert.strictEqual(responseBody?.error, 'invalidToken');
});
it('successfully attaches verified UID from decoded ID token', async () => {
const originalAuth = admin.auth;
try {
// Mock verifyIdToken
admin.auth = () => ({
verifyIdToken: async (token) => {
if (token === 'valid-token') {
return { uid: 'rider_alice_123', email: 'alice@example.com' };
}
throw new Error('Invalid token');
}
});
const req = { headers: { authorization: 'Bearer valid-token' } };
const res = { status: () => ({ json: () => {} }) };
let nextCalled = false;
await requireAuth(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, true);
assert.strictEqual(req.user?.uid, 'rider_alice_123');
assert.strictEqual(req.user?.email, 'alice@example.com');
} finally {
admin.auth = originalAuth;
}
});
});
describe('App Check Middleware', () => {
it('allows request when enforcement is disabled and token is missing', async () => {
const req = { header: () => undefined };
let nextCalled = false;
const res = {
status: () => ({ json: () => {} })
};
await requireAppCheck(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, true);
});
it('fails closed when enforcement is enabled and token is missing', async () => {
process.env.ENFORCE_APP_CHECK = 'true';
try {
const req = { header: () => undefined };
let statusCode = null;
let responseBody = null;
const res = {
status: (c) => {
statusCode = c;
return {
json: (b) => {
responseBody = b;
}
};
}
};
let nextCalled = false;
await requireAppCheck(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, false);
assert.strictEqual(statusCode, 403);
assert.strictEqual(responseBody?.error, 'appCheckFailed');
} finally {
delete process.env.ENFORCE_APP_CHECK;
}
});
it('fails closed when enforcement is enabled and token is invalid', async () => {
process.env.ENFORCE_APP_CHECK = 'true';
try {
const req = { header: (h) => (h === 'X-Firebase-AppCheck' ? 'invalid-token' : undefined) };
let statusCode = null;
let responseBody = null;
const res = {
status: (c) => {
statusCode = c;
return {
json: (b) => {
responseBody = b;
}
};
}
};
let nextCalled = false;
await requireAppCheck(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, false);
assert.strictEqual(statusCode, 403);
assert.strictEqual(responseBody?.error, 'appCheckFailed');
} finally {
delete process.env.ENFORCE_APP_CHECK;
}
});
it('allows valid App Check token when enforcement is enabled', async () => {
process.env.ENFORCE_APP_CHECK = 'true';
const originalAppCheck = admin.appCheck;
try {
admin.appCheck = () => ({
verifyToken: async (token) => {
if (token === 'valid-app-check-token') {
return { appId: 'motorsignal-app-id', token: 'valid-app-check-token' };
}
throw new Error('Bad token');
}
});
const req = { header: (h) => (h === 'X-Firebase-AppCheck' ? 'valid-app-check-token' : undefined) };
const res = { status: () => ({ json: () => {} }) };
let nextCalled = false;
await requireAppCheck(req, res, () => {
nextCalled = true;
});
assert.strictEqual(nextCalled, true);
assert.strictEqual(req.appCheck?.appId, 'motorsignal-app-id');
} finally {
admin.appCheck = originalAppCheck;
delete process.env.ENFORCE_APP_CHECK;
}
});
});