Authentication Strategies

YONGSU JEONG
8 min readSep 17, 2020

Authentication Strategies and Options Part-1

  1. User Auth with Microservices is an unsolved problem.
  • 완벽한 해결책은 없다. 상황에 적절하게 적용해야 한다.
  1. There are many ways to do it, and no one way is “right”
  2. I am going to outline a couple of solutions then propose a solution that works, but still has downsides.

고객이 예매권을 구입할 수 있는 Orders Service가 존재한다고 생각해보자.

Workflow:

  1. Order Service로 예매권 구매 요청이 다음과 같이 들어온다.
{ 영화제목: '00000'}
JWT, Cookie, ETC

2. Order Service는 정의된 로직에 따라 이 요청을 처리한다.

1. JWT, Cookie, ETC를 통해 로그인 여부를 확인.
True or False
True --> 티켓 구매 단계 진행
False --> 로그인 해주세요 alert 출력

Fundamental Option #1

Orders와 같은 ServiceAuth Service에 의존하는 형태로 동작하게 만든다.

  1. Orders Service로 예매권 구매 요청이 다음과 같이 들어온다.
{ 영화제목: '00000'}
JWT, Cookie, ETC

2. Orders Service JWT, Cookie, ETC 중 사용되는 것을 Auth Service에 검증을 목적으로 다시 요청의 형태로 전송한다.

3. Auth Service는 내부 로직으로 요청으로 받은 JWT, Cookie, ETC를 처리하고 응답을 Orders Service에 보낸다.

이 방식으로 서비스가 동작하면 어떤 문제가 발생할까?

위 사진을 보면 갑자기 Auth Service에 문제가 생겨 동작하지 않거나 혹은 아예 Auth Service가 정의되지 않은 상태를 생각해보자. 예매권을 구매하려는 고객이 로그인하고 서비스에 명시된 방식으로 예매권 구입 요청을 했음에도 불구하고 예매권을 구매할 수 없게 되는 문제가 발생한다.

이번에는 Fundamental Options #1을 조금 개선한 Fundamental Options #1.1에 대해서 알아보자

Fundamental Option #1.1Auth Service를 모든 서비스가 동작하기 위한, 더 쉽게 말하면 모든 서비스에 요청을 보내기 위해 반드시 거쳐야 하는 길목의 문과 같은 역할을 하도록 구현했다고 생각해보자.

이 방식의 또한 모든 Service100% Auth Service에 의존하고 있기 때문에 Fundamental Option #1과 동일한 문제를 가지고있다. 그렇다면 어떤 방법을 사용해야할까? 아무리 생각해도 어떤 방식을 사용해도 문제가 결코 생기지 않는 방법은 없는 것 같다.

생각을 전환해서 적어도 모든 ServiceAuth Service에 의존하지 않고 스스로 고객의 타당성 여부를 인증할 수 있다면 비록 한 서비스에 문제가 생기더라도 다른 서비스는 잘 돌아갈 수 있지 않을까?

Fundamental Option #2는 이 생각과 유사한 방식으로 동작한다.

Fundamental Option #2

Fundamental Option #2 에서는 모든 서비스가 고객의 타당성을 확인할 수 있는 로직을 내부에 가지고 있다.

Outside Dependencies가 없다는게 가장 큰 장점이다.

Fundamental Option #1 vs Fundamental Option #2

Fundamental Option #1pros: Changes to auth state are immediately reflected
cons: Auth service goes down? Entire app is broken
--------------------------------------------------------------------Fundamental Option #2pros: Auth service is down? Who cares!
cons: Some user got banned? Darn, I just gave them the keys to my car 5 minutes ago.

Solving Issues with Fundamental Option #2

Issue: 제명된 고객에게 접근할 수 있는 Key를 주고 제명했는데, 그 사람이 가지고 있는 Key가 여전히 유효한 경우

JWT Mechanism: Token은 특정 시간 동안에만 유효하다. ( 놀이동산 입장시 손목에 부착하는 표를 생각하면된다)

Orders Service가 자체적으로 JWT의 만료 여부를 검증할 수 있는 로직을 가지고 있고 만약 JWT가 만료되었다면 두 가지 경우의 수가 있다.

  1. Auth Service에 요청을보내 Token을 재생성 할 수 있는 로직 혹은 에러 메세지를 전송해준다.
  2. Orders Service가 자체적으로 거절(Rejection)을 만드는 방식이다.
  • 유효한 토큰을 가지고 다시 요청해주세요와 같은 에러 메세지 전송
  1. Admin User가 특정 사용자가 서비스에 접근하지 못하도록 요청을 보낸다.
  2. Auth Service는 이 요청을 받아 DBhasAccess: false; 로 업데이트를 해준다.
  3. Event Bus의 개념을 이용해서 2번의 요청과 응답 과정이 끝나면 UserBanned EventEvent Bus에 전송해준다.
  4. Event Bus는 모든 Microservices 혹은 특정한 Microservice 에게 다음과 같은 Event가 발생했다고 전달한다.
  5. 해당 Event를 받은 Service는 내부 로직에 따라 즉시 업데이트 정보를 반영해 특정 사용자의 사용을 방지한다.
  • Short-lived in memory cache를 사용하는 이유는 Expired Token으로 접근을 했기 때문에 엄격한 서비스 입장에서는 부정한 방식의 접근이라 간주하고 일종의 징벌처럼 특정 시간 동안 서비스를 이용하지 못하게 하는 것이다. 이후 다시 로그인해서 정상적으로 JWT를 발급받으면 다시 서비스를 이용할 수 있다.

Cookie vs JWT

Cookie

  1. 서버 로직에 따라 응답으로 브라우저에 전송된다.
  2. 1번의 응답을 받은 브라우저는 자동으로 Cookie Key: Value 형태로 저장한다.
  3. 브라우저에서 서버로 요청을 보낼 때 자동으로 요청을 보내는 정보와 함께Headerkey: value, cookie: value 형태로 같이 요청을 한다.

JWT

payload → JWT Creation Algorithm → Encryption

브라우저에서 Authorization or Body or Cookie 내부에 Token을 담아 서버에 요청한다.

Cookies- Transport Mechanism
- Moves any kind of data between browser and server
- Automatically managed by the browser (이 부분은 별도의 로직을 작성하지 않아도 되기 때문에 수고를 덜어준다)
- 애초에 쿠키는 브라우저와 서버 사이의 데이터를 주고 받기 위한 목적으로 구현되었다. (애초에 인증,권한의 목적으로 구현된 것이 아니다)

JWT
- Authentication/Authorization Mechanism
- Stores any data we want
- We have to manage it manually
- JWT는 애초에 인증, 권한의 목적으로 구현되었다.
- Cookie와 달리 Browser와 서버 사이에 주고 받는 로직을 일일이 다 구현해야한다.

References:

https://www.udemy.com/course/microservices-with-node-js-and-react/learn/lecture/19119742#questions/11200633

--

--