I developed an full stack app using Angular as the frontend and Nestjs as the backend. The project is organized in a monorepository with NX. The project works fine on my local machine, including authentication (Passport library from Nestjs).
So I decided to dockerize the app, but when the app is run in the docker container the protected routes from the Nestjs backend are not accessible and I am getting a 401 error despite using the JWT token that I got from the same instance running in the docker container.
I migrated the project from bcrypt to bcryptjs because I was getting an error when building the docker container. The thing that confuses me mostly is that on my local machine everything works fine, but in the docker container the protected routes are not accessible despite using the JWT token that I got from the backend.
Dockerfile
FROM node:14
ENV PORT=3333
WORKDIR /app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*","nx.json", "./"]
RUN npm install
COPY ./apps .
EXPOSE 3333
CMD npm start
docker-compose.yml
version: '3.4'
services:
myapp:
image: myapp
build:
context: .
dockerfile: ./Dockerfile
volumes:
- .:/app
depends_on:
- postgres
environment:
API_PORT: 3333
JWT_SECRET: verystrongsecret
JWT_EXPIRES_IN: 3600
DB_TYPE: postgres
DB_PORT: 5432
DB_HOST: postgres
DB_USERNAME: user
DB_PASSWORD: password
DB_NAME: db
NODE_ENV: development
TYPEORM_SYNC: 'true'
ports:
- 3333:3333
postgres:
image: postgres:10.4
ports:
- 5432:5432
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: db
How to solve the issue with the authentication? What could cause docker to this strange behavior?
JwtStrategy:
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
@InjectRepository(UserRepository) private userRepository: UserRepository
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET || config.get('jwt.secret'),
});
}
async validate(payload: JwtPayload): Promise<User> {
const { email } = payload;
const user = await this.userRepository.findOne({ email });
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
to protect the routes I am using the : @UseGuards(AuthGuard())
where AuthGuard
is from the passport library.
The AuthModule:
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: process.env.JWT_SECRET || jwtConfig.secret,
signOptions: {
expiresIn: process.env.JWT_EXPIRES_IN || jwtConfig.expiresIn,
},
}),
TypeOrmModule.forFeature([UserRepository]),
],
controllers: [AuthController],
providers: [AuthService, JwtStrategy],
exports: [AuthService, JwtStrategy, PassportModule],
})
export class AuthModule {}