개발/파이썬
[TIL] JWT 토큰 쿠키에 저장하기 (Flask)
seonu._.jang
2019. 5. 5. 15:47
반응형
- JWT 토큰은 JS에서 접근할 수 있는
Localstorage
보다 JS에서 접근할 수 없는httponly cookie
에 저장하는 것이 XSS 공격에 안전하다. ( JS를 페이지에서 쓸 수 없게 escaping을 잘 해두면 LocalStorage에 저장하더라도 XSS 공격을 막을 수 있다. ) - 단, CSRF 공격에 취약하기 때문에, CSRF 토큰을 만들어서
double checking
을 통해 보안에 신경 쓸 필요가 있다. httponly cookie
는 프론트가 아닌 서버에서 Response해줄 때 붙여준다.- Flask 앱에 아래와 같은 옵션을 지정해주면
flask-jwt-extended
라이브러리를 통해 cookie에 jwt를 지정할 수 있다.
JWT_COOKIE_SECURE = False # https를 통해서만 cookie가 갈 수 있는지 (production 에선 True)
JWT_TOKEN_LOCATION = ['cookies']
JWT_ACCESS_COOKIE_PATH = '/' # access cookie를 보관할 url (Frontend 기준)
JWT_REFRESH_COOKIE_PATH = '/' # refresh cookie를 보관할 url (Frontend 기준)
# CSRF 토큰 역시 생성해서 쿠키에 저장할지
# (이 경우엔 프론트에서 접근해야하기 때문에 httponly가 아님)
JWT_COOKIE_CSRF_PROTECT = True
아래와 같이 flask-jwt-extended
라이브러리의 set_access_cookies
와 set_refresh_cookies
를 사용하면 쿠키를 브라우저에 저장할 수 있다.
@app.route('/token/auth', methods=['POST'])
def login():
username = request.json.get('username', None)
password = request.json.get('password', None)
if username != 'test' or password != 'test':
return jsonify({'login': False}), 401
# Create the tokens we will be sending back to the user
access_token = create_access_token(identity=username)
refresh_token = create_refresh_token(identity=username)
# Set the JWTs and the CSRF double submit protection cookies
# in this response
resp = jsonify({'login': True})
set_access_cookies(resp, access_token)
set_refresh_cookies(resp, refresh_token)
return resp, 200
- 그런데 아무리 해도 브라우저에 cookie가 저장되지 않았다.
- 해결책:
- 브라우저가 localhost로 되어있으면 cookie를 저장하지 않는거 같다. http://127.0.0.1로 접속하자.
axios
에withCredentials: true
라는 문구를 추가하자.
import axios from "axios";
export default axios.create({
baseURL: process.env.BASEURL,
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
withCredentials: true
});
Flask-Cors
에서supports_credentials=True
를 추가하자.
CORS(app, origins=ALLOW_ORIGINS, supports_credentials=True)
이렇게 하니 정상적으로 잘 저장됐다.
이제
localstorage
에서 token을 빼서Authorization
헤더를 보낼 필요가 없어졌다.단 csrf 보안을 설정해뒀으므로, 프론트에서 csrf-token을 빼서 보내주어야 백엔드에서 더블 체킹이 된다.
- 쿠키를 쓰려면 도메인이 같아야한다. (*.alphaquant.co.kr에서 *.abcdef.co.kr의 쿠키를 지정할 수 없다는 말)
반응형