JWT를 사용한 사용자 인증:
사용자 인증은 사용자가 자신의 신원을 확인하여 시스템에 접근하는 것을 의미합니다. JWT는 사용자 인증에 효과적인 방법으로 사용됩니다.
인증 과정:
JWT 구조:
JWT는 기본적으로 세 부분으로 이루어집니다.
JWT를 이용한 API 보안 인증:
JWT는 API 보안 인증에 널리 사용되는 방법 중 하나로, 사용자가 API에 접근할 때 JWT를 포함시키는 인증 방식을 사용합니다.
인증 과정:
장점:
JWT를 활용한 SSO (Single Sign-On):
SSO는 여러 개의 서비스나 애플리케이션에 대해 한 번의 로그인으로 모두 접근할 수 있는 인증 방식입니다. JWT를 사용한 SSO는 각 서비스에서 독립적으로 인증하는 대신, 하나의 인증 서비스를 통해 한 번의 로그인으로 여러 서비스에 접근합니다.
인증 과정:
장점:
이러한 방식으로 JWT를 사용하여 사용자 인증, API 보안 인증, 그리고 SSO를 구현할 수 있습니다. 단, JWT를 사용할 때에는 토큰의 유효기간과 보안적인 측면을 고려하여 안전하고 효율적인 인증 시스템을 구성해야 합니다.
설명:
사용자 인증은 사용자가 자신의 신원을 확인하여 시스템에 접근하는 것을 의미합니다. JWT는 사용자 인증에 효과적인 방법으로 사용됩니다.
코드 예시:
const jwt = require('jsonwebtoken');
// 사용자 로그인 시 JWT 발급 예시
function loginUser(req, res) {
// 사용자 정보를 검증하고 유효한 사용자라면 사용자 ID로 JWT를 발급합니다.
const user = {
id: 123,
username: 'user123',
role: 'admin', // 사용자의 권한 등을 포함한 정보
};
// JWT 생성
const token = jwt.sign(user, 'secret_key', { expiresIn: '1h' });
res.json({ token });
}
// JWT를 이용한 사용자 인증 검증 미들웨어 예시
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.sendStatus(401); // Unauthorized
}
jwt.verify(token, 'secret_key', (err, user) => {
if (err) {
return res.sendStatus(403); // Forbidden
}
req.user = user;
next();
});
}
설명:
JWT는 API 보안 인증에 널리 사용되는 방법 중 하나로, 사용자가 API에 접근할 때 JWT를 포함시키는 인증 방식을 사용합니다.
코드 예시:
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// 미들웨어로 사용자 인증 검증
app.use(authenticateToken);
// 보호된 API 엔드포인트 예시
app.get('/protected-resource', (req, res) => {
// 검증된 사용자 정보에 접근 가능
const user = req.user;
res.json({ message: 'This is a protected resource!', user });
});
// 사용자 인증 검증 미들웨어 예시
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.sendStatus(401); // Unauthorized
}
jwt.verify(token, 'secret_key', (err, user) => {
if (err) {
return res.sendStatus(403); // Forbidden
}
req.user = user;
next();
});
}
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
설명:
SSO는 여러 개의 서비스나 애플리케이션에 대해 한 번의 로그인으로 모두 접근할 수 있는 인증 방식입니다. JWT를 사용한 SSO는 각 서비스에서 독립적으로 인증하는 대신, 하나의 인증 서비스를 통해 한 번의 로그인으로 여러 서비스에 접근합니다.
코드 예시:
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// SSO 서비스 로그인 예시
app.post('/sso/login', (req, res) => {
// 사용자 정보를 검증하고 유효한 사용자라면 사용자 ID로 JWT를 발급합니다.
const user = {
id: 123,
username: 'user123',
role: 'admin', // 사용자의 권한 등을 포함한 정보
};
// JWT 생성
const token = jwt.sign(user, 'sso_secret_key', { expiresIn: '1h' });
res.json({ token });
});
// 다른 서비스에서 SSO 토큰을 이용한 인증 검증 미들웨어 예시
function authenticateToken(req, res, next) {
const ssoToken = req.headers['sso-authorization'];
if (!ssoToken) {
return res.sendStatus(401); // Unauthorized
}
jwt.verify(ssoToken, 'sso_secret_key', (err, user) => {
if (err) {
return res.sendStatus(403); // Forbidden
}
req.user = user;
next();
});
}
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
위의 코드 예시들은 간단한 노드js 서버를 구현한 것으로, 실제로 사용되는 시스템에서는 보안 및 에러 처리 등에 추가적인 구현이 필요할 수 있습니다. 실제 서비스에서는 보안에 신경을 써야 하며, 비밀 키 관리, HTTPS 사용 등을 고려해야 합니다.
NestJS에서 JWT 라이브러리를 사용하는 시나리오를 코드 예시와 함께 설명하겠습니다. NestJS에서는 @nestjs/jwt
패키지를 사용하여 JWT를 쉽게 구현할 수 있습니다.
먼저, NestJS 프로젝트를 설정하고 @nestjs/jwt
패키지를 설치해야 합니다.
npm install --save @nestjs/jwt
다음으로, NestJS 애플리케이션 모듈에 JwtModule을 등록하고 JWT의 시크릿 키와 유효성 검사 옵션을 설정해야 합니다.
// app.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth/auth.service';
import { AuthController } from './auth/auth.controller';
@Module({
imports: [
JwtModule.register({
secret: 'SECRET_KEY', // JWT를 암호화/복호화하는데 사용되는 시크릿 키
signOptions: { expiresIn: '1h' }, // JWT 유효기간 설정 (예: 1시간)
}),
],
controllers: [AuthController],
providers: [AuthService],
})
export class AppModule {}
이제 AuthService에서 로그인과 JWT 토큰 발행을 처리하는 로직을 구현해보겠습니다.
// auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(private readonly jwtService: JwtService) {}
// 사용자 로그인 로직 (DB와 연동하여 사용자 인증)
async login(username: string, password: string) {
const user = await this.validateUser(username, password);
if (!user) {
throw new Error('Invalid credentials');
}
// 로그인이 성공하면 JWT 토큰 발행
const payload = { username: user.username, sub: user.userId };
return {
access_token: this.jwtService.sign(payload),
};
}
// 사용자 인증 검증 (예시로 단순히 확인만 수행)
async validateUser(username: string, password: string): Promise<any> {
// 예시로 사용자를 하나 정의하고 인증 수행
const user = { userId: 1, username: 'testuser', password: 'password' };
return user.username === username && user.password === password ? user : null;
}
}
마지막으로, AuthController에서 로그인 요청을 처리하고 JWT 토큰을 클라이언트에게 반환해줍니다.
// auth/auth.controller.ts
import { Controller, Post, Request, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('login')
async login(@Body() body: any) {
const { username, password } = body;
return this.authService.login(username, password);
}
}
이제 NestJS 애플리케이션에 JWT 인증이 구현되었습니다. 사용자가 POST /auth/login
엔드포인트에 유효한 자격 증명을 제공하면 서버에서 JWT 토큰을 발행하고 해당 토큰을 클라이언트에게 반환합니다. 클라이언트는 이후 보호된 API 엔드포인트에 JWT 토큰을 Authorization 헤더 등에 포함하여 요청을 보내어 인증될 수 있습니다. API 보호를 위해 Guards
와 함께 사용할 수도 있습니다.