Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1e026d5
🌐 Add Korean translation for /docs/ko/docs/tutorial/security/oauth2-j…
yes0ng Feb 8, 2025
9a3aa52
🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
pre-commit-ci[bot] Feb 8, 2025
88f97c0
🌐 Add Korean translation for /docs/ko/docs/tutorial/security/oauth2-j…
yes0ng Feb 9, 2025
141842c
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
e33c740
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
119cf1d
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
6e23f66
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
e5b60bf
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
6201d39
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
77d00dc
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 10, 2025
1bf5364
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 11, 2025
b390078
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 11, 2025
44a8ba4
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 11, 2025
f469efa
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 19, 2025
9145f42
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 19, 2025
e3e4e11
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 19, 2025
e259404
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 19, 2025
2c27712
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 19, 2025
5db68e9
Update docs/ko/docs/tutorial/security/oauth2-jwt.md
yes0ng Feb 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
273 changes: 273 additions & 0 deletions docs/ko/docs/tutorial/security/oauth2-jwt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
# νŒ¨μŠ€μ›Œλ“œ 해싱을 μ΄μš©ν•œ OAuth2, JWT 토큰을 μ‚¬μš©ν•˜λŠ” Bearer 인증

λͺ¨λ“  λ³΄μ•ˆ 흐름을 κ΅¬μ„±ν–ˆμœΌλ―€λ‘œ, 이제 <abbr title="JSON Web Tokens">JWT</abbr> 토큰과 νŒ¨μŠ€μ›Œλ“œ 해싱을 μ‚¬μš©ν•΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ•ˆμ „ν•˜κ²Œ λ§Œλ“€ κ²ƒμž…λ‹ˆλ‹€.

이 μ½”λ“œλŠ” μ‹€μ œλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ νŒ¨μŠ€μ›Œλ“œλ₯Ό ν•΄μ‹±ν•˜μ—¬ DB에 μ €μž₯ν•˜λŠ” λ“±μ˜ μž‘μ—…μ— ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이전 μž₯에 μ΄μ–΄μ„œ μ‹œμž‘ν•΄ λ΄…μ‹œλ‹€.

## JWT

JWT λŠ” "JSON Web Tokens" 을 μ˜λ―Έν•©λ‹ˆλ‹€.

JSON 객체λ₯Ό 곡백이 μ—†λŠ” κΈ΄ λ¬Έμžμ—΄λ‘œ μΈμ½”λ”©ν•˜λŠ” ν‘œμ€€μ΄λ©°, λ‹€μŒκ³Ό 같은 ν˜•νƒœμž…λ‹ˆλ‹€:

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```

JWTλŠ” μ•”ν˜Έν™”λ˜μ§€ μ•Šμ•„ λˆ„κ΅¬λ“ μ§€ ν† ν°μ—μ„œ 정보λ₯Ό 볡원할 수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ JWTλŠ” μ„œλͺ…λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μžμ‹ μ΄ λ°œκΈ‰ν•œ 토큰을 λ°›μ•˜μ„ λ•Œ, μ‹€μ œλ‘œ μžμ‹ μ΄ λ°œκΈ‰ν•œκ²Œ λ§žλŠ”μ§€ 검증할 수 μžˆμŠ΅λ‹ˆλ‹€.

만료 기간이 일주일인 토큰을 λ°œν–‰ν–ˆλ‹€κ³  κ°€μ •ν•΄ λ΄…μ‹œλ‹€. λ‹€μŒ λ‚  μ‚¬μš©μžκ°€ 토큰을 가져왔을 λ•Œ, κ·Έ μ‚¬μš©μžκ°€ μ‹œμŠ€ν…œμ— μ—¬μ „νžˆ λ‘œκ·ΈμΈλ˜μ–΄ μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

일주일 λ’€μ—λŠ” 토큰이 만료될 것이고, μ‚¬μš©μžλŠ” μΈκ°€λ˜μ§€ μ•Šμ•„ μƒˆ 토큰을 λ°›κΈ° μœ„ν•΄ λ‹€μ‹œ λ‘œκ·ΈμΈν•΄μ•Ό ν•  κ²ƒμž…λ‹ˆλ‹€. λ§Œμ•½ μ‚¬μš©μž(λ˜λŠ” 제3자)κ°€ 토큰을 μˆ˜μ •ν•˜κ±°λ‚˜ λ§Œλ£ŒμΌμ„ λ³€κ²½ν•˜λ©΄, μ„œλͺ…이 μΌμΉ˜ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ•Œμ•„μ±Œ 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

λ§Œμ•½ JWT 토큰을 닀뀄보고, μž‘λ™ 방식도 μ•Œμ•„λ³΄κ³  μ‹Άλ‹€λ©΄ <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a> 을 ν™•μΈν•˜μ‹­μ‹œμ˜€.

## `PyJWT` μ„€μΉ˜

파이썬으둜 JWT 토큰을 μƒμ„±ν•˜κ³  κ²€μ¦ν•˜λ €λ©΄ `PyJWT` λ₯Ό μ„€μΉ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

[κ°€μƒν™˜κ²½](../../virtual-environments.md){.internal-link target=_blank} 을 λ§Œλ“€κ³  ν™œμ„±ν™”ν•œ λ‹€μŒ `pyjwt` λ₯Ό μ„€μΉ˜ν•˜μ‹­μ‹œμ˜€:

<div class="termy">

```console
$ pip install pyjwt

