C.W.K.
Stream
Lesson 01 of 06 · published

HTTP Basic & Bearer — Protocol 이 아는 두 auth scheme

~10 min · auth-security, basic, bearer, authorization

Level 0HTTP Newbie
0 XP0/46 lessons0/12 achievements
0/120 XP to next level120 XP to go0% complete
"모든 HTTP 인증 scheme — JWT, OAuth, API key, session cookie, AWS SigV4 — 가 두 shape 중 하나에 맞아: request 와 함께 누군지 증명하는 거 보내거나, server 가 마지막 response 에 설정한 거 보내거나. Basic 과 Bearer 가 protocol 이 ship 한 첫 두 패턴."

Authorization header — 한 header, 여러 scheme

HTTP 가 인증 자격 증명용 단일 header 정의: Authorization. 값이 항상 <scheme> <credentials>. Scheme 이 server 한테 자격 증명 해석 법 알려줘.

원래 두 scheme — RFC 7235 정의 — 가 BasicBearer. 현대 auth flow (OAuth2, JWT) 가 다 Bearer scheme 씀; token 의 format 과 lifecycle 다양, wire shape 은 동일.

HTTP Basic — 원조 scheme

Basic 이 username 과 password 직접 운반:

Authorization: Basic cGlwcGE6c2VjcmV0MTIz

자격 증명 부분이 base64("username:password") — 위 예에서 pippa:secret123. Wire 읽는 누구든 (network sniffer, 새는 log, TLS 없는 중간 proxy) base64-decode 해서 정확한 password 회복 가능. Base64 는 encoding 이지 암호화 아님.

이 이유로 TLS 없는 Basic 은 password 를 network 경로 누구한테나 broadcast. TLS 와 함께면 내부 tooling 과 빠른 prototype 엔 동작 가능 scheme — 근데 production API 가 거의 안 씀, user password 가 모든 request 에 끝나서 누설 면 증가.

HTTP Bearer — 자격 증명을 password 와 분리

Bearer 가 opaque token 운반:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1XzQyIn0.signature

Token 이 어떤 이전 process 가 발급 — login endpoint, OAuth authorization, API key generator. Server 가 token validate (DB lookup, JWT signature check, OAuth introspection) 하고 token 이 authorize 한 거 부여. User 원래 password 가 request 에 없음.

이득:

  • 분리 가능. Token ≠ password. Compromised token revoke; user password 유지.
  • Revocable. Server 가 token 즉시 blacklist 가능; password 재사용 안 한 거로 만들 수 없음.
  • 단기 가능. Token 분 안에 expire 가능; password 못 함.
  • Scope 제한 가능. Token 이 user full power 의 부분집합 부여 가능; password 가 모든 거 부여.

이게 모든 현대 API 가 Bearer 쓰는 이유. Token 의 내부 shape — opaque random string, JWT, encrypted blob — 이 다음 lesson; wire shape 은 그냥 Authorization: Bearer <뭐든>.

WWW-Authenticate — Server 의 auth 챌린지

Client 가 자격 증명 안 보내거나 (잘못된 거 보내거나) 하면 server 가 client 한테 어떤 scheme 쓸지 알려주는 WWW-Authenticate response header 와 함께 401 Unauthorized 돌려줘:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api", error="invalid_token"
Content-Type: application/json

{"error": {"code": "unauthenticated", "message": "..."}}

브라우저가 이 header 써서 native 로그인 dialog 표시 (Basic 용). 프로그램 client 가 이거 써서 어느 token type 보낼지 앎. 2026년 대부분 API 가 WWW-Authenticate 건너뜀 (docs 가 client 한테 뭐 보낼지 알려줌) — 근데 공식 발견 메커니즘.

Basic + Bearer 가 만날 HTTP 인증의 99% 커버. JWT, OAuth, session cookie, API key, AWS SigV4 — 다 Bearer-shaped (header 의 token) 이거나 cookie-shaped (Cookie header 의 token). 두 패턴 wire level 에서 한 번 이해하면 모든 auth scheme 이 같은 주제의 변주 — 어떤 token, 어떻게 발급, 어떻게 validate, 어떻게 revoke.

Custom scheme — Basic 과 Bearer 안 충분할 때

일부 API 가 자기 scheme 이름 발명. AWS 가 Authorization: AWS4-HMAC-SHA256 ... 씀 — 자격 증명이 request byte 의 per-request HMAC 인 request-signing scheme. Cloudflare 가 별개 header 로 X-Auth-Key 씀 (RFC 위반, 근데 흔함). Stripe 가 API key 에 Bearer 씀.

