이번에 회사에서 소셜 로그인 쪽을 구현하게 됐는데 리서치하다보니 생각보다 챙겨야 할 것들과 알아두면 좋을 개념들이 많아서 정리하려고 한다.
지난 글에 쿠키, 세션, 캐시에 대해서 간략히 정리했는데 사실 그 글도 로그인 구현-0 에 들어가야할 글이었다. 앱으로 로그인을 구현했을 때는 서버로부터 받은 토큰을 암호화 하여 스토리지에 저장했다가 서버에 요청시 Header에 같이 보내주면 끝. 이었다. 그런데 웹에서 구현하려고 하니 생각보다 결정 해야할 것, 생각 해야할 것이 더 많았다.
OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로 사용되는 접근 위임을 위한 개방형 표준이다. by Wiki
쉽게 말해 Service Provider(Facebook, Google, Kakao 등)의 유저 비밀번호를 Third party 앱에 제공 없이 인증, 인가 할 수 있는 개방형 표준 프로토콜이다.
OAuth 인증을 통해 유저 대신 우리 앱에서 Google이 제공해주는 API 에 접근할 수 있는 권한을 얻을 수 있다.
인증을 받을 때 유저의 아이디와 비밀번호를 직접 주고 받는 것은 위험하기 때문에 OAuth 를 통해 인증하고 Service Provider에서 인증이 완료되면 제공하는 API 에 접근할 수 있는 Access Token을 준다.
용어 | 설명 |
---|---|
User | Service Provider에 계정을 가지고 있으며 Consumer앱을 이용하려는 유저 |
Service Provider | OAuth를 사용하는 OAuth API를 제공하는 서비스(Social Service) |
Protected Reource | Service Provider로부터 제공되어지는 API 자원들 |
Consumer | OAuth 인증을 사용해 Service Provider의 기능을 사용하려는 애플리케이션이나 웹 서비스(=내가 개발하는 서비스) |
Consumer Key | Consumer가 Service Provider에게 자시능ㄹ 식별하는 데 사용하는키 |
Consumer Secret | Consumer Key의 소유권을 확립하기 위해 Consumer가 사용하는 Secret |
Request Token | Consumer가 Service Provider에게 접근 권한을 인증받기 위해 사용하는 값, 인증 완료 후 Access Token으로 교환 |
Acces Token | 인증 후 Consumer가 Service Provider의 자원에 접근하기 위하 키를 포함한 값 |
Token Secret | 주어지 토큰의 소유궈을 인증하기 위해 소비자가 사용하는 Secret |
간략하게 정리하는 플로우
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 1.0 | 설명 |
---|---|---|
Resource Owner | User | 유저(사용자) |
Resource Server | Protected Resource | REST API 서버 |
Authorization Server | Service Provider | 인증 서버 |
Client | Consumer | Third party 앱 |
OAuth 2.0이 되면서 인증 종류도 다양해졌다.
그 중 제일 많이 사용되는 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로 유저 데이터을 사용할 수 있다.
웹 으로 개발하려고 하니 한 가지 더 생각할 게 생겼다.
자동 로그인을 해야하는데 유저의 프라이빗한 정보를 어디에 저장하고 관리할까? Session 방식 과 JWT 방식
첫 번째 방식이 전 포스트에 작성한 Session/Cookie 방식
로그인이 된 유저의 세션 정보를 세션 저장소에 저장한 뒤 클라이언트에게 세션 ID를 발급하여 쿠키에 저장한다. 그 후 데이터 요청을 할 때 마다 헤더에 세션 ID를 실어 보내면 서버에서 세션 검증 후 인증이 완료되면 데이터를 보내주게 된다.
JWT는 웹 표준으로 두 개체에서 JSON 객체를 사용하여 가볍고 자가 수용적인(self-contained) 방시긍로 정보를 안정성있게 전달해주는 토큰
주로 로그인에서 사용되며 플로우는 아래와 같다.
1. 유저가 로그인
2. 서버는 유저의 ID, PW로 유저를 validate한 뒤 jwt을 발급하여 전달
3. 클라이언트는 데이터를 요청할 때 마다 jwt를 포함하여 전달
4. 서버는 jwt를 validate한 후 데이터를 전달
유저의 세션을 유지할 필요가 없기 때문에 로그인 여부에 대해 신경쓸 필요가 없다.
세션 관리를 위한 서버 리소스를 절약할 수 있다.
aaaaaa.bbbbbb.cccccc
header.payload.signature
JWT를 마들 때는 JWT 라이브러리가 자동으로 토큰을 인코딩 및 해싱 해주며 토큰의 뜻은 아래와 같다.
토큰 타입과 해싱 알고리즘을 지정해주는 Header
{
typ: "JWT",
alg: "HS256"
}
registered, public, private claim(정보의 한 조각)이 들어가 있는 payload
헤더의 이코딩 값과 정보의 인코딩 값을 합친 후 비밀키로 해쉬하여 생성한 signature
Consumet ? Consumer 아닌가유?