[GCP] 구글 로그인 연동하기 (SSO)

[원본 링크]

구글도 타 SSO 시스템들과 대략 비슷한 구조를 따른다.
그냥 브라우저에서 SNS 로그인이 되면, 리다이렉트를 태우고 토큰을 받아와서 이래저래 써먹는 식이다.

이걸 통해서 한번 로그인을 구성해보도록 하겠다.

SSO용 구글 앱 등록은 구글의 클라우드 플랫폼인 GCP에서 수행할 수 있다.
계정이 없다면 먼저 만들어주고 들어가자




앱 설정하기

만약 프로젝트가 없었다면 새로 파서

이름을 적절히 지어서 만들어준 뒤,

해당 프로젝트로 전환한다.

사용자 인증 정보로 들어가서

동의 화면 구성

외부로 하고

적절히 정보들을 넣어준다.

이런건 넣으면 좋긴 하지만 비워둬도 된다.

범위(scope)에 대한 것도 등록할 수 있다.

근데 당장 필요하지는 않아서 넘기겠다.

그리고 테스트 사용자를 등록해준다.

프로덕션 모드가 아닐때는 저기에 등록한 계정만 로그인 테스트를 해볼 수 있다.

다 저장하고 생성해서 나가면 이렇게 구성이 되어있을 것이다.

나중에 프로덕션 모드로 전환할 때는 저걸로 게시를 하면 된다.

아직 끝이 아니다.

사용자 인증 정보 만들기를 클릭하고

OAuth 클라이언트를 만들어줘야 한다.

이름은 적절히 지어주고, 지금은 웹으로 하겠다.

로컬에서의 테스트를 위해 localhost들을 넣어줬다.
저 루트 페이지에서 구글 로그인 창을 띄우고, 창에서 로그인이 성공하면 리디렉션 URI로 인증 정보를 넘겨주는 형태가 될 것이다.

그럼 이런식으로 만들어질 것이다.

잘 보관한다.




브라우저 측 처리

그럼 저걸 이용해서 이제 브라우저에서 로그인 정보를 받아오는 법을 다뤄보도록 하겠다.

https://developers.google.com/identity/gsi/web/tools/configurator?hl=ko
여기 들어가면 샘플 코드들을 생성해서 쓸 수 있다.

근데 저 사이트는 단점이 좀 있는데, 언어가 한국어로 번역되면 코드가 터진다.
쓰려면 영어로 깔아줘야 한다..

아무튼 적절히 케이스 골라서

고르고

생성하면

이런식으로 뽑힌다.

받아적으면 대강 이런 형태가 될 것이다.

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <div id="g_id_onload" 
        data-client_id="클라이언트 키"
        data-context="signin"
        data-ux_mode="popup"
        data-login_uri="콜백 URL"
        data-auto_prompt="false">
    </div>

    <div class="g_id_signin" 
        data-type="standard"
        data-shape="rectangular"
        data-theme="outline"
        data-text="signin_with"
        data-size="large"
        data-logo_alignment="left">
    </div>

    <script src="https://accounts.google.com/gsi/client" async defer></script>
  </body>
</html>

문서화가 은근히 개판이라서 저 스크립트 태그 찾는데만도 한참 걸렸다.

아무튼 저렇게 해서 돌리면

이렇게 익숙한 버튼이 뜨고


누르면 로그인이 되면서 리디렉션 URI로 넘겨버린다.




리디렉션 URI

이건 경우에 따라서 브라우저에서 해도 되고, 서버에서 해도 될 것이다.

토큰을 받아먹을 리디렉션 API를 한번 파서 받아보겠다.

그럼 대충 저런 형태로

{
    "credential":"...",
    "g_csrf_token":"..."
}

값 2개가 넘어온다.
여기서 중요한건 credential이라는 값이다.
id token이라고 부르더라

저건 JWT 기반의 토큰이라서

까보면 별도 API 호출 없이도 이런저런 정보를 꺼내올 수 있다.





서버 측 처리

토큰에 정보가 들어있든 말든 서버에서는 해당 토큰이 해당 유저를 가리킬 수 없는 위조 불가능한 값이란 것을 판별할 수 있어야 한다.

NPM의 경우에는 google-auth-library 모듈을 통해 처리할 수 있다.

이런식으로 verify를 구현하고

const { OAuth2Client } = require("google-auth-library");

async function verify(token) {
  const client = new OAuth2Client({
    clientId: CLIENT_ID,
    clientSecret: SECRET,
  });

  const ticket = await client.verifyIdToken({
    idToken: token,
  });
  const payload = ticket.getPayload();
  return payload;
}

저걸로 토큰을 검증하면 된다.

문제없을때는 페이로드를 잘 긁어올 것이고

뭔가 위조된 값이라면 대조에 실패할 것이다.

그리고 각 유저들에 대한 고유값은 "sub"다.
데이터에는 저걸 google_sso_id 같은 필드로 추가해서 써먹으면 될 것이다.



참조
https://www.joinc.co.kr/w/man/12/oAuth2/Google
https://github.com/googleapis/google-api-nodejs-client
https://developers.google.com/identity/sign-in/web/sign-in
https://yohanpro.com/posts/codereview
https://jforj.tistory.com/239
https://cloud.google.com/architecture/identity/single-sign-on?hl=ko
https://developers.google.com/identity/sign-in/web/backend-auth?hl=ko
https://developers.google.com/identity/gsi/web/guides/verify-google-id-token?hl=ko