---> 100%
```

</div>

/// info | μ°Έκ³ 

RSAλ‚˜ ECDSA 같은 μ „μž μ„œλͺ… μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜λ €λ©΄, `pyjwt[crypto]`λΌλŠ” μ•”ν˜Έν™” 라이브러리 μ˜μ‘΄μ„±μ„ μ„€μΉ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

더 μžμ„Έν•œ λ‚΄μš©μ€ <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT μ„€μΉ˜</a> μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

///

## νŒ¨μŠ€μ›Œλ“œ ν•΄μ‹±

"ν•΄μ‹±(Hashing)"은 μ–΄λ–€ λ‚΄μš©(μ—¬κΈ°μ„œλŠ” νŒ¨μŠ€μ›Œλ“œ)을 해석할 수 μ—†λŠ” 일련의 λ°”μ΄νŠΈ μ§‘ν•©(λ‹¨μˆœ λ¬Έμžμ—΄)으둜 λ³€ν™˜ν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

λ™μΌν•œ λ‚΄μš©(λ˜‘κ°™μ€ νŒ¨μŠ€μ›Œλ“œ)을 ν•΄μ‹±ν•˜λ©΄ λ™μΌν•œ λ¬Έμžμ—΄μ„ μ–»μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ κ·Έ λ¬Έμžμ—΄μ„ λ‹€μ‹œ νŒ¨μŠ€μ›Œλ“œλ‘œ 되돌릴 μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€.

### νŒ¨μŠ€μ›Œλ“œλ₯Ό ν•΄μ‹±ν•˜λŠ” 이유

λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό νƒˆμ·¨λ‹Ήν•˜λ”λΌλ„, μΉ¨μž…μžλŠ” μ‚¬μš©μžμ˜ 평문 νŒ¨μŠ€μ›Œλ“œ λŒ€μ‹  ν•΄μ‹œ κ°’λ§Œ 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ μΉ¨μž…μžλŠ” ν›”μΉœ μ‚¬μš©μž νŒ¨μŠ€μ›Œλ“œλ₯Ό λ‹€λ₯Έ μ‹œμŠ€ν…œμ—μ„œ ν™œμš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€. (λŒ€λ‹€μˆ˜ μ‚¬μš©μžκ°€ μ—¬λŸ¬ μ‹œμŠ€ν…œμ—μ„œ λ™μΌν•œ νŒ¨μŠ€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— 평문 νŒ¨μŠ€μ›Œλ“œκ°€ 유좜되면 μœ„ν—˜ν•©λ‹ˆλ‹€.)

## `passlib` μ„€μΉ˜

PassLibλŠ” νŒ¨μŠ€μ›Œλ“œ ν•΄μ‹œλ₯Ό λ‹€λ£¨λŠ” ν›Œλ₯­ν•œ 파이썬 νŒ¨ν‚€μ§€μž…λ‹ˆλ‹€.

λ§Žμ€ μ•ˆμ „ν•œ ν•΄μ‹œ μ•Œκ³ λ¦¬μ¦˜κ³Ό 도ꡬ듀을 μ§€μ›ν•©λ‹ˆλ‹€.

μΆ”μ²œν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ "Bcrypt"μž…λ‹ˆλ‹€.

[κ°€μƒν™˜κ²½](../../virtual-environments.md){.internal-link target=_blank} 을 λ§Œλ“€κ³  ν™œμ„±ν™”ν•œ λ‹€μŒ PassLib와 Bcryptλ₯Ό μ„€μΉ˜ν•˜μ‹­μ‹œμ˜€:

<div class="termy">

```console
$ pip install "passlib[bcrypt]"

