기술과 산업/언어 및 프레임워크
FastAPI 시리즈 11화 - OAuth2 이해와 FastAPI 로그인 인증 시스템 구축
B컷개발자
2025. 5. 23. 17:01
728x90
FastAPI에서 OAuth2PasswordBearer와 JWT(Json Web Token)를 이용해 사용자 인증 시스템을 구축하는 방법을 설명합니다. 실전 로그인/토큰 발급/보호된 엔드포인트 예제를 포함합니다.
OAuth2는 왜 필요할까?
API 기반 서비스에서 “로그인”은 단순한 기능이 아닙니다.
다음과 같은 보안 요구사항을 만족해야 합니다:
- 사용자 식별 및 인증
- 액세스 권한 제한
- 비밀번호 노출 방지
- Stateless 인증 처리
FastAPI는 OAuth2 흐름을 기본 지원하며, 여기에 JWT(JSON Web Token)를 결합해
RESTful하고 안전한 인증 체계를 구현할 수 있습니다.
1. OAuth2PasswordBearer 기본 구조
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
- tokenUrl="token": 클라이언트가 토큰을 발급받기 위해 POST 요청할 URL
- Swagger UI에 자동으로 인증 입력 필드 추가됨
2. JWT 토큰 발급 함수 정의
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "mysecret"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
- JWT는 jose 라이브러리 사용 (pip install python-jose)
- data: 토큰에 포함할 정보 (예: username)
- exp: 만료시간 설정
3. 로그인 엔드포인트 구현
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
app = FastAPI()
# 사용자 인증 로직 (간단 예시)
def authenticate_user(username: str, password: str):
if username == "admin" and password == "secret":
return {"username": username}
return None
@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=400, detail="Invalid credentials")
access_token = create_access_token(data={"sub": user["username"]})
return {"access_token": access_token, "token_type": "bearer"}
- /token으로 POST 요청 시 username, password 수신
- 성공 시 access_token 반환
4. 보호된 엔드포인트 만들기
from fastapi import Security
from jose import JWTError, jwt
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid token")
return {"username": username}
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
@app.get("/secure-data")
def read_secure_data(current_user: dict = Depends(get_current_user)):
return {"user": current_user, "data": "This is protected data"}
- 헤더에 Authorization: Bearer <token> 포함 시 인증 통과
- 토큰이 없거나 만료된 경우 401 반환
5. Swagger UI에서 인증 테스트
- /token 엔드포인트에 username=admin, password=secret 입력
- 발급된 access_token 복사
- /secure-data 엔드포인트 → 상단 “Authorize” 클릭
- Bearer <token> 형식으로 토큰 입력 후 API 호출
Swagger UI에서도 OAuth2 흐름을 완벽히 시뮬레이션할 수 있습니다.
6. 실무 적용 팁
항목설명
| 사용자 DB 연동 | 실제 DB 조회 로직으로 대체 필요 |
| 비밀번호 해싱 | bcrypt 등으로 암호화 후 비교 |
| 리프레시 토큰 | 액세스 토큰 만료 시 재발급 구조 구현 가능 |
| 권한(Role) 관리 | JWT payload에 role 필드 포함 후 인증 로직에 조건 추가 |
정리 – FastAPI는 OAuth2 인증도 기본 내장
기능구성 요소
| 로그인 | OAuth2PasswordRequestForm |
| 토큰 발급 | create_access_token() |
| 토큰 인증 | OAuth2PasswordBearer + JWT decode |
| 보호된 API | Depends(get_current_user) |
FastAPI의 인증 구조는 OAuth2 흐름을 그대로 따르면서도
코드가 매우 간결하고 문서화까지 자동으로 제공된다는 점이 큰 장점입니다.
다음 글 예고
FastAPI 시리즈 12화 - JWT 기반 인증 시스템 완성: 토큰 구조와 보안 처리 심화
에서는 JWT의 내부 구조, 서명 방식, 보안 취약점 대응까지 고려한
실전 인증 시스템 완성 전략을 다룹니다.
728x90