[MongoDB] bad auth : Authentication failed

Shin Hyun Woo·2022년 12월 2일
1
post-thumbnail

오늘도 강의를 따라하다 에러를 마주쳤다.

발생 상황

Github에 commit할 경우 mongoose와 연결할 때 사용하는 URI가 아이디와 패스워드를 담고 있어 보안이 취약하다.
그래서 비밀 정보를 보호하기 위해 개발 로컬 환경과 배포 환경마다 해당되는 부분을 따로 받을 수 있게 설정하기 위해 파일을 분기하는 과정에서 발생했다.

그 과정에서 발생한 에러가 아래의 에러이다.

MongoServerError: bad auth : Authentication failed.

라는 에러인데 "몽고DB 서버 에러 : 잘못된 인증 : 인증에 실패했다."라는 것이다.

음.. 개인적으로 경고 메세지가 너무 포괄적이고 강사님과 나의 환경(node와 mongoDB의 버전 차이)이 다르기 때문에 걱정부터 했지만 일단 침착하게 구글링했다 ㅎㅎㅎ..

I think you're confused with the mongodb account password and user password. You should use user password, not account password. That was the reason of my case.
출처 : stackoverflow

stackoverflow에서 다른 분이 올린 질문에 이와 같은 답변이 채택되어 있었다.
mongoDB의 계정 비밀번호와 사용자 비밀번호를 혼동한게 아니냐라는 것이다.
하지만 나는 mongoDB 계정 비밀번호와 사용자 비밀번호를 혼동하지 않았지만 우선 '계정 문제'이겠구나 하며 코드에서 수정했던 부분을 되짚어봤다.

우선 분기한 파일은 아래와 같다.

index.js에서 연결한 username과 password가 연결할 URI에 노출되어 있었다.

// index.js
const express = require("express");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");

const { User } = require("./models/User");


app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// 아래처럼 username과 password가 노출되어있었다.
const username = encodeURIComponent(<username>);
const password = encodeURIComponent(<password>);

const mongoose = require("mongoose");

// 노출된 username과 password을 사용한다.
mongoose  .connect(`mongodb+srv://${username}:${password}@cluster0.3rt3shc.mongodb.net/?retryWrites=true&w=majority`,)
  .then(() => console.log("MongoDB connected"))
  .catch((err) => console.log(err));

app.get("/", (req, res) => {
  res.send("Hello Word! 안녕하세요~ 저는 신현우입니다.");
});

app.post("/register", (req, res) => {
  const user = new User(req.body);
  user.save((err, userInfo) => {
    if (err) return res.json({ success: false, err });
    return res.status(200).json({
      success: true,
    });
  });
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

그래서 이것을 개발/배포 환경에 따라 다르게 위해 파일을 아래처럼 분기하였다.

// dev.js - 개발 환경에서 사용할 URI
module.exports = {
  mongoURI: `mongodb+srv://${username}:${password}@cluster0.3rt3shc.mongodb.net/?retryWrites=true&w=majority`,
};
// prod.js - 배포 한 후 환경에서 사용할 URI
module.exports = {
  mongoURI: process.env.MONGO_URL,
};
// key.js - production 환경인지 아닌지에 따라 모듈을 export하여 해당 모듈을 사용한다. 
if (process.env.NODE_ENV === "production") {
  module.exports = require("./prod");
} else {
  module.exports = require("./dev");
}

그리고 조건을 만족하는 export된 모듈을 사용해서 index.js에 URI를 적용시킨다.

const express = require("express");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");
// 상수 config에 export된 모듈을 담아서 사용한다. 이 모듈을 mongoURI가 property로 존재하는 객체이다.
const config = require("./config/key");
const { User } = require("./models/User");

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

const username = encodeURIComponent(<username>);
const password = encodeURIComponent(<password>);

const mongoose = require("mongoose");
// 여기서 config가 사용된다.
mongoose
  .connect(config.mongoURI)
  .then(() => console.log("MongoDB connected"))
  .catch((err) => console.log(err));

app.get("/", (req, res) => {
  res.send("Hello Word! 안녕하세요~ 저는 신현우입니다.");
});

app.post("/register", (req, res) => {
  const user = new User(req.body);
  user.save((err, userInfo) => {
    if (err) return res.json({ success: false, err });
    return res.status(200).json({
      success: true,
    });
  });
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

이렇게 했을 때 아래의 에러가 발생한 것..!

문제 해결

우선 usernamepassword를 우선적으로 살펴보았다.
여기서 아.. 내가 dev.js에 usernamepassword값을 옮겨주지 않았구나..
에러가 발생한 이유가 usernamepassword가 정의되지 않았기 때문에 인증에 실패했구나..😓

그래서 아래처럼 usernamepassword를 dev.js로 옮겨주었더니 정상적으로 동작했다.

const express = require("express");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");

const config = require("./config/key");
const { User } = require("./models/User");

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// username / password 상수 dev.js로 옮김

const mongoose = require("mongoose");
mongoose
  .connect(config.mongoURI)
  .then(() => console.log("MongoDB connected"))
  .catch((err) => console.log(err));

app.get("/", (req, res) => {
  res.send("Hello Word! 안녕하세요~ 저는 신현우입니다.");
});

app.post("/register", (req, res) => {
  const user = new User(req.body);
  user.save((err, userInfo) => {
    if (err) return res.json({ success: false, err });
    return res.status(200).json({
      success: true,
    });
  });
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
const username = encodeURIComponent(<username>);
const password = encodeURIComponent(<password>);

module.exports = {
  mongoURI: `mongodb+srv://${username}:${password}@cluster0.3rt3shc.mongodb.net/?retryWrites=true&w=majority`,
};

에러가 나면 덜컥 겁먹곤 했는데 별거 아니였다..ㅎㅎㅎ
코드를 꼼꼼히 보는 것도 중요하지만 모를 땐 역시 구글링이 최고..👍

profile
untiring_dev - Notion 페이지는 정리 중!

0개의 댓글