본문 바로가기
개발정리 (nodeJS)

[nodeJS] Node.js에서 JWT를 활용한 권한 관리 및 역할 기반 접근 제어 구현하기

by 할리갈리0 2024. 10. 1.

JWT(JSON Web Token)는 웹 애플리케이션에서 사용자 인증 및 권한 관리를 구현하는 데 널리 사용됩니다. 역할 기반 접근 제어(RBAC)를 통해 사용자의 권한을 관리하고, 보안을 강화할 수 있습니다. 이번 포스팅에서는 JWT를 사용하여 사용자 권한과 역할을 관리하는 방법을 Node.js 환경에서 구현하는 과정을 설명하겠습니다.

 

 

1. 역할 기반 접근 제어

  • RBAC(Role-Based Access Control)
    • 사용자의 역할에 따라 시스템 자원에 대한 접근 권한을 제어하는 방법
    • 각 사용자는 특정 역할(role)을 할당받으며, 각 역할은 시스템에서 수행할 수 있는 작업(permissions)을 정의하고, 이를 통해 사용자별로 세분화된 권한을 설정하고 보안을 강화.
  • 예시 역할: 사용자(User), 관리자(Admin), 슈퍼 관리자(SuperAdmin)
  • 권한 예시: 읽기(Read), 쓰기(Write), 삭제(Delete)

 

2. Node.js에서 JWT 설정 및 구현

[프로젝트 초기화 및 JWT 라이브러리 설치]

  • express: 서버를 구현하기 위한 웹 프레임워크
  • jsonwebtoken: JWT를 생성하고 검증하기 위한 라이브러리
  • bcryptjs: 비밀번호를 안전하게 해싱하고 검증하기 위한 라이브러리
mkdir jwt-auth-example
cd jwt-auth-example
npm init -y
npm install express jsonwebtoken bcryptjs

 

[기본 Express 서버 설정]

  • /register: 사용자가 회원가입을 하며, 비밀번호는 해싱되어 저장
  • /login: 사용자가 로그인하면, 사용자의 역할과 함께 JWT가 발급
// server.js
import express from 'express';
import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';

const app = express();
const SECRET_KEY = 'your_secret_key';

app.use(express.json());

let users = [];

// 회원가입 엔드포인트
app.post('/register', async (req, res) => {
  const { username, password, role } = req.body;

  const hashedPassword = await bcrypt.hash(password, 10);
  users.push({ username, password: hashedPassword, role });

  res.status(201).json({ message: 'User registered successfully' });
});

// 로그인 엔드포인트
app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username);

  if (!user) return res.status(404).json({ message: 'User not found' });

  const isMatch = await bcrypt.compare(password, user.password);

  if (!isMatch) return res.status(403).json({ message: 'Invalid credentials' });

  const token = jwt.sign({ username: user.username, role: user.role }, SECRET_KEY, { expiresIn: '1h' });

  res.json({ token });
});

// 서버 시작
app.listen(3000, () => {
  console.log('Server running on <http://localhost:3000>');
});

 

 

3. 사용자 권한 및 역할 할당하기

JWT 페이로드에는 사용자의 역할을 포함할 수 있어, 사용자가 시스템에서 어떤 권한을 갖고 있는지 관리 가능.

회원가입 시 사용자가 역할(role)을 선택할 수 있게 하고, 로그인 시 역할 정보를 포함한 JWT를 생성

  • 사용자 역할: User, Admin
  • JWT 페이로드: { "username": "john_doe", "role": "Admin" }
// 페이로드에 역할 포함
const token = jwt.sign(
  { username: user.username, role: user.role },
  SECRET_KEY,
  { expiresIn: '1h' }
);

 

 

4. JWT를 활용한 역할 기반 접근 제어

[미들웨어로 권한 검사 구현]

JWT를 활용해 사용자의 역할을 확인하고, 특정 API 엔드포인트에 대한 접근을 제어 가능.

// 권한 확인 미들웨어
const authorize = (roles) => {
  return (req, res, next) => {
    const token = req.headers['authorization'];

    if (!token) return res.status(401).json({ message: 'Access token required' });

    try {
      const decoded = jwt.verify(token.split(' ')[1], SECRET_KEY);

      if (!roles.includes(decoded.role)) {
        return res.status(403).json({ message: 'Forbidden: You do not have the right permissions' });
      }

      req.user = decoded;
      next();
    } catch (error) {
      return res.status(401).json({ message: 'Invalid token' });
    }
  };
};

 

[관리자 전용 API 엔드포인트]

Admin 역할을 가진 사용자만 /admin 경로에 접근할 수 있도록 설정

authorize 미들웨어는 JWT를 검사하고, 사용자 역할이 Admin이 아니면 접근 차단

// 관리자 전용 엔드포인트
app.get('/admin', authorize(['Admin']), (req, res) => {
  res.json({ message: 'Welcome Admin!' });
});

 

 

5. 보안 강화: JWT 만료 및 갱신 처리

[JWT 만료 설정]

JWT는 만료 시간이 설정된 유효한 토큰이어야 하므로, 보안을 강화하기 위해 만료 시간(expiresIn)을 설정

const token = jwt.sign({ username: user.username, role: user.role }, SECRET_KEY, { expiresIn: '1h' });

 

[토큰 갱신 처리]

토큰이 만료되기 전에 새로운 토큰을 발급해주는 방식으로 보안 강화 가능.

"Refresh Token"을 사용하여 유효한 토큰을 재발급받는 엔드포인트를 구현 필요

// 기존 토큰이 만료되었을 때 새로운 토큰을 발급
app.post('/refresh-token', (req, res) => {
  const token = req.headers['authorization'];

  if (!token) return res.status(401).json({ message: 'Access token required' });

  try {
    const decoded = jwt.verify(token.split(' ')[1], SECRET_KEY, { ignoreExpiration: true });
    const newToken = jwt.sign({ username: decoded.username, role: decoded.role }, SECRET_KEY, { expiresIn: '1h' });

    res.json({ token: newToken });
  } catch (error) {
    return res.status(401).json({ message: 'Invalid token' });
  }
});

 

 

 

 

이번 포스팅에서는 Node.js 환경에서 JWT를 활용한 사용자 권한 관리 및 역할 기반 접근 제어를 구현하는 방법을 살펴보았습니다. JWT를 사용하면 사용자 권한을 보다 안전하고 효율적으로 관리할 수 있으며, 역할 기반 접근 제어를 통해 시스템의 보안을 강화할 수 있습니다.

반응형