[python] FastAPI에서 JWT 토큰 갱신 구현하기

이번 포스트에서는 FastAPI에서 JWT 토큰 갱신을 구현하는 방법에 대해 알아보겠습니다. JWT는 JSON Web Token의 약자로, 인증과 정보 교환을 위해 사용되는 기술입니다. 토큰이 만료되면 재발급해야 하는데, 이를 간편하게 처리하기 위해 FastAPI에서 제공하는 기능을 사용할 수 있습니다.

FastAPI의 JWT 기능 활용

FastAPI는 PyJWT 라이브러리를 사용하여 JWT 토큰을 생성하고 유효성을 검사할 수 있는 기능을 제공합니다. 이를 활용하여 토큰 생성, 갱신, 검사 등을 간단하게 구현할 수 있습니다.

먼저, FastAPI와 PyJWT를 설치해줍니다.

pip install fastapi
pip install python-jose
from fastapi import FastAPI
from fastapi import Depends
from fastapi import HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import jwt

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    # 유저 정보를 확인하고, 유효한 경우 토큰을 생성하여 반환
    # 여기서는 단순 예시를 위해 하드코딩으로 처리합니다.
    user_authenticated = True

    if user_authenticated:
        token = {
            "access_token": jwt.encode({"sub": form_data.username}, "secret_key", algorithm="HS256"),
            "token_type": "bearer"
        }
        return token
    else:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")

@app.post("/token/refresh")
async def refresh_token(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, "secret_key", algorithms=["HS256"])
        refreshed_token = {
            "access_token": jwt.encode({"sub": payload.get("sub")}, "secret_key", algorithm="HS256"),
            "token_type": "bearer"
        }
        return refreshed_token
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token has expired")
    except jwt.JWTError:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")

사용법

위 코드를 실행하고, /token 엔드포인트를 호출하여 토큰을 발급받습니다.

curl -X POST "http://localhost:8000/token" -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=admin"

발급된 토큰은 다음과 같은 형식으로 반환됩니다.

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiJ9.8CzvQ1qEZbA5escc-1nhqj_5OrYKfCqrN7St5dS-Mro",
  "token_type": "bearer"
}

이후, /token/refresh 엔드포인트를 호출하여 토큰을 갱신합니다.

curl -X POST "http://localhost:8000/refresh" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiJ9.8CzvQ1qEZbA5escc-1nhqj_5OrYKfCqrN7St5dS-Mro"

발급된 토큰은 유효기간이 갱신된 상태로 반환됩니다.

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiJ9.CS8ZfBMJxDtTGQVuG9xocNe8S5VGVqxgdOGmBAxvIjI",
  "token_type": "bearer"
}

이제 토큰을 사용하여 API를 호출할 때는 발급된 토큰을 Authorization 헤더에 포함시켜 보내면 됩니다.

결론

FastAPI를 사용하여 JWT 토큰 갱신 기능을 구현하는 방법을 알아보았습니다. JWT를 이용하면 유저 인증 및 인가를 간편하게 처리할 수 있고, FastAPI의 기능을 사용하면 손쉽게 구현할 수 있습니다.