[Front-end] 로그인 구현 -1 OAuth/JWT/Session

silverj-kim·2020년 6월 28일
6
post-thumbnail

이번에 회사에서 소셜 로그인 쪽을 구현하게 됐는데 리서치하다보니 생각보다 챙겨야 할 것들과 알아두면 좋을 개념들이 많아서 정리하려고 한다.




지난 글에 쿠키, 세션, 캐시에 대해서 간략히 정리했는데 사실 그 글도 로그인 구현-0 에 들어가야할 글이었다. 앱으로 로그인을 구현했을 때는 서버로부터 받은 토큰을 암호화 하여 스토리지에 저장했다가 서버에 요청시 Header에 같이 보내주면 끝. 이었다. 그런데 웹에서 구현하려고 하니 생각보다 결정 해야할 것, 생각 해야할 것이 더 많았다.



1. 쿠키(Cookie),세션(Session)

2. OAuth

Open Authorization, Open Authentication

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로 사용되는 접근 위임을 위한 개방형 표준이다. by Wiki


쉽게 말해 Service Provider(Facebook, Google, Kakao 등)의 유저 비밀번호를 Third party 앱에 제공 없이 인증, 인가 할 수 있는 개방형 표준 프로토콜이다.
OAuth 인증을 통해 유저 대신 우리 앱에서 Google이 제공해주는 API 에 접근할 수 있는 권한을 얻을 수 있다.
인증을 받을 때 유저의 아이디와 비밀번호를 직접 주고 받는 것은 위험하기 때문에 OAuth 를 통해 인증하고 Service Provider에서 인증이 완료되면 제공하는 API 에 접근할 수 있는 Access Token을 준다.

개념

용어설명
UserService Provider에 계정을 가지고 있으며 Consumer앱을 이용하려는 유저
Service ProviderOAuth를 사용하는 OAuth API를 제공하는 서비스(Social Service)
Protected ReourceService Provider로부터 제공되어지는 API 자원들
ConsumerOAuth 인증을 사용해 Service Provider의 기능을 사용하려는 애플리케이션이나 웹 서비스(=내가 개발하는 서비스)
Consumer KeyConsumer가 Service Provider에게 자시능ㄹ 식별하는 데 사용하는키
Consumer SecretConsumer Key의 소유권을 확립하기 위해 Consumer가 사용하는 Secret
Request TokenConsumer가 Service Provider에게 접근 권한을 인증받기 위해 사용하는 값, 인증 완료 후 Access Token으로 교환
Acces Token인증 후 Consumer가 Service Provider의 자원에 접근하기 위하 키를 포함한 값
Token Secret주어지 토큰의 소유궈을 인증하기 위해 소비자가 사용하는 Secret

WorkFlow

간략하게 정리하는 플로우
C : Consumer, S/P: Service Provider, R/T: Requet token, A/T: Access token
1. C는 S/P에서 key, secret을 발급받는다
2. C는 S/P에게 R/T 요청, S/P는 C에게 R/T 발급한다
3. R/T 받은 후 C는 유저를 S/P의 인증사이트로 다이렉트 시키고 유저는 S/P에 로그인하여 인증한다
4. 해당 유저가 인증 되면 C는 OAuth_Token과 OAuth_Verifier를 넘겨준다
5. C는 S/P에게 A/T 요청한다
6. S/P는 받은 토큰과 서명들이 인증되어 있다면 A/T를 C에게 발급한다
7. A/T를 통해 S/P의 자원에 접근할 수 있게 된다


OAuth 1.0에는 S/P에 요청을 할 때 마다 전자 서명을 만들어 보내야 한다.요즘은 C의 개발 간소화를 중심으로 개발 된 OAuth 2.0을 주로 사용한다.
인증 절차 간소화로 구현이 좀 더 쉬워졌다. OAuth 1.0은 전자 서명 기반 이었다면 OAuth 2.0은 암호화를 https에 맡김으로 훨씬 더 간결해졌다.



OAuth 2.0

용어OAuth 1.0설명
Resource OwnerUser유저(사용자)
Resource ServerProtected ResourceREST API 서버
Authorization ServerService Provider인증 서버
ClientConsumerThird party 앱

OAuth 2.0이 되면서 인증 종류도 다양해졌다.
그 중 제일 많이 사용되는 Authorization Code Grant 를 알아보자.

Authorization Code Grant

