and thanks for the tool .
I'm working on a Nestjs (v8.x) application relying on Passport.js with a JWT strategy through HttpOnly cookies. For testing the different endpoints of my app, I'm using supertest (v6.1.x).
In order to reach certain endpoints, I need to get an authentication cookie set after submitting credentials. When playing with the UI, everything is working correctly and I can get the data I want. However, when trying to create an automated test based on that, it does not work (at all).
My tests looks like following:
it('gives the current user when the token is valid', async () => {
const cookieToken = await authenticate(app);
const { body: user } = await request(app.getHttpServer())
.get('/users/me')
.set('Cookie', cookieToken);
expect(user.email).toEqual('joe.doe@gmail.com');
expect(user.fullname).toEqual('Joe Doe');
expect(user.uuid).toBeTruthy();
expect(user.password).toBeFalsy();
});
The authenticate
function is a helper that looks like:
export const authenticate = async (
app: INestApplication,
username = 'joe.doe@gmail.com',
password = 'password',
) => {
const res = await request(app.getHttpServer()).post('/auth/login').send({
username,
password,
});
// This cookie resolves correctly
const cookieWithToken = res.headers['set-cookie'];
return cookieWithToken;
};
This tests fails and I got a 401
response from my JWT strategy. The code for this strategy looks like:
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromExtractors([
(request: Request) => {
let data = request?.cookies?.['auth-cookie'];
// In the test scenario, request.cookies is always undefined
if (!data) {
throw new UnauthorizedException();
}
return data.access_token;
},
]),
ignoreExpiration: false,
secretOrKey: jwtConstants.secret,
});
}
async validate(payload: any) {
// Not important for this issue
}
}
During the test run, request?.cookies
is undefined and never set, thus throws the 401 error to the caller.
I don't know what is going but it looks like something is wrong on the way I set it.
I've tried the following approaches:
- Adding
withCredentials
(cuz, who knows...) - Nesting the second call inside the callback resolving the login call in case there's a shared context between the requests
- Relying on the same agent to make both the calls instead of directly calling superagent
But still, without success :(
Do you have any ideas?