๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

OAuth 2.0์˜ ํ•ต์‹ฌ ์š”์†Œ์™€ ํ† ํฐ ๊ด€๋ฆฌ: ํšจ์œจ์ ์ธ ์ธ์ฆ ์‹œ์Šคํ…œ ๊ตฌ์ถ•ํ•˜๊ธฐ

mrmount 2024. 10. 18.

 

 

 

OAuth 2.0์—์„œ์˜ ํ† ํฐ์˜ ์—ญํ• 

OAuth 2.0์—์„œ๋Š” Access Token ๊ณผ Refresh Token ์„ ์‚ฌ์šฉํ•ด ์ธ์ฆ๊ณผ ๊ถŒํ•œ ๋ถ€์—ฌ ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํ† ํฐ๋“ค์€ ์‚ฌ์šฉ์ž์˜ ์ž๊ฒฉ ์ฆ๋ช…์„ ๋Œ€์‹ ํ•˜์—ฌ API ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ ์„ ๋ถ€์—ฌํ•˜๋ฉฐ, ํ•„์š”์— ๋”ฐ๋ผ JWT(JSON Web Token) ํ˜•์‹์œผ๋กœ ๋ฐœ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

 


 

1. Access Token๊ณผ Refresh Token์˜ ์ฐจ์ด

ํ† ํฐ ์œ ํ˜• ์„ค๋ช… ์‚ฌ์šฉ ์˜ˆ์‹œ
Access Token API์— ๋Œ€ํ•œ ๋‹จ๊ธฐ ์ ‘๊ทผ ๊ถŒํ•œ ์„ ๋ถ€์—ฌ ์‚ฌ์šฉ์ž ์ •๋ณด API ํ˜ธ์ถœ
Refresh Token ๋งŒ๋ฃŒ๋œ Access Token์„ ๊ฐฑ์‹  ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ Access Token ๋งŒ๋ฃŒ ํ›„ ์ƒˆ ํ† ํฐ ๋ฐœ๊ธ‰



Access Token์˜ ํŠน์ง•

  • ์งง์€ ์œ ํšจ ๊ธฐ๊ฐ„ (์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ ๋ถ„~์ˆ˜ ์‹œ๊ฐ„) ๋™์•ˆ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.
  • API ํ˜ธ์ถœ ์‹œ ํ—ค๋”์— ํฌํ•จ ๋˜์–ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

์˜ˆ์‹œ: Access Token์„ ์‚ฌ์šฉํ•œ API ํ˜ธ์ถœ

import requests

access_token = "your_access_token"
url = "https://api.example.com/user"

headers = {
    "Authorization": f"Bearer {access_token}"
}

response = requests.get(url, headers=headers)
print(response.json())

 

 

OAuth 2.0์—์„œ์˜ ํ† ํฐ์˜ ์—ญํ• 

OAuth 2.0์—์„œ๋Š” Access Token ๊ณผ Refresh Token ์„ ์‚ฌ์šฉํ•ด ์ธ์ฆ๊ณผ ๊ถŒํ•œ ๋ถ€์—ฌ ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํ† ํฐ๋“ค์€ ์‚ฌ์šฉ์ž์˜ ์ž๊ฒฉ ์ฆ๋ช…์„ ๋Œ€์‹ ํ•˜์—ฌ API ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ ์„ ๋ถ€์—ฌํ•˜๋ฉฐ, ํ•„์š”์— ๋”ฐ๋ผ JWT(JSON Web Token) ํ˜•์‹์œผ๋กœ ๋ฐœ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

 


 

1. Access Token๊ณผ Refresh Token์˜ ์ฐจ์ด

ํ† ํฐ ์œ ํ˜• ์„ค๋ช… ์‚ฌ์šฉ ์˜ˆ์‹œ
Access Token API์— ๋Œ€ํ•œ ๋‹จ๊ธฐ ์ ‘๊ทผ ๊ถŒํ•œ ์„ ๋ถ€์—ฌ ์‚ฌ์šฉ์ž ์ •๋ณด API ํ˜ธ์ถœ
Refresh Token ๋งŒ๋ฃŒ๋œ Access Token์„ ๊ฐฑ์‹  ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ Access Token ๋งŒ๋ฃŒ ํ›„ ์ƒˆ ํ† ํฐ ๋ฐœ๊ธ‰



Access Token์˜ ํŠน์ง•

  • ์งง์€ ์œ ํšจ ๊ธฐ๊ฐ„ (์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ ๋ถ„~์ˆ˜ ์‹œ๊ฐ„) ๋™์•ˆ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.
  • API ํ˜ธ์ถœ ์‹œ ํ—ค๋”์— ํฌํ•จ ๋˜์–ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

