티스토리 뷰

1. OAuth의 작동

1) 인증(Authentication) : 사용자가 신뢰할 수 있는 인증 제공자(google, naver, kakao 등)를 통해 인증

2) 권한 부여(Authorization) : 사용자가 특정 리소스(예: 이메일, 사진 등)에 대한 엑세스를 승인

3) 엑세스 토큰 발급 : 인증 서버가 발급하는 짧은 수명의 토큰으로, 클라이언트가 API에 요청을 보낼 때 사용

 

2. 엑세스 토큰(Access Token)

- 사용자를 대신하여 보호된 리소스에 액세스하는데 필요한 키 

 

3. 토큰 관리 원칙

- 짧은 유효기간 : 토큰은 만료 시간이 짧아야 하며, 장기 토큰을 피한다

- 리프레시 토큰 사용: 만료된 액세스 토큰을 갱신하기 위해 리프레시 토큰을 사용

- JWT(Json Web Token) : 서명된 형태로 데이터 페이로드와 함께 제공되며, 추가적인 인증 서버 호출 없이 검증 가능

- JWT의 만료 시간을 짧게 설정하여 보안성을 높이지만, 매번 사용자에게 다시 로그인하게 하면 불편해 리프레시 토큰을 서버에 별도로 저장해 엑세스 토큰 갱신 요청시 추가 검증 과정을 거쳐 사용하기도함

 

* JWT 구조

1) Header : 토큰의 타입(JWT)과 서명에 사용된 알고리즘 정보를 포함

2) Payload: 토큰에 포함된 클레임 정보(사용자 ID, 역할, 토큰 만료 시간 등)

3) Signature: Header와 Payload를 비밀 키를 사용해 서명하여 생성. 토큰의 무결성을 검증

* JWT 특징

- 토큰에 필요한 모든 정보가 포함되어 있으므로 서버가 상태 정보를 저장할 필요가 없음

- 클라이언트에서 제공된 JWT가 조작되지 않았음을 검증 간으

- 일반적으로 JWT는 짧은 유효기간을 가지며, 만료 후 갱신 필요

* JWT 사용 예시

- 클라이언트가 서버에 로그인 요청> 서버가 사용자 정보를 검증한 후 JWT를 생성해 반환> 클라이언트는 이JWT를 저장(Local Storage 또는 HttpOnly 쿠키)하고, 요청마다 Authorization: Bearer <JWT> 헤더에 포함하여 보냄

 

4. 쿠키와 보안 설정

- Secure: HTTPS 연결에서만 쿠키가 전송되도록 설정

- HttpOnly: JavaScript로 쿠키에 접근하지 못하도록 설정하여 XSS 공격을 방지

- SameSite: CSRF(Cross-Stie Request Forgery) 공격을 방지하기 위해 Strict 또는 Lax로 설정

- Token Storage: 엑세스 토큰은 로컬 스토리지 대신 HttpOnly 쿠키에 저장하여 안전하게 관리

 

*HTTPOnly 쿠키와 Token Storage 비교

항목 HttpOnly 쿠키 Token Storage
보안성 XSS에 강함 (JavaScript 접근 불가) XSS에 취약 (JavaScript 접근 가능)
CSRF 취약성 CSRF에 취약(SameSite 속성으로 방지 가능) CSRF에 강함(자동 전송 없음)
편의성 자동으로 요청에 포함 수동으로 헤더 추가 필요
브라우저 외 환경 지원이 제한적(웹브라우저 중심) RESTful API호출에 적합

 

5. 미들웨어

- 요청이 처리되는 동안 인증 및 권한 부여 논리를 삽입할 수 있는 계층

- 미들웨어 사용 패턴

1) 엑세스 토큰 검증

- 요청 헤더의 Authorization: Bearer <token>을 읽음

- 토큰 유효성을 확인하고, 유효하지 않으면 401 응답

 

2) 쿠키에서 토큰 추출

- 쿠키에 저장된 엑세스 토큰을 읽고 디코딩

- 사용자 권한을 확인

 

3) 로그인 상태 유지

- 리프레시 토큰을 사용해 엑세스 토큰을 갱신

- 토큰 갱신 로직을 미들웨어에 포함하여 사용자 경험을 개선

 

<구현 예시>

from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from jose import JWTError, jwt

app = FastAPI()

# JWT 토큰 검증을 위한 키 및 알고리즘
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"

# 미들웨어를 통한 요청 처리
@app.middleware("http")
async def validate_token(request: Request, call_next):
    token = request.cookies.get("access_token")  # 쿠키에서 토큰 추출
    if token:
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            request.state.user = payload  # 유효한 경우 사용자 정보 저장
        except JWTError:
            raise HTTPException(status_code=401, detail="Invalid token")
    return await call_next(request)

@app.get("/secure-endpoint")
async def secure_endpoint(request: Request):
    if not request.state.user:
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {"message": "Welcome, authorized user!"}


6. 보안 최적화

- HTTPS 적용: 모든 통신에 SSL/TLS를 사용해 데이터 암호화

- CSRF 방지: 쿠키 기반 인증을 사용하는 경우 CSRF 토큰 사용

- IP 및 디바이스 제한: 인증 시 IP 또는 디바이스 기반 필터링 추가

- 토큰 블랙리스트: 만료되거나 강제로 무효화된 토큰 처리

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함