로그인 상태를 유지하기 위해서 jwt의 만료에 따라 refresh token을 해주어야 한다는 것을 알게 되었다.
passport google strategy를 보니 access token 과 refresh token을 전혀 사용안했었는데 있었던 이유를 알게 되었다.
그래서 자세히 정리해보려 한다.
- request는 stateless이기 때문에 서버는 누가 요청을 보내는지 모르기 때문에 세션DB에 user_id가 저장되어 있는 세션ID가 담긴 쿠키를 클라이언트에게 발급한다.
- 서버는 쿠키가 들어오는 것을 확인해 세션ID를 deserialize 후 서버는 user_id가 무엇인지 알아낸다.
- 서버는 user_id를 가지고 요청을 처리후 응답을 한다.
- 쿠키는 그저 세션 ID를 전달하기 위한 수단(매개체)일 뿐이다.
- 쿠키는 브라우저에만 있는 기능이다. 그래서 네이티브 앱에서는 불가능!
- 모든 요청이 올 때마다 세션id를 통해 deserialize한 user_id를 verify 하려면 항상 DB조회를 해야한다
-> DB 사용이 과도해진다
-> JWT 를 사용하면 세션 DB가 필요없다. 서버의 일이 줄어든다.
JWT (Jsonwebtoken)
- 토큰의 의미 = 신분증처럼 클라이언트가 서버에게 보여주는 것을 의미
- JWT의 의미 = 정보를 가지고 있는 토큰 ( 형태: header.payload.signature )
- 토큰이 만료될 때까지 서버가 클라이언트를 강제할 수 있는 방법은 없다.
- 서버는 토큰 쿠키에 저장을 했을 때 토큰을 refresh 해서 재발급해주거나, 삭제만 가능하다.
- 토큰을 localStorage에 저장을 한다면 안드로이드, ios에서도 사용 가능하다.
- DB 리소스를 줄일 수 있다.
- QR코드로 인코딩이 가능해 사용방법이 다양하다.
- 보안 문제가 생긴다면 모든 JWT의 SECRET_KEY를 바꾸면 된다.
- Signature와 Payload에는 HMACSHA256 algorithm 사용 / header에는 Base64URL 사용으로 암호화 되지 않았다.
- JWT를 암호화하고 싶다면 JSON Web Encryption (JWE)를 고려해보자.
- Header 에서 signning 알고리즘 종류를 선택할 수 있다. ( 지원하는 라이브러리일 경우 )
- 쿠키에 저장하면 XSRF( Cross-Site Request Forgery ) 공격이 문제가 될 수 있다.
-> localStorage에 저장해야한다.
-> localStorage에 저장하면 XSS 공격에 안전하다. 왜냐하면 sanitizing 해주는 프레임워크들이 많기 때문이다. - 보안을 높이려면 만료시간을 짧게 잡고, 토큰 재발급을 자주 해준다.
oauth 2.0 생활코딩 정리
- accessToken를 서버가 획득
- Resource Owner - Client - Resource Server (API, Identity Provider[idp])
(예를들어 구글이 두 개의 레이어를 가지고 있지만 Resource Server 한 개로 생략한 상태로 설명함) - 권한을 부여하는 과정에서 인증이 끝나면 redirect_uri를 cilent에게 준다. 준다. callback
- scope의 경우 resouce server에서 필요한 기능을 정해주는 역할을 한다.
- 서버가 client_id 와 client_scret을 Resource Server에게 주어야 한다.
- Resource Owner는 로그인 요청을 보내 인증이 성공하면 Resource Server가 authorization code를 Resource Owner에게 응답해주면서 임시적으로 authorization code를 들고 있는다.
- 다시 Resource Owner가 authorization code를 Client가 받아 client_id와 client_scret을 함께 Resource Server에게 보낸다.
- 3 가지를 다 받은 Resource Server는 authorization code를 확인 후 지우고, 새로 accessToken과 refreshToken을 client 에게 발급한다. (이 때 scope에 따라서 어떤 자원을 읽도록 허용할 지 정해준다.)
- accessToken은 수명이 있다. (accessToken을 쉽게 발급할 수 있도록 refreshToken을 사용한다.)
nodejs의 passport에서 accessToken과 refreshToken을 사용하는 방법은 찾아보지만 아직 좋은 글을 발견하지 못했다..
OpenID Connect
- OIDC 라고도 부른다.
- 사용자 인증에 사용되는 개방형 표준이다.
- OAuth 2.0 기술을 이용하여 만들어진 인증 레이어이다.
- OpenID Connect는 OAuth 2.0 기능을 확장한다.
- 키 대신해 클라이언트(애플리케이션)에게 내가 누구인지 기본 정보를 제공해주는 특정 권한을 가지는 뱃지를 준다.
- ATM 기기가 비슷한 체계를 가지고 있다. 카드에 정보가 담겨 있다.
- Oauth 프레임워크 위에서 작동한다. (Oauth가 없이는 작동하지 않는다.)
- ID token을 발급해서 Resource Server와 Client 둘다 가지고 있는다. (ID token과 accessToken은 매우 다르다.
- JWT로 이루져서 Client가 디코딩해서 JWT 안의 정보를 알 수 있다.
- OAuth 2.0를 사용할 때 Bearer 토큰을 사용하지만 OpenID Connect의 경우 ID 토큰을 쓸 수 있다.
- ID Token(JWT) 안에는 인증 이벤트와 사용자에 대한 청구가 포함된다.
- accesstoken을 발급해주는 방식과 다르게 ID token을 발급하면 발급하는 횟수를 줄여줄 수 있다.
- SAML 2.0 : 2001년 OASIS에서 정의한 개방형 Authentication(인증) 및 Authorization(인가) 표준이며, 엔터프라이즈 애플리케이션의 SSO(Single Sign On)를 목적으로 XML(Extensible Markup Language) 형식으로 개발
- OAuth 2.0 : 2006년 Twitter와 Google이 정의한 개방형 Authorization 표준이며, API 허가를 목적으로 JSON(Javascript Object Notation) 형식으로 개발
- OIDC 2.0 : 2014년 OpenID Foundation에서 정의한 개방형 Authentication 표준이며, 컨슈머 어플리케이션의 SSO를 목적으로 JSON 형식으로 개발
https://www.samsungsds.com/kr/insights/oidc.html
https://www.youtube.com/watch?v=hm2r6LtUbk8&list=PLXB5p_g4hZpMgHGZ4iMefHl_6D51sEhaT
댓글