Fix jwt-token
This commit is contained in:
@@ -188,5 +188,179 @@ describe('Authentication Middleware', () => {
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.message).to.equal('User account is inactive');
|
||||
});
|
||||
|
||||
it('should handle malformed JWT token', async () => {
|
||||
const req = mockRequest({
|
||||
headers: { authorization: 'Bearer malformed.jwt' }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.error).to.equal('INVALID_TOKEN');
|
||||
expect(res.data.redirectToLogin).to.be.true;
|
||||
});
|
||||
|
||||
it('should handle JWT with invalid signature', async () => {
|
||||
const invalidToken = jwt.sign(
|
||||
{ userId: 1, username: 'test' },
|
||||
'wrong-secret',
|
||||
{ expiresIn: '1h' }
|
||||
);
|
||||
|
||||
const req = mockRequest({
|
||||
headers: { authorization: `Bearer ${invalidToken}` }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.error).to.equal('INVALID_TOKEN');
|
||||
expect(res.data.redirectToLogin).to.be.true;
|
||||
});
|
||||
|
||||
it('should handle JWT not before error', async () => {
|
||||
const futureToken = jwt.sign(
|
||||
{ userId: 1, username: 'test', nbf: Math.floor(Date.now() / 1000) + 3600 },
|
||||
process.env.JWT_SECRET || 'test-secret',
|
||||
{ expiresIn: '1h' }
|
||||
);
|
||||
|
||||
const req = mockRequest({
|
||||
headers: { authorization: `Bearer ${futureToken}` }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.error).to.equal('TOKEN_NOT_ACTIVE');
|
||||
expect(res.data.redirectToLogin).to.be.true;
|
||||
});
|
||||
|
||||
it('should handle missing JWT_SECRET environment variable', async () => {
|
||||
const originalSecret = process.env.JWT_SECRET;
|
||||
delete process.env.JWT_SECRET;
|
||||
|
||||
const token = jwt.sign(
|
||||
{ userId: 1, username: 'test' },
|
||||
'any-secret',
|
||||
{ expiresIn: '1h' }
|
||||
);
|
||||
|
||||
const req = mockRequest({
|
||||
headers: { authorization: `Bearer ${token}` }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data.success).to.be.false;
|
||||
expect(res.data.error).to.equal('AUTHENTICATION_FAILED');
|
||||
expect(res.data.redirectToLogin).to.be.true;
|
||||
|
||||
// Restore original secret
|
||||
process.env.JWT_SECRET = originalSecret;
|
||||
});
|
||||
|
||||
it('should include error details for monitoring', async () => {
|
||||
const originalEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const consoleSpy = sinon.spy(console, 'error');
|
||||
|
||||
const req = mockRequest({
|
||||
headers: {
|
||||
authorization: 'Bearer invalid.jwt.token',
|
||||
'user-agent': 'Test Agent',
|
||||
},
|
||||
ip: '127.0.0.1',
|
||||
path: '/api/test',
|
||||
connection: { remoteAddress: '127.0.0.1' }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(consoleSpy.calledOnce).to.be.true;
|
||||
const logCall = consoleSpy.firstCall.args;
|
||||
expect(logCall[0]).to.equal('🔐 Authentication error:');
|
||||
expect(logCall[1]).to.have.property('error');
|
||||
expect(logCall[1]).to.have.property('userAgent', 'Test Agent');
|
||||
expect(logCall[1]).to.have.property('ip', '127.0.0.1');
|
||||
expect(logCall[1]).to.have.property('path', '/api/test');
|
||||
|
||||
consoleSpy.restore();
|
||||
process.env.NODE_ENV = originalEnv;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Enhanced Error Response Format', () => {
|
||||
it('should return consistent error format for expired tokens', async () => {
|
||||
const expiredToken = jwt.sign(
|
||||
{ userId: 1, username: 'test' },
|
||||
process.env.JWT_SECRET || 'test-secret',
|
||||
{ expiresIn: '-1h' }
|
||||
);
|
||||
|
||||
const req = mockRequest({
|
||||
headers: { authorization: `Bearer ${expiredToken}` }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data).to.deep.equal({
|
||||
success: false,
|
||||
error: 'TOKEN_EXPIRED',
|
||||
message: 'Token expired',
|
||||
redirectToLogin: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should return consistent error format for invalid tokens', async () => {
|
||||
const req = mockRequest({
|
||||
headers: { authorization: 'Bearer invalid.jwt.token' }
|
||||
});
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data).to.deep.equal({
|
||||
success: false,
|
||||
error: 'INVALID_TOKEN',
|
||||
message: 'Invalid token',
|
||||
redirectToLogin: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should return consistent error format for missing tokens', async () => {
|
||||
const req = mockRequest();
|
||||
const res = mockResponse();
|
||||
const next = mockNext();
|
||||
|
||||
await authenticateToken(req, res, next);
|
||||
|
||||
expect(res.statusCode).to.equal(401);
|
||||
expect(res.data).to.deep.equal({
|
||||
success: false,
|
||||
message: 'Access token required'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user