---> 100%
```

</div>

/// tip | 팁

`passlib`λ₯Ό μ‚¬μš©ν•˜μ—¬, **Django**, **Flask** 의 λ³΄μ•ˆ ν”ŒλŸ¬κ·ΈμΈμ΄λ‚˜ λ‹€λ₯Έ λ„κ΅¬λ‘œ μƒμ„±ν•œ νŒ¨μŠ€μ›Œλ“œλ₯Ό 읽을 수 μžˆλ„λ‘ μ„€μ •ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μžλ©΄, FastAPI μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό Django μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 같은 λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 데이터λ₯Ό κ³΅μœ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ˜λŠ” 같은 λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ Django μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ μ§„μ μœΌλ‘œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

그리고 μ‚¬μš©μžλŠ” FastAPI μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό Django μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λ™μ‹œμ— λ‘œκ·ΈμΈν•  수 μžˆμŠ΅λ‹ˆλ‹€.

///

## νŒ¨μŠ€μ›Œλ“œμ˜ ν•΄μ‹œμ™€ 검증

ν•„μš”ν•œ 도ꡬλ₯Ό `passlib`μ—μ„œ μž„ν¬νŠΈν•©λ‹ˆλ‹€.

PassLib "μ»¨ν…μŠ€νŠΈ(context)"λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. 이것은 νŒ¨μŠ€μ›Œλ“œλ₯Ό ν•΄μ‹±ν•˜κ³  κ²€μ¦ν•˜λŠ”λ° μ‚¬μš©ν•©λ‹ˆλ‹€.

/// tip | 팁

PassLib μ»¨ν…μŠ€νŠΈλŠ” λ‹€μ–‘ν•œ ν•΄μ‹± μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•  수 μžˆλŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λ©°, 더 이상 μ‚¬μš©μ΄ ꢌμž₯λ˜μ§€ μ•ŠλŠ” 였래된 ν•΄μ‹± μ•Œκ³ λ¦¬μ¦˜μ„ κ²€μ¦ν•˜λŠ” κΈ°λŠ₯도 ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, λ‹€λ₯Έ μ‹œμŠ€ν…œ(Django 같은)μ—μ„œ μƒμ„±ν•œ νŒ¨μŠ€μ›Œλ“œλ₯Ό 읽고 검증할 수 있으며, μƒˆλ‘œμš΄ νŒ¨μŠ€μ›Œλ“œλ₯Ό Bcrypt 같은 λ‹€λ₯Έ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν•΄μ‹±ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

그리고 λ™μ‹œμ— 그런 λͺ¨λ“  μ•Œκ³ λ¦¬μ¦˜κ³Ό ν˜Έν™˜μ„±μ„ μœ μ§€ν•©λ‹ˆλ‹€.

///

μ‚¬μš©μžλ‘œλΆ€ν„° 받은 νŒ¨μŠ€μ›Œλ“œλ₯Ό ν•΄μ‹±ν•˜λŠ” μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

그리고 받은 νŒ¨μŠ€μ›Œλ“œκ°€ μ €μž₯된 ν•΄μ‹œμ™€ μΌμΉ˜ν•˜λŠ”μ§€ κ²€μ¦ν•˜λŠ” 또 λ‹€λ₯Έ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ„ μƒμ„±ν•©λ‹ˆλ‹€.

그리고 μ‚¬μš©μžλ₯Ό μΈμ¦ν•˜κ³  λ°˜ν™˜ν•˜λŠ” 또 λ‹€λ₯Έ ν•¨μˆ˜λ„ μƒμ„±ν•©λ‹ˆλ‹€.

{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}

/// note

μƒˆλ‘œμš΄ (κ°€μ§œ) λ°μ΄ν„°λ² μ΄μŠ€ `fake_users_db`λ₯Ό ν™•μΈν•˜λ©΄, ν•΄μ‹œ 처리된 νŒ¨μŠ€μ›Œλ“œκ°€ μ–΄λ–»κ²Œ μƒκ²ΌλŠ”μ§€ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.

///

## JWT 토큰 처리

μ„€μΉ˜λœ λͺ¨λ“ˆμ„ μž„ν¬νŠΈ ν•©λ‹ˆλ‹€.

JWT 토큰 μ„œλͺ…에 μ‚¬μš©λ  μž„μ˜μ˜ λΉ„λ°€ν‚€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

μ•ˆμ „ν•œ μž„μ˜μ˜ λΉ„λ°€ν‚€λ₯Ό μƒμ„±ν•˜λ €λ©΄ λ‹€μŒ λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•˜μ‹­μ‹œμ˜€:

<div class="termy">

```console
$ openssl rand -hex 32

