OAuth 1.0๊ณผ OAuth 2.0์ ๋น๊ต: ํ๋กํ ์ฝ ๋ณํ์ ๋ณด์์ฑ์ ์งํ
OAuth๋ ๋ฌด์์ธ๊ฐ?
OAuth๋ ์ฌ์ฉ์๊ฐ ์์ ์ ์๊ฒฉ ์ฆ๋ช ์ ๊ณต์ ํ์ง ์๊ณ ์ธ๋ถ ์ ํ๋ฆฌ์ผ์ด์ ์ด ํน์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋๋ก ๊ถํ์ ๋ถ์ฌํ๋ ํ๋กํ ์ฝ ์ ๋๋ค. OAuth๋ ์ฃผ๋ก ์์ ๋ก๊ทธ์ธ, API ํธ์ถ ๋ฑ์ ์ฌ์ฉ๋๋ฉฐ, OAuth 1.0 ๊ณผ OAuth 2.0 ์ ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ฅผ ์ํํฉ๋๋ค.
1. OAuth 1.0๊ณผ OAuth 2.0์ ์ฃผ์ ์ฐจ์ด์
ํญ๋ชฉ | OAuth 1.0 | OAuth 2.0 |
---|---|---|
์ถ์ ์ฐ๋ | 2007๋ | 2012๋ |
์๋ช ๋ฐฉ์ | ์์ฒญ๋ง๋ค HMAC ์๋ช ํ์ | Access Token ๊ธฐ๋ฐ ๊ฐํธํ ์ธ์ฆ |
๋ณด์ ๋ฐฉ์ | ์์ฒญ๋ง๋ค ๋ณต์กํ ์๋ช ๊ฒ์ฆ | HTTPS ๋ก ์ ์ก๋ Access Token ๋ณดํธ |
์ฌ์ฉ ํธ์์ฑ | ๊ตฌํ์ด ๋ณต์กํ๊ณ ์ค์ ์ด ์ด๋ ค์ | ๋ ๊ฐ๋จํ ๊ตฌ์กฐ์ ๋ค์ํ ์ธ์ฆ ๋ฐฉ์ ์ง์ |
PKCE ์ง์ | ์ง์๋์ง ์์ | OAuth 2.1 ๋ถํฐ PKCE ํ์ํ |
ํด๋ผ์ด์ธํธ ์ ํ | ์ฃผ๋ก ์๋ฒ-์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ | ์น, ๋ชจ๋ฐ์ผ ๋ฑ ๋ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ง์ |
OAuth 2.0์ ๋ณด์์ฑ ํฅ์๊ณผ ๋๋ถ์ด ์ฌ์ฉ ํธ์์ฑ ์ ์ ๊ณตํ์ฌ ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ํด๋ผ์ฐ๋ ์๋น์ค ๋ฑ ๋ค์ํ ํ๊ฒฝ์์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
2. ๋ณด์์ฑ ๋ฐ ์ฌ์ฉ ํธ์์ฑ ๋น๊ต
OAuth 1.0์ ๋ณด์์ฑ๊ณผ ํ๊ณ
- HMAC ์๋ช ๋ฐฉ์ ์ ์ฌ์ฉํ์ฌ ๋งค ์์ฒญ๋ง๋ค ์๋ช ์ ์์ฑํด์ผ ํ์ต๋๋ค.
- API ์์ฒญ๋ง๋ค ์๋ช ์ ๊ฒ์ฆํ๋ ๊ณผ์ ์ด ๋ณต์กํ์ต๋๋ค.
- HTTPS ์ฌ์ฉ์ด ๊ถ์ฅ๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ค๊ฐ์ ๊ณต๊ฒฉ(MITM) ์ ์ทจ์ฝํ์ต๋๋ค.
OAuth 2.0์ ๋ณด์์ฑ๊ณผ ๊ฐ์ ์
- Access Token ์ผ๋ก ๊ฐํธํ๊ฒ ์ธ์ฆ์ ์ํํฉ๋๋ค.
- HTTPS๋ฅผ ์ฌ์ฉํด ํ ํฐ์ ๊ธฐ๋ฐ์ฑ ์ ๋ณด์ฅํฉ๋๋ค.
- Refresh Token ์ ํตํด Access Token์ ๊ฐฑ์ ํ ์ ์์ด ๋ณด์์ ๊ฐํํ์ต๋๋ค.
- PKCE(Proof Key for Code Exchange) ๋ฅผ ๋์ ํด ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ๊ฐ์ ํด๋ผ์ด์ธํธ์ ๋ณด์์ ๊ฐ์ ํ์ต๋๋ค.
3. OAuth 2.1 ๊ฐ์: ์ต์ ํ์ค์ผ๋ก์ ์งํ
OAuth 2.1 ์ OAuth 2.0์ ๊ฐ์ ๋ ๋ฒ์ ์ผ๋ก, ๋ณด์์ฑ๊ณผ ์ฌ์ฉ์ฑ์ ๋ ๊ฐํํ์ต๋๋ค. ๋ค์์ OAuth 2.1์ ์ฃผ์ ํน์ง์ ๋๋ค.
- PKCE ํ์ํ : ๋ชจ๋ ํด๋ผ์ด์ธํธ์ PKCE ์ฌ์ฉ์ด ๊ถ์ฅ๋ฉ๋๋ค.
- Implicit Grant ์ ๊ฑฐ : ๋ณด์ ๋ฌธ์ ๋ก ์ธํด Implicit Grant ๋ฐฉ์์ ์ ๊ฑฐํ์ต๋๋ค.
- ๋ ๊ฐํธํ ํด๋ผ์ด์ธํธ ๊ตฌํ : ์ค์ ๋ณต์ก์ฑ์ ์ค์ด๊ณ ๋ณด์ ๊ฐํ๋ฅผ ์ํด ์ผ๋ถ ๊ธฐ๋ฅ์ ํตํฉํ์ต๋๋ค.
4. OAuth 2.0์ ์ฌ์ฉ ์์ : ํ์ด์ฌ์ผ๋ก ๊ตฌํํ๊ธฐ
์๋๋ Flask์ Requests ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฅผ ์ฌ์ฉํ OAuth 2.0 ๊ตฌํ ์์ ์ ๋๋ค.
from flask import Flask, redirect, request, session, url_for
import requests
app = Flask(__name__)
app.secret_key = 'your_secret_key'
CLIENT_ID = 'your_client_id'
CLIENT_SECRET = 'your_client_secret'
REDIRECT_URI = 'http://localhost:5000/callback'
AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/auth'
TOKEN_URL = 'https://accounts.google.com/o/oauth2/token'
@app.route('/')
def home():
return '<a href="/login">๊ตฌ๊ธ ๋ก๊ทธ์ธ</a>'
@app.route('/login')
def login():
auth_url = f"{AUTHORIZATION_URL}?response_type=code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope=email"
return redirect(auth_url)
@app.route('/callback')
def callback():
code = request.args.get('code')
token_response = requests.post(TOKEN_URL, data={
'code': code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'
}).json()
session['access_token'] = token_response['access_token']
return '๋ก๊ทธ์ธ ์ฑ๊ณต!'
if __name__ == '__main__':
app.run(debug=True)
OAuth๋ ๋ฌด์์ธ๊ฐ?
OAuth๋ ์ฌ์ฉ์๊ฐ ์์ ์ ์๊ฒฉ ์ฆ๋ช ์ ๊ณต์ ํ์ง ์๊ณ ์ธ๋ถ ์ ํ๋ฆฌ์ผ์ด์ ์ด ํน์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋๋ก ๊ถํ์ ๋ถ์ฌํ๋ ํ๋กํ ์ฝ ์ ๋๋ค. OAuth๋ ์ฃผ๋ก ์์ ๋ก๊ทธ์ธ, API ํธ์ถ ๋ฑ์ ์ฌ์ฉ๋๋ฉฐ, OAuth 1.0 ๊ณผ OAuth 2.0 ์ ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ฅผ ์ํํฉ๋๋ค.
1. OAuth 1.0๊ณผ OAuth 2.0์ ์ฃผ์ ์ฐจ์ด์
ํญ๋ชฉ | OAuth 1.0 | OAuth 2.0 |
---|---|---|
์ถ์ ์ฐ๋ | 2007๋ | 2012๋ |
์๋ช ๋ฐฉ์ | ์์ฒญ๋ง๋ค HMAC ์๋ช ํ์ | Access Token ๊ธฐ๋ฐ ๊ฐํธํ ์ธ์ฆ |
๋ณด์ ๋ฐฉ์ | ์์ฒญ๋ง๋ค ๋ณต์กํ ์๋ช ๊ฒ์ฆ | HTTPS ๋ก ์ ์ก๋ Access Token ๋ณดํธ |
์ฌ์ฉ ํธ์์ฑ | ๊ตฌํ์ด ๋ณต์กํ๊ณ ์ค์ ์ด ์ด๋ ค์ | ๋ ๊ฐ๋จํ ๊ตฌ์กฐ์ ๋ค์ํ ์ธ์ฆ ๋ฐฉ์ ์ง์ |
PKCE ์ง์ | ์ง์๋์ง ์์ | OAuth 2.1 ๋ถํฐ PKCE ํ์ํ |
ํด๋ผ์ด์ธํธ ์ ํ | ์ฃผ๋ก ์๋ฒ-์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ | ์น, ๋ชจ๋ฐ์ผ ๋ฑ ๋ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ง์ |
OAuth 2.0์ ๋ณด์์ฑ ํฅ์๊ณผ ๋๋ถ์ด ์ฌ์ฉ ํธ์์ฑ ์ ์ ๊ณตํ์ฌ ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ํด๋ผ์ฐ๋ ์๋น์ค ๋ฑ ๋ค์ํ ํ๊ฒฝ์์ ๋๋ฆฌ ์ฌ์ฉ๋ฉ๋๋ค.
2. ๋ณด์์ฑ ๋ฐ ์ฌ์ฉ ํธ์์ฑ ๋น๊ต
OAuth 1.0์ ๋ณด์์ฑ๊ณผ ํ๊ณ
- HMAC ์๋ช ๋ฐฉ์ ์ ์ฌ์ฉํ์ฌ ๋งค ์์ฒญ๋ง๋ค ์๋ช ์ ์์ฑํด์ผ ํ์ต๋๋ค.
- API ์์ฒญ๋ง๋ค ์๋ช ์ ๊ฒ์ฆํ๋ ๊ณผ์ ์ด ๋ณต์กํ์ต๋๋ค.
- HTTPS ์ฌ์ฉ์ด ๊ถ์ฅ๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ค๊ฐ์ ๊ณต๊ฒฉ(MITM) ์ ์ทจ์ฝํ์ต๋๋ค.
OAuth 2.0์ ๋ณด์์ฑ๊ณผ ๊ฐ์ ์
- Access Token ์ผ๋ก ๊ฐํธํ๊ฒ ์ธ์ฆ์ ์ํํฉ๋๋ค.
- HTTPS๋ฅผ ์ฌ์ฉํด ํ ํฐ์ ๊ธฐ๋ฐ์ฑ ์ ๋ณด์ฅํฉ๋๋ค.
- Refresh Token ์ ํตํด Access Token์ ๊ฐฑ์ ํ ์ ์์ด ๋ณด์์ ๊ฐํํ์ต๋๋ค.
- PKCE(Proof Key for Code Exchange) ๋ฅผ ๋์ ํด ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ๊ฐ์ ํด๋ผ์ด์ธํธ์ ๋ณด์์ ๊ฐ์ ํ์ต๋๋ค.
3. OAuth 2.1 ๊ฐ์: ์ต์ ํ์ค์ผ๋ก์ ์งํ
OAuth 2.1 ์ OAuth 2.0์ ๊ฐ์ ๋ ๋ฒ์ ์ผ๋ก, ๋ณด์์ฑ๊ณผ ์ฌ์ฉ์ฑ์ ๋ ๊ฐํํ์ต๋๋ค. ๋ค์์ OAuth 2.1์ ์ฃผ์ ํน์ง์ ๋๋ค.
- PKCE ํ์ํ : ๋ชจ๋ ํด๋ผ์ด์ธํธ์ PKCE ์ฌ์ฉ์ด ๊ถ์ฅ๋ฉ๋๋ค.
- Implicit Grant ์ ๊ฑฐ : ๋ณด์ ๋ฌธ์ ๋ก ์ธํด Implicit Grant ๋ฐฉ์์ ์ ๊ฑฐํ์ต๋๋ค.
- ๋ ๊ฐํธํ ํด๋ผ์ด์ธํธ ๊ตฌํ : ์ค์ ๋ณต์ก์ฑ์ ์ค์ด๊ณ ๋ณด์ ๊ฐํ๋ฅผ ์ํด ์ผ๋ถ ๊ธฐ๋ฅ์ ํตํฉํ์ต๋๋ค.
4. OAuth 2.0์ ์ฌ์ฉ ์์ : ํ์ด์ฌ์ผ๋ก ๊ตฌํํ๊ธฐ
์๋๋ Flask์ Requests ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฅผ ์ฌ์ฉํ OAuth 2.0 ๊ตฌํ ์์ ์ ๋๋ค.
from flask import Flask, redirect, request, session, url_for
import requests
app = Flask(__name__)
app.secret_key = 'your_secret_key'
CLIENT_ID = 'your_client_id'
CLIENT_SECRET = 'your_client_secret'
REDIRECT_URI = 'http://localhost:5000/callback'
AUTHORIZATION_URL = 'https://accounts.google.com/o/oauth2/auth'
TOKEN_URL = 'https://accounts.google.com/o/oauth2/token'
@app.route('/')
def home():
return '<a href="/login">๊ตฌ๊ธ ๋ก๊ทธ์ธ</a>'
@app.route('/login')
def login():
auth_url = f"{AUTHORIZATION_URL}?response_type=code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope=email"
return redirect(auth_url)
@app.route('/callback')
def callback():
code = request.args.get('code')
token_response = requests.post(TOKEN_URL, data={
'code': code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'
}).json()
session['access_token'] = token_response['access_token']
return '๋ก๊ทธ์ธ ์ฑ๊ณต!'
if __name__ == '__main__':
app.run(debug=True)
์ฝ๋ ์ค๋ช :
- ๊ตฌ๊ธ ๋ก๊ทธ์ธ URL๋ก ๋ฆฌ๋๋ ์ : ์ฌ์ฉ์๊ฐ ๊ถํ์ ์น์ธํ๋ฉด ์ฝ๋ฐฑ URL๋ก ์ด๋ํฉ๋๋ค.
- Access Token ๋ฐ๊ธ : ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ธ์ฆ ์ฝ๋๋ฅผ ์ฌ์ฉํด Access Token ์ ๋ฐ๊ธ๋ฐ์ต๋๋ค.
- API ํธ์ถ์ Access Token ์ฌ์ฉ : ๋ก๊ทธ์ธ ์ฑ๊ณต ํ, ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ๊ธ API๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
5. OAuth์ ๊ด๋ จ๋ ์ต์ ํธ๋ ๋
- OAuth 2.1 ์ฑํ์ด ์ ์ ํ์ฐ๋๋ฉฐ, ๋ณด์์ด ์ค์ํ ์๋น์ค์์ PKCE ์ฌ์ฉ์ด ์ฆ๊ฐํ๊ณ ์์ต๋๋ค.
- ์์ ๋ก๊ทธ์ธ๊ณผ API ์ธ์ฆ์์ OAuth ํ์ค ์ด ๋ ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
- ํด๋ผ์ฐ๋ ์๋น์ค ์ ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ์์ OAuth๊ฐ ๊ธฐ๋ณธ ์ธ์ฆ ๋ฐฉ์์ผ๋ก ์๋ฆฌ ์ก๊ณ ์์ต๋๋ค.
FAQ
Q1. OAuth 1.0๊ณผ OAuth 2.0์ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
A1. OAuth 1.0์ ์์ฒญ๋ง๋ค HMAC ์๋ช
์ ์ฌ์ฉํ ๋ฐ๋ฉด, OAuth 2.0์ Access Token ์ผ๋ก ๊ฐํธํ๊ฒ ์ธ์ฆํฉ๋๋ค.
Q2. OAuth 2.1์ ์ฃผ์ ๊ฐ์ ์ฌํญ์ ๋ฌด์์ธ๊ฐ์?
A2. PKCE ํ์ํ ์ Implicit Grant ์ ๊ฑฐ ๊ฐ ์ฃผ์ ๊ฐ์ ์ฌํญ์
๋๋ค.
Q3. OAuth์์ Refresh Token์ ์ธ์ ์ฌ์ฉํ๋์?
A3. Access Token์ด ๋ง๋ฃ๋ ํ ์๋ก์ด Access Token ์ ๋ฐ๊ธ๋ฐ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
Q4. ๋ชจ๋ฐ์ผ ์ฑ์์๋ OAuth 2.0์ ์ด๋ป๊ฒ ๊ตฌํํ๋์?
A4. ๋ชจ๋ฐ์ผ ์ฑ์์๋ PKCE ๋ฅผ ์ฌ์ฉํด ๋ณด์์ ๊ฐํํ OAuth 2.0์ ๊ตฌํํฉ๋๋ค.
Q5. OAuth๋ ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ๋์?
A5. OAuth๋ ์ธ๊ฐ(Authorization) ์ ์ค์ ์ ๋๋ฉฐ, ์ธ์ฆ(Authentication)์ OpenID Connect๊ฐ ๋ด๋นํฉ๋๋ค.
'IT' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
OAuth 2.0์ ๊ถํ ๋ถ์ฌ ๋ฐฉ์(Grant Types): ์ํฉ์ ๋ง๋ ์ธ์ฆ ๋ฐฉ๋ฒ ์ ํํ๊ธฐ (0) | 2024.10.18 |
---|---|
OAuth 2.0๊ณผ OAuth 2.1์ ๋์ ์ฌ๋ก (0) | 2024.10.18 |
OAuth์ ์ฅ์ ๊ณผ ํ๊ณ (0) | 2024.10.18 |
OAuth์ ๊ฐ๋ ๊ณผ ํ์์ฑ: ์์ ํ ์ธ์ฆ๊ณผ ๊ถํ ๋ถ์ฌ์ ํต์ฌ ์ดํดํ๊ธฐ (0) | 2024.10.18 |
HTTPS ๋์ ํ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ (0) | 2024.10.18 |
๋๊ธ