2025/10/29 miniproject - 2

김기훈·2025년 10월 29일

TIL

목록 보기
45/191

오늘 학습 범위

오늘 학습 내용

  • 클라이언트(예: 브라우저, Postman, 프론트엔드 앱)가 서버로 요청을 보낼 때
    • 추가적인 메타데이터나 인증 정보를 함께 전달하는 방법
GET /users HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...
Content-Type: application/json
User-Agent: Mozilla/5.0
  • Authorization, Content-Type, User-Agent 같은 부분이 헤더(Header)
    • 요청의 본문(body)과는 별개로 서버에
    • “이 요청은 어떤 종류의 데이터고, 누가 보낸 것이며, 어떤 인증을 거쳤는지” 등을 알려주는 역할

HTTPBearer / OAuth2PasswordBearer

  • 공통점
    • FastAPI의 fastapi.security 모듈에서 제공하는 “보안 스킴(Security Scheme)” 클래스
    • HTTP 요청 헤더(Authorization)에서 토큰을 추출하는 역할을 함
      • Authorization: Bearer <토큰>

HTTPBearer

  • “헤더에서 Bearer 토큰 문자열을 꺼내주는 역할만” 함
    • 토큰의 내용이 JWT인지, 유효한지 등은 직접 검증해야 함
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer

security = HTTPBearer()

@app.get("/secure")
async def secure_endpoint(credentials=Depends(security)):
    token = credentials.credentials  # 단순히 Authorization 헤더에서 토큰 꺼냄
    if token != "mysecrettoken":
        raise HTTPException(status_code=401, detail="Invalid token")
    return {"msg": "Access granted"}
  • 단순히 Authorization: Bearer <token> 을 읽음.
    • Swagger UI에서 “Authorize” 버튼을 누르면 Bearer 토큰 입력칸이 뜸.
    • 토큰의 검증 로직은 전부 직접 작성해야 함.

OAuth2PasswordBearer

  • OAuth2 인증 흐름에 맞춘 고수준 도구, 주로 JWT 로그인/로그아웃 구현에 사용
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
    1. /auth/login 경로를 통해 사용자에게 토큰을 발급받는 엔드포인트가 있다고 가정
    1. Swagger UI에서 “Authorize” 버튼을 누르면 자동으로 /auth/login 경로를 보여주고
    • 로그인 → 토큰 발급을 시뮬레이션할 수 가능
    1. 이후 엔드포인트에서 Depends(oauth2_scheme)을 사용하면,
    • Authorization 헤더의 토큰을 자동으로 추출해서 전달해줌.

예시

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt, JWTError

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    # 여기서 토큰 검증 (JWT decode)
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get("sub")
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")
    return {"username": username}

어려운 내용(추가 학습 필요)

오늘 발생한 문제(발생 했다면)

등록 / 로그인 은 완전하게 작동하는데 로그아웃의 문제

  • 문제 1. 로그아웃을 진행하면 422 (token missing)이 발생

    • 원인: oauth2_scheme이 tokenUrl="/auth/login" 으로 설정되어 있는데,
      • 이걸 사용하는 엔드포인트(logout)에서 의존성 주입이 누락된 형태로 쓰였기 때문
      • 즉, get_current_user()가 토큰을 직접 받지 않고 있음
    • 해결: get_current_user(token: str):
      • get_current_user(token: str = Depends(oauth2_scheme)): 이렇게 변경
  • 문제 2. 422 해결했더니 401("Invalid token") 발생

    • 원인
        1. JWT가 잘못된 문자열
        1. Secret key 불일치
        1. 만료된 토큰
        1. 알고리즘 불일치
    • 4가지중 3번 만료된 토큰 문제였음 토큰 새로 생성해서 성공

로그아웃이 postman에서는 가능한데 docs에서는 안됨

  • OAuth2PasswordBearer
    • 이거를 사용하면 docs에서 401만 뜸
  • HTTPBearer
    • 이거를 사용하니까 문제가 바로 해결됨
  • 원인
    • Postman은 직접 Authorization → Bearer Token으로 토큰을 헤더에 넣으면
      • token: str = Depends(oauth2_scheme) 이 코드가 토큰을 읽고
        • jwt.decode() → payload 검증 → 통과
    • Swagger (docs)에서는 OAuth2PasswordBearer(tokenUrl="/auth/login")을 쓰면
      • Swagger는 “OAuth2 Password Flow 전체를 처리하는 UI”를 띄우는데
        • 이 UI는 로그인 요청 → 토큰 발급 → 헤더 삽입을 자동으로 해주지 않음
        • docs에서는 Authorization 헤더가 비어 있으니 FastAPI가 401 내보냄
        • 즉, Swagger가 “자동으로 토큰을 들고 가는” 걸 지원 안 하는 구조

OAuth2PasswordBearer 터미널에서 작동 확인하기

profile
안녕하세요.

0개의 댓글