09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
```

</div>

그리고 μƒμ„±ν•œ λΉ„λ°€ν‚€λ₯Ό 볡사해 λ³€μˆ˜ `SECRET_KEY`에 λŒ€μž…ν•©λ‹ˆλ‹€. (이 예제의 λ³€μˆ˜ 값을 κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜μ§€ λ§ˆμ‹­μ‹œμ˜€.)

JWT 토큰을 μ„œλͺ…ν•˜λŠ” 데 μ‚¬μš©λ  μ•Œκ³ λ¦¬μ¦˜μ„ μœ„ν•œ λ³€μˆ˜ `ALGORITHM` 을 μƒμ„±ν•˜κ³  `"HS256"` 으둜 μ„€μ •ν•©λ‹ˆλ‹€.

토큰 만료 기간을 μœ„ν•œ λ³€μˆ˜λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

응닡을 μœ„ν•œ 토큰 μ—”λ“œν¬μΈνŠΈμ— μ‚¬μš©λ  Pydantic λͺ¨λΈμ„ μ •μ˜ν•©λ‹ˆλ‹€.

μƒˆ μ•‘μ„ΈμŠ€ 토큰을 μƒμ„±ν•˜κΈ° μœ„ν•œ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}

## μ˜μ‘΄μ„± μˆ˜μ •

`get_current_user` ν•¨μˆ˜λ₯Ό 이전과 λ™μΌν•œ 토큰을 받도둝 μˆ˜μ •ν•˜λ˜, μ΄λ²ˆμ—λŠ” JWT 토큰을 μ‚¬μš©ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.

받은 토큰을 λ””μ½”λ”©ν•˜μ—¬ κ²€μ¦ν•œ ν›„ ν˜„μž¬ μ‚¬μš©μžλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

토큰이 μœ νš¨ν•˜μ§€ μ•Šλ‹€λ©΄ HTTP 였λ₯˜λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}

## `/token` 경둜 μž‘μ—… μˆ˜μ •

ν† ν°μ˜ 만료 μ‹œκ°μ„ μ„€μ •ν•˜κΈ° μœ„ν•΄ `timedelta` λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

μ‹€μ œ JWT μ•‘μ„ΈμŠ€ 토큰을 μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€.

{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}

### JWT "주체(subject)" `sub`에 λŒ€ν•œ 기술 μ„ΈλΆ€ 사항

JWT λͺ…세에 λ”°λ₯΄λ©΄ ν† ν°μ˜ 주체λ₯Ό ν¬ν•¨ν•˜λŠ” `sub`λΌλŠ” ν‚€κ°€ μžˆμŠ΅λ‹ˆλ‹€.

μ‚¬μš© μ—¬λΆ€λŠ” μ„ νƒμ‚¬ν•­μ΄μ§€λ§Œ, μ‚¬μš©μžμ˜ 식별 정보λ₯Ό μ €μž₯ν•  수 μžˆμœΌλ―€λ‘œ μ—¬κΈ°μ„œλŠ” 이λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

JWTλŠ” μ‚¬μš©μžλ₯Ό μ‹λ³„ν•˜κ³  μ‚¬μš©μžκ°€ APIλ₯Ό 직접 μ‚¬μš©ν•  수 μžˆλ„λ‘ ν—ˆμš©ν•˜λŠ” 것 외에도 λ‹€λ₯Έ μš©λ„λ‘œ μ‚¬μš©λ  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ "μžλ™μ°¨"λ‚˜ "λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Ό"을 μ‹λ³„ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

그리고 "μžλ™μ°¨λ₯Ό μš΄μ „ν•˜λ‹€"λ‚˜ "λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Όμ„ μˆ˜μ •ν•˜λ‹€"처럼 ν•΄λ‹Ή 엔터티에 λŒ€ν•œ κΆŒν•œμ„ μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έ ν›„ 이 JWT 토큰을 μ‚¬μš©μž(λ˜λŠ” 봇)μ—κ²Œ μ œκ³΅ν•˜λ©΄, 그듀은 계정을 λ”°λ‘œ λ§Œλ“€ ν•„μš” 없이 APIκ°€ μƒμ„±ν•œ JWT ν† ν°λ§ŒμœΌλ‘œ μž‘μ—…(μžλ™μ°¨ μš΄μ „ λ˜λŠ” λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Ό νŽΈμ§‘)을 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ κ°œλ…μ„ ν™œμš©ν•˜λ©΄ JWTλŠ” 훨씬 더 λ³΅μž‘ν•œ μ‹œλ‚˜λ¦¬μ˜€μ—λ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 경우 μ—¬λŸ¬ μ—”ν„°ν‹°κ°€ λ™μΌν•œ IDλ₯Ό κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ fooλΌλŠ” IDλ₯Ό κ°€μ§„ μ‚¬μš©μž, μžλ™μ°¨, λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Όμ΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ ID μΆ©λŒμ„ λ°©μ§€ν•˜κΈ° μœ„ν•΄, μ‚¬μš©μžμ˜ JWT 토큰을 생성할 λ•Œ μ ‘λ‘μ‚¬λ‘œ `sub` ν‚€λ₯Ό μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ `username:` 을 λΆ™μ΄λŠ” λ°©μ‹μž…λ‹ˆλ‹€. 이 μ˜ˆμ œμ—μ„œλŠ” `sub` 값이 `username:johndoe`이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

κ°€μž₯ μ€‘μš”ν•œ 점은 `sub` ν‚€λŠ” 전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ κ³ μœ ν•œ μ‹λ³„μžκ°€ λ˜μ–΄μ•Ό ν•˜λ©° λ¬Έμžμ—΄μ΄μ–΄μ•Ό ν•œλ‹€λŠ” μ μž…λ‹ˆλ‹€.

## ν™•μΈν•΄λ΄…μ‹œλ‹€

μ„œλ²„λ₯Ό μ‹€ν–‰ν•˜κ³  λ¬Έμ„œλ‘œ μ΄λ™ν•˜μ‹­μ‹œμ˜€: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.

λ‹€μŒκ³Ό 같은 μ‚¬μš©μž μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

<img src="/img/tutorial/security/image07.png">

이전과 같은 λ°©λ²•μœΌλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μΈμ¦ν•˜μ‹­μ‹œμ˜€.

λ‹€μŒ 인증 정보λ₯Ό μ‚¬μš©ν•˜μ‹­μ‹œμ˜€:

Username: `johndoe`
Password: `secret`

/// check

μ½”λ“œ 어디에도 평문 νŒ¨μŠ€μ›Œλ“œ "`secret`" 이 μ—†λ‹€λŠ” 점에 μœ μ˜ν•˜μ‹­μ‹œμ˜€. ν•΄μ‹œλœ λ²„μ „λ§Œ μžˆμŠ΅λ‹ˆλ‹€.

///

<img src="/img/tutorial/security/image08.png">

`/users/me/` λ₯Ό ν˜ΈμΆœν•˜λ©΄ λ‹€μŒκ³Ό 같은 응닡을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€:

```JSON
{
"username": "johndoe",
"email": "[email protected]",
"full_name": "John Doe",
"disabled": false
}
```

<img src="/img/tutorial/security/image09.png">

개발자 도ꡬλ₯Ό 열어보면 μ „μ†‘λœ 데이터에 ν† ν°λ§Œ ν¬ν•¨λœ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. νŒ¨μŠ€μ›Œλ“œλŠ” μ‚¬μš©μžλ₯Ό μΈμ¦ν•˜κ³  μ•‘μ„ΈμŠ€ 토큰을 λ°›κΈ° μœ„ν•œ 첫 번째 μš”μ²­μ—λ§Œ μ „μ†‘λ˜λ©°, μ΄ν›„μ—λŠ” μ „μ†‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€:

<img src="/img/tutorial/security/image10.png">

/// note

`Bearer `둜 μ‹œμž‘ν•˜λŠ” `Authorization` 헀더에 μ£Όλͺ©ν•˜μ‹­μ‹œμ˜€.

///

## `scopes` 의 κ³ κΈ‰ μ‚¬μš©λ²•

OAuth2λŠ” "μŠ€μ½”ν”„(scopes)" λΌλŠ” κ°œλ…μ„ κ°–κ³  μžˆμŠ΅λ‹ˆλ‹€.

이λ₯Ό μ‚¬μš©ν•˜μ—¬ JWT 토큰에 νŠΉμ • κΆŒν•œ 집합을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έ ν›„ 이 토큰을 μ‚¬μš©μžμ—κ²Œ 직접 μ œκ³΅ν•˜κ±°λ‚˜ 제3μžμ—κ²Œ μ œκ³΅ν•˜μ—¬, νŠΉμ • μ œν•œμ‚¬ν•­ ν•˜μ—μžˆλŠ” API와 ν†΅μ‹ ν•˜λ„λ‘ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

**FastAPI** μ—μ„œμ˜ μ‚¬μš© 방법과 톡합 방식은 **심화 μ‚¬μš©μž μ•ˆλ‚΄μ„œ** μ—μ„œ μžμ„Ένžˆ 배울 수 μžˆμŠ΅λ‹ˆλ‹€.

## μš”μ•½

μ§€κΈˆκΉŒμ§€ μ‚΄νŽ΄λ³Έ λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ, OAuth2와 JWT 같은 ν‘œμ€€μ„ μ‚¬μš©ν•˜μ—¬ μ•ˆμ „ν•œ **FastAPI** μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

거의 λͺ¨λ“  ν”„λ ˆμž„μ›Œν¬μ—μ„œ λ³΄μ•ˆ μ²˜λ¦¬λŠ” μƒλ‹Ήνžˆ λ³΅μž‘ν•œ μ£Όμ œμž…λ‹ˆλ‹€.

이λ₯Ό λ‹¨μˆœν™”ν•˜λŠ” λ§Žμ€ νŒ¨ν‚€μ§€λŠ” 데이터 λͺ¨λΈ, λ°μ΄ν„°λ² μ΄μŠ€, μ‚¬μš© κ°€λŠ₯ν•œ κΈ°λŠ₯듀에 λŒ€ν•΄ μ—¬λŸ¬ μ œμ•½μ΄ μžˆμŠ΅λ‹ˆλ‹€. 그리고 μ§€λ‚˜μΉ˜κ²Œ λ‹¨μˆœν™”ν•˜λŠ” 일뢀 νŒ¨ν‚€μ§€λ“€μ€ μ‹¬κ°ν•œ λ³΄μ•ˆ 결함을 κ°€μ§ˆ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

---

**FastAPI** λŠ” μ–΄λ–€ λ°μ΄ν„°λ² μ΄μŠ€, 데이터 λͺ¨λΈ, 도ꡬ도 κ°•μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

ν”„λ‘œμ νŠΈμ— κ°€μž₯ μ ν•©ν•œ 것을 선택할 수 μžˆλŠ” μœ μ—°μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

그리고 `passlib` 와 `PyJWT` 처럼 잘 κ΄€λ¦¬λ˜κ³  널리 μ‚¬μš©λ˜λŠ” νŒ¨ν‚€μ§€λ“€μ„ λ°”λ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. **FastAPI** λŠ” μ™ΈλΆ€ νŒ¨ν‚€μ§€ 톡합을 μœ„ν•΄ λ³΅μž‘ν•œ λ©”μ»€λ‹ˆμ¦˜μ΄ ν•„μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ μœ μ—°μ„±, 견고성, λ³΄μ•ˆμ„±μ„ ν•΄μΉ˜μ§€ μ•ŠμœΌλ©΄μ„œ 과정을 λ‹¨μˆœν™”ν•  수 μžˆλŠ” 도ꡬ듀을 μ œκ³΅ν•©λ‹ˆλ‹€.

그리고 OAuth2와 같은 ν‘œμ€€ ν”„λ‘œν† μ½œμ„ 비ꡐ적 κ°„λ‹¨ν•œ λ°©λ²•μœΌλ‘œ κ΅¬ν˜„ν•˜κ³  μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

더 μ„ΈλΆ„ν™”λœ κΆŒν•œ 체계λ₯Ό μœ„ν•΄ OAuth2의 "μŠ€μ½”ν”„"λ₯Ό μ‚¬μš©ν•˜λŠ” 방법은 **심화 μ‚¬μš©μž μ•ˆλ‚΄μ„œ**μ—μ„œ 더 μžμ„Ένžˆ 배울 수 μžˆμŠ΅λ‹ˆλ‹€. OAuth2의 μŠ€μ½”ν”„λŠ” 제3자 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‚¬μš©μžλ₯Ό λŒ€μ‹ ν•΄ κ·Έλ“€μ˜ API와 μƒν˜Έμž‘μš©ν•˜λ„λ‘ κΆŒν•œμ„ λΆ€μ—¬ν•˜κΈ° μœ„ν•΄, Facebook, Google, GitHub, Microsoft, Twitter λ“±μ˜ λ§Žμ€ λŒ€ν˜• 인증 μ œκ³΅μ—…μ²΄λ“€μ΄ μ‚¬μš©ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μž…λ‹ˆλ‹€.