[python] FastAPI에서 JWT 인증 구현하기

이번 포스트에서는 FastAPI 프레임워크를 사용하여 JWT(Jason Web Token) 인증을 구현하는 방법에 대해 알아보겠습니다. JWT는 인증과 권한 부여를 위해 사용되는 토큰 기반의 인증 방식으로, 클라이언트와 서버 간의 통신을 보안하는 데 사용됩니다.

준비 작업

프로젝트를 시작하기 전에 몇 가지 패키지를 설치해야 합니다. 다음 명령어를 사용하여 필요한 패키지를 설치합니다.

pip install fastapi pyjwt python-multipart

JWT 토큰 생성

FastAPI에서 JWT 인증을 구현하기 위해서는 먼저 JWT 토큰을 생성해야 합니다. 이를 위해 PyJWT 패키지를 사용할 수 있습니다. 다음은 JWT 토큰을 생성하는 예제 코드입니다.

import jwt

def create_token(data: dict, secret_key: str, algorithm: str = "HS256") -> str:
    token = jwt.encode(data, secret_key, algorithm=algorithm)
    return token

위의 코드에서 data는 토큰에 포함되는 데이터를 나타내는 딕셔너리입니다. secret_key는 토큰의 서명에 사용되는 비밀 키이며, algorithm은 토큰의 암호화 알고리즘을 지정합니다.

JWT 토큰 확인

다음으로는 FastAPI 애플리케이션에서 JWT 토큰을 확인하는 방법을 알아보겠습니다. 여기서는 FastAPI의 미들웨어를 사용하여 인증을 처리할 것입니다.

from fastapi import FastAPI, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt

app = FastAPI()
security = HTTPBearer()

async def verify_token(token: str, secret_key: str) -> bool:
    try:
        jwt.decode(token, secret_key, algorithms=["HS256"])
        return True
    except jwt.JWTError:
        return False

@app.middleware("http")
async def authenticate(request: Request, call_next):
    credentials: HTTPAuthorizationCredentials = security(request)
    token = credentials.credentials

    if not await verify_token(token, secret_key):
        raise HTTPException(status_code=401, detail="Invalid or expired token")

    response = await call_next(request)
    return response

위의 코드에서 verify_token 함수는 토큰의 유효성을 검사하고, authenticate 미들웨어 함수는 요청 헤더에서 토큰을 추출하고 유효성을 확인하는 역할을 담당합니다. 유효하지 않은 토큰이나 만료된 토큰이 전송된 경우, HTTPException을 발생시켜 인증 오류를 처리합니다.

테스트

이제 FastAPI 애플리케이션을 실행하고 토큰을 테스트해볼 수 있습니다.

from fastapi.testclient import TestClient

client = TestClient(app)

def test_invalid_token():
    response = client.get("/protected", headers={"Authorization": "Bearer invalid_token"})
    assert response.status_code == 401
    assert response.json() == {"detail": "Invalid or expired token"}

def test_valid_token():
    token = create_token({"username": "example"}, secret_key="secret")
    response = client.get("/protected", headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == 200
    assert response.json() == {"message": "Protected route"}

위의 테스트 코드에서 test_invalid_token은 유효하지 않은 토큰을 전송하였을 때를 테스트하고, test_valid_token은 유효한 토큰을 전송하였을 때를 테스트합니다.

결론

FastAPI 프레임워크를 사용하여 JWT 인증을 구현하는 방법에 대해 살펴보았습니다. JWT는 간편한 사용법과 보안성을 제공하여 웹 애플리케이션의 인증과 권한 부여에 유용한 도구입니다. FastAPI와 JWT를 함께 사용하여 안전하고 신뢰할 수 있는 애플리케이션을 개발할 수 있습니다.