์˜ˆ์‹œ: Access Token์„ ์‚ฌ์šฉํ•œ API ํ˜ธ์ถœ

import requests

access_token = "your_access_token"
url = "https://api.example.com/user"

headers = {
    "Authorization": f"Bearer {access_token}"
}

response = requests.get(url, headers=headers)
print(response.json())

์„ค๋ช…: Access Token์€ Authorization ํ—ค๋” ์— ํฌํ•จํ•ด API๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

Refresh Token์˜ ํŠน์ง•

  • ๋” ๊ธด ์œ ํšจ ๊ธฐ๊ฐ„ ์„ ๊ฐ€์ง€๋ฉฐ, Access Token ๋งŒ๋ฃŒ ์‹œ ์ƒˆ๋กœ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋…ธ์ถœ ์‹œ ์œ„ํ—˜ ์ด ์žˆ์œผ๋ฏ€๋กœ ๋ณด์•ˆ์ด ์ค‘์š”ํ•œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

์˜ˆ์‹œ: Refresh Token์œผ๋กœ ์ƒˆ Access Token ๋ฐœ๊ธ‰

response = requests.post(
    "https://api.example.com/oauth/token",
    data={
        "grant_type": "refresh_token",
        "refresh_token": "your_refresh_token",
        "client_id": "your_client_id",
        "client_secret": "your_client_secret",
    }
)

new_access_token = response.json().get("access_token")
print(f"New Access Token: {new_access_token}")

์„ค๋ช…: ๋งŒ๋ฃŒ๋œ Access Token์€ Refresh Token ์„ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


 

2. Token Scope์™€ Expiration: ๊ถŒํ•œ๊ณผ ์œ ํšจ ๊ธฐ๊ฐ„ ๊ด€๋ฆฌ

 

Token Scope(์Šค์ฝ”ํ”„)

Scope ๋Š” ํ† ํฐ์— ๋ถ€์—ฌ๋œ ๊ถŒํ•œ์˜ ๋ฒ”์œ„ ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ํŠน์ • ๋ฆฌ์†Œ์Šค์—๋งŒ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ์Šค์ฝ”ํ”„๋Š” ๊ฐœ๋ณ„์ ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

์Šค์ฝ”ํ”„ ์„ค๋ช…
read:user ์‚ฌ์šฉ์ž ์ •๋ณด ์ฝ๊ธฐ
write:post ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ ๊ถŒํ•œ ๋ถ€์—ฌ
read:email ์ด๋ฉ”์ผ ์ฃผ์†Œ ์ฝ๊ธฐ ๊ถŒํ•œ



์˜ˆ์‹œ: ์Šค์ฝ”ํ”„๊ฐ€ ํฌํ•จ๋œ ๊ถŒํ•œ ๋ถ€์—ฌ ์š”์ฒญ

https://accounts.example.com/oauth/authorize?response_type=code
&client_id=your_client_id
&redirect_uri=https://yourapp.com/callback
&scope=read:user write:post

Token Expiration(์œ ํšจ ๊ธฐ๊ฐ„)

  • Access Token์€ ์งง์€ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๊ฐ€์ง€๋ฉฐ, ๋ณด์•ˆ์„ ์œ„ํ•ด ์ž์ฃผ ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
  • Refresh Token์€ ๋” ๊ธด ์œ ํšจ ๊ธฐ๊ฐ„ ์„ ๊ฐ€์ง€์ง€๋งŒ, ๋ณด์•ˆ ์‚ฌ๊ณ  ์‹œ ๋…ธ์ถœ ์œ„ํ—˜์ด ํฝ๋‹ˆ๋‹ค.

 


 

3. JWT(JSON Web Token)์˜ ์‚ฌ์šฉ

JWT ๋Š” OAuth 2.0์—์„œ Access Token ์˜ ํ•œ ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. JWT๋Š” Base64๋กœ ์ธ์ฝ”๋”ฉ๋œ JSON ํ˜•์‹์˜ ํ† ํฐ ์œผ๋กœ, ์‰ฝ๊ฒŒ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค์–‘ํ•œ ์‹œ์Šคํ…œ์—์„œ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.

JWT์˜ ๊ตฌ์กฐ

JWT๋Š” ํ—ค๋”(Header), ํŽ˜์ด๋กœ๋“œ(Payload), ์„œ๋ช…(Signature) ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

header.payload.signature

 