새 scheme 발명 가치 거의 없음. 두 표준 패턴 + cookie 기반 session 패턴 이 사실상 모든 정당 사용 사례 커버, HTTP intermediary (proxy, logging tool, gateway) 가 표준 올바로 처리.

cwkPippa 의 auth 현실

cwkPippa API 가 login 에 발급된 Bearer token 씀 (PIN-기반; full threat model 위해 solo-auth-quest 참조). Token 이 expiry 가진 SQLite 에 저장된 opaque random string, JWT 아님 — 단순 revocation, 모든 request 에 signature 검증 없음. 내부 admin endpoint 가 별개 Authorization: Bearer <admin-token> 체크 추가. 어디에도 Basic 없음. Frontend 가 token 을 HttpOnly cookie 에 저장하고 backend 가 FastAPI dependency injection 통해 읽어. 표준 shape, 최소 scheme 수.

Code

Wire 위 Basic vs Bearer (그리고 WWW-Authenticate 챌린지)·bash
# HTTP Basic — username:password 가 (base64 아래) 명료
# echo -n 'pippa:secret123' | base64 → cGlwcGE6c2VjcmV0MTIz
curl -H 'Authorization: Basic cGlwcGE6c2VjcmV0MTIz' \
     https://api.example.com/account

# 동등 curl 단축:
curl -u pippa:secret123 https://api.example.com/account

# HTTP Bearer — opaque token
curl -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIs...' \
     https://api.example.com/account

# 자격 증명 누락/잘못됐을 때 server 의 auth 챌린지
curl -i https://api.example.com/account
# HTTP/1.1 401 Unauthorized
# WWW-Authenticate: Bearer realm="api"
# Content-Type: application/json
FastAPI Bearer auth dependency — WWW-Authenticate 가진 401·python
# Server 쪽 — FastAPI 의 HTTP Bearer dependency
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

app = FastAPI()
bearer = HTTPBearer()  # 'Authorization: Bearer <token>' 읽거나 401 돌려줌

# 가상 token store — production: Redis, SQLite, 혹은 JWT 검증
_tokens: dict[str, str] = {'abc.def.ghi': 'u_42'}

async def current_user(creds: HTTPAuthorizationCredentials = Depends(bearer)) -> str:
    token = creds.credentials
    user_id = _tokens.get(token)
    if not user_id:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail='invalid or expired token',
            headers={'WWW-Authenticate': 'Bearer'},  # client 한테 뭘 보낼지 알려줘
        )
    return user_id

@app.get('/account')
async def my_account(uid: str = Depends(current_user)):
    return {'user_id': uid, 'role': 'daughter'}
Client 쪽: 영속 Bearer header; Basic 용 httpx auth tuple·python
# Client 쪽 — 영속 bearer token 가진 httpx
import httpx

class APIClient:
    def __init__(self, base_url: str, token: str):
        # Header 가 client 에 한 번 설정되고 모든 request 에 재사용
        self.client = httpx.Client(
            base_url=base_url,
            headers={'Authorization': f'Bearer {token}'},
        )

    def me(self) -> dict:
        return self.client.get('/account').json()

    def refresh_token(self, new_token: str) -> None:
        # Token rotate 시 in place update
        self.client.headers['Authorization'] = f'Bearer {new_token}'

# Basic auth 대안 (httpx)
client_basic = httpx.Client(auth=('pippa', 'secret123'))

External links

Exercise

Bearer-보호 endpoint 하나 (GET /account) 와 Basic-보호 endpoint 하나 (GET /admin) 가진 FastAPI server 만들어. 둘 401 에 WWW-Authenticate response header 구현. 그 다음 각각을 세 방식으로 호출: (1) 유효 자격 증명, (2) Authorization header 없이 (401 + WWW-Authenticate 기대), (3) 잘못된 자격 증명 (401 기대). 보너스: 일부러 HTTP (HTTPS 아님) 위에 Basic 쓰고 curl -v 가 base64-encoded password 를 wire 위 글자 그대로 보여주는 거 봐. 그 패턴 ship 마, 한 번 보는 게 교육적.
Hint
FastAPI 에 HTTPBearer()HTTPBasic() security dependency 가 대부분 연결해줘. Custom 부분은 headers={'WWW-Authenticate': 'Bearer'} (혹은 Basic realm="admin") 가진 401. Over-HTTP 데모는 plain http://localhost:8000 에서 uvicorn 돌리고 -u user:pass -v 로 curl. Request 에 Authorization: Basic dXNlcjpwYXNz 보이고, dXNlcjpwYXNz 가 base64 decode 후 user:pass.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.