[python] FastAPI에서 인증 토큰 발급 및 검증 구현하기

FastAPI는 Python으로 작성된 빠르고 현대적인 웹 프레임워크로, HTTP 요청과 응답을 처리하는 데 특화되어 있습니다. 이 글에서는 FastAPI를 사용하여 간단한 인증 토큰 발급 및 검증 방법을 알아보겠습니다.

1. JWT(JSON Web Token) 소개

JWT는 인증과 정보 교환을 위해 사용되는 JSON 기반의 토큰입니다. 토큰 안에는 클레임(Claim)이라는 정보 조각들을 포함하고 있으며, 서명을 이용하여 검증됩니다. 사용자의 인증 정보를 토큰으로 전달하고, 서버에서는 토큰을 검증하여 사용자를 인증하는 방식으로 주로 사용됩니다.

2. FastAPI에서 JWT 사용하기

FastAPI에서 JWT를 사용하기 위해서는 먼저 PyJWT 라이브러리를 설치해야 합니다. 다음 명령어를 사용하여 설치합니다.

pip install PyJWT

그리고 다음과 같이 필요한 모듈을 임포트합니다.

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from jwt import PyJWTError
from typing import Optional

3. 토큰 발급 및 검증 기능 구현

# JWT 설정
SECRET_KEY = "*****************"  # 실제 사용시에는 랜덤한 값으로 변경해야 합니다.
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60

# FastAPI 애플리케이션 인스턴스 생성
app = FastAPI()

# JWT 검증을 위한 의존성 선언
security = HTTPBearer()

# 토큰 발급
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# 토큰 검증 및 사용자 인증
async def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security)
):
    try:
        payload = jwt.decode(
            credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM]
        )
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid authentication credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
    except PyJWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )

# 토큰 발급 API
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    # 사용자 인증 과정 생략 (사용자 이름과 비밀번호 검증)

    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": form_data.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

# 보호된 API 엔드포인트
@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

4. 사용 예제

토큰 발급 API를 통해 토큰을 발급받은 후, 보호된 API 엔드포인트에 해당 토큰을 전달하여 호출할 수 있습니다.

# 토큰 발급 받기
$ curl -X POST "http://localhost:8000/token" -H "Content-Type: application/x-www-form-urlencoded" -d "username=test&password=test"

# 반환된 토큰으로 보호된 API 호출
$ curl -X GET "http://localhost:8000/users/me" -H "Authorization: Bearer [토큰값]"

위 예제에서는 토큰을 발급받은 사용자에게만 /users/me 엔드포인트를 접근할 수 있도록 보호한 것을 확인할 수 있습니다.

FastAPI를 사용하여 인증 토큰 발급 및 검증 기능을 구현했습니다. 이를 활용하여 안전하고 보안성 높은 웹 애플리케이션을 개발할 수 있습니다. 자세한 사항은 FastAPI 공식 문서를 참조하시기 바랍니다.