A/S : Authorization Server, R/S: Resource Server
소셜로그인 할 때 가장 많이 쓰이는 방식
1. Client가 A/S에게 redirect URL을 포함하여 인증 요청 (주로 소셜 사이트에 들어가 프로젝트를 생성하고 redirect URL을 입력)
2. User가 "소셜 로 로그인하기" 버튼을 클릭하면 A/S는 해당 유저에게 로그인 창 제공
3. 로그인 후 A/S는 인증된 코드를 클라이언트에게 제공
4. 클라이언트는 인증코드를 넘겨주며 A/S에 Access Token을 요청
5. A/S는 클라이언트에게 Access Token 발급
6. Access Token을 이용하여 R/S에 접근 가능
7. 그 이후 토큰이 만료 됐다면 refresh token을 이용하여 재발급 가능



소셜로그인을 통해 이 유저에 대한 Access Token이 발급되면 그 토큰으로 소셜 서비스가 제공해주는 API로 유저 데이터을 사용할 수 있다.


우리 서비스(App)에서는 Access Token을 받아 우리 서버(App Back-end)로 전달해주면 우리 서버에서 A/S로부터 토큰을 검증 받은 후 유저 데이터를 받아와 클라이언트에 넘겨주게 개발되어 있다. 모바일 애플리케이션을 개발했을 때는 Access Token을 검증 받은 후 서버에서 유저에게 유니크한 토큰을 새로 발급하여 클라이언트에 전달해주었다. 그러면 클라이언트에서 그 앱을 보관 후 매 API 호출 마다 Header에 포함하여 서버에 요청했다.

웹 으로 개발하려고 하니 한 가지 더 생각할 게 생겼다.

자동 로그인을 해야하는데 유저의 프라이빗한 정보를 어디에 저장하고 관리할까? Session 방식 과 JWT 방식


첫 번째 방식이 전 포스트에 작성한 Session/Cookie 방식
로그인이 된 유저의 세션 정보를 세션 저장소에 저장한 뒤 클라이언트에게 세션 ID를 발급하여 쿠키에 저장한다. 그 후 데이터 요청을 할 때 마다 헤더에 세션 ID를 실어 보내면 서버에서 세션 검증 후 인증이 완료되면 데이터를 보내주게 된다.


그리고 새로 정리할 **JWT 방식**

토큰 기반 인증 방식 : JWT (Json Web Token)

JWT는 웹 표준으로 두 개체에서 JSON 객체를 사용하여 가볍고 자가 수용적인(self-contained) 방시긍로 정보를 안정성있게 전달해주는 토큰


주로 로그인에서 사용되며 플로우는 아래와 같다.
1. 유저가 로그인
2. 서버는 유저의 ID, PW로 유저를 validate한 뒤 jwt을 발급하여 전달
3. 클라이언트는 데이터를 요청할 때 마다 jwt를 포함하여 전달
4. 서버는 jwt를 validate한 후 데이터를 전달

JWT 장점

유저의 세션을 유지할 필요가 없기 때문에 로그인 여부에 대해 신경쓸 필요가 없다.
세션 관리를 위한 서버 리소스를 절약할 수 있다.


JWT

aaaaaa.bbbbbb.cccccc
header.payload.signature

JWT를 마들 때는 JWT 라이브러리가 자동으로 토큰을 인코딩 및 해싱 해주며 토큰의 뜻은 아래와 같다.

토큰 타입과 해싱 알고리즘을 지정해주는 Header

{
	typ: "JWT",
    alg: "HS256"
}

registered, public, private claim(정보의 한 조각)이 들어가 있는 payload
헤더의 이코딩 값과 정보의 인코딩 값을 합친 후 비밀키로 해쉬하여 생성한 signature



사실 상, 세션 관리로 할 지 JWT 방식으로 할지에 대한 고민은 프론트엔드의 고민 보다는 서버 측에 고민이 더 필요한 요소인 것 같다. 그치만 이러한 개념과 플로우를 알고 있어야 로그인 구현에 있어 조금은 덜 버벅일 것 같아 (ㅋㅋㅋ) 정리하게 되었다. JWT 방식으로 하게 될 것 같지만 JWT 방식으로 하게 된다면 그 후에 토큰을 local storage에 저장할 지, 쿠키에 저장할 지도 선택해야 한다. 또 세션이나 토큰이 만료 되었을 때 처리 로직에 대해서도 고민해야할 것 같다. 다음은 **로그인 구현 - 2** 에서![](https://velog.velcdn.com/images%2Fsilverj-kim%2Fpost%2F951236bd-50a1-4200-b9eb-b443dad2bc0a%2FIMG_1487.jpg)

출처 :
링크텍스트
링크텍스트

profile
Front-end developer

4개의 댓글

comment-user-thumbnail
2020년 6월 28일

Consumet ? Consumer 아닌가유?

1개의 답글