Project2 - Google Social Login

Heechul Yoon·2020년 3월 10일
2

LOG

목록 보기
28/62

2프로젝트로 sound cloud 스트리밍 사이트를 클론 해서 만들어보게 되었고, 구글로그인 기능을 구현해보았다.

구글로그인에 앞서 일반로그인 과정을 짚고 넘어가자.

일반적인 로그인

  1. 유저가 브라우저에서 id와 password를 입력해서 front-end서버로 전달된다
  2. front-end서버에서 id와 password가 back-end서버로 전달되고 아이디가 존재하고 비밀번호가 데이터베이스의 비밀번호와 일치하면 토큰을 발행 해 준다.
  3. front-end에서는 발행받은 토큰을 세션스토리지에 저장시키고 request를 보낼 때 마다 header의 Authorization에 토큰을 실어서 보낸다.

구글 소셜 로그인

다른 소셜로그인과 마찬가지로 리소스 서버(resource server)인 구글의 api를 이용한다.

소셜로그인은 구글의 유저정보를 빌려서 사용한다. 유저가 입력한 정보가 구글에 있는 유저정보와 일치하면 내 서비스상의 토큰을 발행 해 주는 것이다. 그렇다면 어떻게 구글의 유저정보를 요청해서 가져올까?

정답은 구글의 auth_token을 통해서 구글의 유저정보를 가져 올 수 있다.

리소스서버(소셜로그인 서비스를 제공하는 서버)의 입장에서는 데이터 유출의 우려가 큰 것이기 때문에 승인과정을 거쳐야한다.

구글 로그인의 과정을 알아보자(backend 위주의 설명)

구글 autho2.0


위와 같이 여기 에서 web app에서 구글 로그인을 위한 소셜로그인 api 서비스에 가입해준다.

유저 로그인

유저가 내 서비스 창에서 구글로그인을 누르면 실재 구글의 로그인창이 뜨고 이메일과 페스워드를 입력한다.

로그인 성공

로그인에 성공하면 front-end 서버로 id_token이 전달된다.

id_token(frontend)

frontend 서버는 id_token을 backend의 구글로그인 api를 호출할 때 header에 실어서 보낸다. 리소스 서버에서 제공하는 auth_token은 대체로 만료기간이 있다(10~15분). 기간이 만료되면 refresh를 하거나 재발행을 해준다.

id_token 활용(backend)

backend 서버는 header의 Authorization을 확인해 들어온 id_token을 여기
에서 설명된 구글의 앤드포인트의 query parameter에 id_token을 넣어서 requests를 보낸다.

import requests    - [1]

    def post(self, request):
        data         = json.loads(request.body)
        id_token     = request.headers.get('id_token', None)
[2]     user_request = requests.get(f'https://oauth2.googleapis.com/tokeninfo?id_token={id_token}')
[3]     user_info    = user_request.json()
[4]     google_email = user_info.get('email')
        google_name  = user_info.get('name')

[1] python의 requets 모듈을 사용하여 구글 api에 request를 보낼 준비를한다.
[2] google api 조수를 넣고 id_token을 query parameter에 넣어준다.
[3] request로 가져온 값의 json을 읽어온다.
[4] 읽어온 json에서 email이라는 key의 값을 가져온다.

{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

구글 auth 2.0페이지에서 보면 [2]의 주소로 request를 보내면 위와같은 return을 얻을 수 있다. 여기서 email을 가져오는 것을 [4]를 통해서 확인할 수 있다.

[1]     if User.objects.filter(email = google_email).exists():
            user       = User.objects.get(email = google_email)
[2]         token      = jwt.encode({'user_id' : user.id}, SECRET_KEY, algorithm = ALGORITHM)
            return_key = {'user' : {'token' : token.decode('utf-8'), 'uuid' : user.uuid}}

            return JsonResponse(return_key, status = 200)

[1] id_token을 구글 api에 요청해서 받은 구글 유저의 email이 내 데이터베이스에 존재하는지 확인한다.
[2] 존재한다면 내 서비스의 token을 발행해서 실재 내가 운영하는 사이트에서 로그인한것 과 같은 권한을 준다.

[1]     user = User.objects.create(
            email = google_email,
            name  = google_name,
            uuid  = str(uuid.uuid3(uuid.NAMESPACE_DNS, google_email).hex)
        )
[2]     token = jwt.encode({'user_id' : user.id}, SECRET_KEY, algorithm = ALGORITHM)
        user_uuid  = user.uuid
        return_key = {'user' : {'token' : token.decode('utf-8'), 'uuid' : user_uuid}}

[1] 데이터베이스에 구글유저의 email이 없다면 생성해서 회원가입시키고,
[2] 자체 app의 토큰을 발행해준다.

profile
Quit talking, Begin doing

1개의 댓글

comment-user-thumbnail
2023년 8월 25일

감사합니다.

답글 달기