만약 내가 JWT를 이용해서 로그인에 대한 관리를 하겠다. 라고 한다면, 그 JWT를 이용해서 어떠한 흐름으로 내가 관리를 할 것인지 미리 생각을 해두고 작업을 시작해야하는데....
일단은 그래 JWT 를 이용한 로그인에 대해서 이론적으로 공부를 한다. 하지만? 그 공부가 완벽하지 않은거다.
나는 내가 어느정도 안다고 생각하고 코드적인 부분으로 넘어가는 경향이 있는데, 내가 아는게 아는게 아니다!
그러면, 어떻게 내가 이걸 극복할 수 있을까? 라고 생각해보면 답은
이해한 큰 흐름의 sequence diagram 을 그려보고, 물어보는 것 이다.
물어보는 것에 대해 두려워하면 안된다!!!
결국, 신입에게 회사란 키워주는 입장이다 안타깝게도. 그러다보니, 신입은 최대한 빨리 클 수 있게 나보다 경력이 많은 사람들의 도움을 많이 받아야한다는거다! 괴롭히면서라도 빨리 성장한다면, 그게 회사가 신입에게 투자한 값어치를 뽑아낼 수 있는 방법 중 하나라고 생각이 든다. 그래서 최대한 빨리 물어봐서 빨리 습득해서 실전에 내가 쓰일 수 있는 경우의 수가 많아질 수 있도록 노력해야한다.
망한 로그인 sequence diagram....
여기서의 오류는, 3. HttpServletRequest 에 JWT가 존재하는지를 체크한다. 부분이다.왜 HttpServletRequest 에 JWT가 존재하는지를 체크하냐는 질문에 나는 말문이 또 콱 막혀버렷다....ㅠㅠ 대답을 할 수 없었다는 말은 결국엔 JWT에 대한 공부가 정말로 내것이 되지않아서 라는 말밖에는 설명이 되지 않는다. 나는 localStorage에 저장하기로 했으니, JWT가 존재한다는건 localStorage에 저장이 되어있는지만 확인하면 되는것이라고 했다.
어떠한 웹사이트를 사용할 때, 계정을 생성하고, 어떠한 특정한 기능을 사용하기위해 로그인하여 접근해야한다. 그러한 action 을 우리는 Authentication 이라고 부른다.
2. Session 기반의 Authentication
그렇다면, 어떻게 계정을 인증(authenticate) 할까?
우선, 과거에 가장 많이 사용한 심플한 방법인 Session-based Authentication 을 살펴보자!!https://www.bezkoder.com/jwt-json-web-token/
위의 사진을 보면서 설명해보자.
1. 사용자가 website에 로그인 2. Server는 그 사용자에 대한 Session을 생성하여 저장 (in Memory or Database) 3. Server는 브라우저 Cookie 에 저장할 그 Client의 SessionId를 return Server에 있는 그 Session은 만료시간을 가지고 있음. 그 일정 시간이 지난 후, 그 Session은 만료되고 다른 Session을 생성하여 다시 로그인을 해야함 4. 로그인이 된 사Cookie 와 SessionId 의 HTTP Request는 Server로 감 5. Server는 인증을 위해 이 SessionId 와 저장된 Session을 비교한 후에 6. 적절한 Response를 return 함
3. Token-based Authentication이 탄생한 이유?
그런데, 우리는 왜 Token-based Authentication 을 많이 사용하는 걸까?
이유는, 우리는 website만 가지고 있는 것이 아니고, 많은 플랫폼들이 존재하기 때문이다!
가정해보자, 우리가 사용하는 website가 Session으로 잘 작동한다고 하자. 어느날, 우리가 Mobile (Navtive Apps) 에 시스템을 구축해야하고 같은 Database를 최신 Web app에 사용해야한다면 우리는 어떻게 해야할까?
우리는 Native App의 사용자를 Session을 기반으로 하는 Authentication로 인증할 수 없다. 왜냐면, Native App 과 비슷한 아이들은 Cookie가 없기 때문이다!!!!
그러면, 우리는 Native App 을 위한 Backend 프로젝트를 다시 빌드 하거나, Native App을 위한 Authentication module 을 새로 구축해야한다. 그래서 탄생 한 것이 Token-based Authentication!!!
이 방법으로, 사용자의 login 상태가 Server에 의해 JWT(JSON Web Token) 으로 encoding 되어져서 Client로 보내질 수 있다. 그래서 요즘 RESTful API들은 이것을 많이 사용한다. 그러니 이제 JWT 의 원리에 대해서 알아보자!!!
4. Token-based Authentication의 원리
아래의 사진과 같이 이해하기 간단하다.
JWT의 작동
Session을 생성하는 것 대신에, Server는 로그인한 사용자의 data로부터 JWT를 생성하고 Client 로 보낸다. 그 Client 는 생성된 JWT를 이제부터 저장하고 되고, 그 Client로 부터 오는 모든 Request는 모두 JWT를 (보통은 header에) 붙여서 온다. 그러면 Server는 JWT를 인증하고 Response를 return 해준다. https://www.bezkoder.com/jwt-json-web-token/Client side에 JWT를 저장하는 방법은, 어떤 플랫폼을 사용하느냐에 따라 다른다.
Browser : Local Storage IOS : Keychain Android : SharedPreferences
JWT의 생성 방법
JWT 의 중요한 3가지
Header Payload Signature
Header
Header는 질문에 대답한다.
우리가 어떻게 JWT를 계산할까?
이제, header의 예제를 살펴보자. JSON 객체는 이렇게 생겼다:
{ "typ" : "JWT", "alg": "HS256" }
typ -'type', Token의 종류를 나타낸다. 여기서는 of course JWT alg - 'algorithm', Token signature 를 생성하기 위한 hash 알고리즘. 알고리즘은 Secret Key를 사용 여기서는, HMAC-SHA256 을 말한다.
Payload
Payload는 우리가 대답할 수 있게 도와준다.
우리는 JWT에 무엇을 저장하고 싶지?
이제, payload는 이렇게 생겼다.
{
"userId": "abcd1234",
"username": "minah",
"email": "contact@minah.com",
// standard fields
"iss": "park, author of minah.com",
"iat": 4568874212,
"exp": 4568874212
}
3가지의 저장하는 사용자 항목들 : userId , username, email Standard Fields (선택): iss (Issuer) - JWT 발행한사람 iat (Issued at) - JWT가 발행된 시간 exp (Expiration Time) - JWT의 만료 시간
단지, JWT를 생성하는 과정이 데이터를 encode하고 hash 할 뿐 암호화 하지 않는다. 그래서, JWT를 Main-in-the-middle attack으로 훔칠 수도있다. 그렇기 때문에 application 은 HTTPS encryption (암호화) 를 가지고 있어야한다.
6. Server가 Client 로 부터 JWT를 확인하는 방법
앞전에, Signature를 생성하는데 Secret 문자를 사용했다. 그 Secret 문자는 모든 application마다 유니크하고 안전한 server side에 보관되어 있어야한다.
Client로 부터 JWT를 받았을 때, Server는 Signature를 받아 그 Signature가 같은 알고리즘과 Secret문자로 hash 되었는지 확인한다.
중요!! Server로 Payload를 보낼 때, Payload정보는 숙력된 프로그래머들에 의해서 편집이나 추가가 될 수 있다.
그러면 어째야하냐구?
Token 을 Client로 보내기전에 저장해야한다. 그럼으로써, 나중에 Client로 부터 보내진 JWT가 valid 하다는걸 보장할 수 있다.
또한, 사용자의 Token을 Server에 저장하는 것 또한 시스템으로부터 Force Logout 기능도 도울 것이다.
참고 사이트를 내 나름대로 번역해서 적은 것이기 때문에, 영어에 능한 사람은 맨위에 있는 참고사이트를 보는 것을 더욱 추천한다! 역시 영어가 더욱 직설적이고 심플하게 표현되다보니 이해하는게 더 쉽다.