์˜ˆ์‹œ: JWT ๋””์ฝ”๋”ฉ

import jwt

encoded_jwt = "your_jwt_token"
decoded = jwt.decode(encoded_jwt, options={"verify_signature": False})
print(decoded)

 

์˜ˆ์‹œ JWT Payload

{
    "sub": "1234567890",
    "name": "John Doe",
    "iat": 1516239022,
    "exp": 1516242622,
    "scope": "read:user"
}

์„ค๋ช…: JWT๋Š” ์œ ํšจ ๊ธฐ๊ฐ„๊ณผ ์Šค์ฝ”ํ”„ ์ •๋ณด๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์–ด ๊ฒ€์ฆ์ด ๊ฐ„ํŽธ ํ•ฉ๋‹ˆ๋‹ค.

 


 

4. ํ† ํฐ ๊ด€๋ฆฌ ์ „๋žต: ๋ณด์•ˆ๊ณผ ํšจ์œจ์„ฑ์˜ ๊ท ํ˜•

  1. ํ† ํฐ ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐฑ์‹ 
    Access Token์€ ์ž์ฃผ ๊ฐฑ์‹ ํ•ด ํƒˆ์ทจ ์œ„ํ—˜ ์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.
  2. Refresh Token ๋ณดํ˜ธ
    Refresh Token์€ ๋ฏผ๊ฐํ•œ ์ •๋ณด์ด๋ฏ€๋กœ HTTPS๋ฅผ ์‚ฌ์šฉ ํ•ด ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  3. ์Šค์ฝ”ํ”„ ์ตœ์†Œํ™”
    ํ•„์š”ํ•œ ๋ฒ”์œ„์˜ ๊ถŒํ•œ๋งŒ ๋ถ€์—ฌํ•˜๋Š” ์ตœ์†Œ ๊ถŒํ•œ ์›์น™ ์„ ์ค€์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.
  4. JWT ์‚ฌ์šฉ ์‹œ ์„œ๋ช… ๊ฒ€์ฆ
    JWT๋Š” ์„œ๋ช…(Signature) ์„ ํ†ตํ•ด ๋ฌด๊ฒฐ์„ฑ์„ ๊ฒ€์ฆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 


 

OAuth 2.0 ํ† ํฐ ๊ด€๋ฆฌ์™€ ์ตœ์‹  ํŠธ๋ Œ๋“œ

  • PKCE ์™€ ํ•จ๊ป˜ Access Token์„ ์‚ฌ์šฉํ•ด ๋ชจ๋ฐ”์ผ ์•ฑ์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • OAuth 2.1 ์—์„œ๋Š” ๋ณด์•ˆ์„ ์œ„ํ•ด ํ† ํฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๋”์šฑ ๋‹จ์ถ•ํ•˜๊ณ  ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
  • JWT๋Š” ์Šค์ผ€์ผ๋ง์— ์œ ๋ฆฌ ํ•˜๋ฉฐ, ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 


 

FAQ

Q1. Access Token๊ณผ Refresh Token์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?
A1. Access Token์€ ๋‹จ๊ธฐ์ ์ธ API ์ ‘๊ทผ ์— ์‚ฌ์šฉ๋˜๋ฉฐ, Refresh Token์€ ์ƒˆ๋กœ์šด Access Token ๋ฐœ๊ธ‰ ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Q2. JWT์™€ ์ผ๋ฐ˜ Access Token์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?
A2. JWT๋Š” Base64 ์ธ์ฝ”๋”ฉ๋œ JSON ํ˜•์‹ ์œผ๋กœ ์ž์ฒด์ ์œผ๋กœ ์„œ๋ช… ๋ฐ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Q3. Refresh Token์€ ํ•ญ์ƒ ๋ฐœ๊ธ‰ํ•ด์•ผ ํ•˜๋‚˜์š”?
A3. ๋ชจ๋“  ๊ฒฝ์šฐ์— ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ์žฅ๊ธฐ ์„ธ์…˜ ์„ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ Refresh Token ๋ฐœ๊ธ‰์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

Q4. JWT์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์€ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋‚˜์š”?
A4. JWT์˜ exp (expiration) ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

Q5. ํ† ํฐ ํƒˆ์ทจ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ๊ฐ€์š”?
A5. HTTPS ์‚ฌ์šฉ ๊ณผ ์ฃผ๊ธฐ์ ์ธ ํ† ํฐ ๊ฐฑ์‹  ์œผ๋กœ ํ† ํฐ ํƒˆ์ทจ ์œ„ํ—˜์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

 


๋Œ“๊ธ€