관리 메뉴

나의 개발일지(김지헌)

항해 99 85일차 12/12일 본문

항해 99

항해 99 85일차 12/12일

코딩이좋아요 2022. 12. 13. 02:15

오늘은 구글 소셜 로그인을 구현했다.

이전에 포스트한 카카오 로그인과 코드를 비슷하게 구현했다.

구글 로그인은 카카오와 다르게 인가코드를 받지 않고 에쎄스 토큰으로 준다.

 //프론트 코드
 
 const oAuthURL = 
  `https://accounts.google.com/o/oauth2/v2/auth?client_id=클라이언트아이디&
response_type=token&
redirect_uri=https://localhost:3000&
scope=https://www.googleapis.com/auth/userinfo.profile` //에메일과 프로필 받을려면 email+profile
  const oAuthHandler = () => {
    window.location.assign(oAuthURL);
  }
..위의 코드로 요청하면 등록된 리다이렉트 주소로 토큰값과 온다.
http://localhost:3000/google/callback#access_token=구글에서 주는 토큰값
&token_type=Bearer&expires_in=1234&scope=profile%20https://www.googleapis.com/auth/userinfo.profile

access_token으로 넘어오는 토큰 값을 백앤드에게 넘겨주면 된다.

//googlejwt.ts

import jwt from "jsonwebtoken";
import bcrypt from 'bcrypt';
import axios from "axios";
import { NextFunction, Request, Response } from "express";
import User from "../database/models/user";
import { Unauthorized } from "./exceptions";

export default async (req:Request, res:Response, next:NextFunction) => {
  try{
    //토큰 생성 및 토큰 전달 함수
  const googlejwt = async (userId:number)=>{
    const AccessToken = jwt.sign(
      { userId: userId },
      process.env.JWT_KEY!,
      { expiresIn: "3h" }
    );
    const RefreshToken = jwt.sign(
      { userId: userId },
      process.env.JWT_KEY!,
      { expiresIn: "7d" }
    );
    const salt = bcrypt.genSaltSync(Number(process.env.SALT_ROUND!));
    const refreshToken = bcrypt.hashSync(RefreshToken, salt); //암호화
    await User.update({refreshToken}, {where : {userId}}) //리프레쉬 업데이트
    res.cookie("refreshToken", RefreshToken);
    res.cookie("accessToken", AccessToken);
    res.status(200).json({
              message: "로그인 성공",
              accesstoken: AccessToken,
              refreshtoken: RefreshToken,
            })
          }
          const {authorization}=req.headers; //프론트에서 보내주는 구글 인가코드
    if(!authorization) throw new Unauthorized("토큰 정보가 없습니다.")
    const GoogleAccessToken = authorization
    //엑시오스 요청으로 유저정보 받아오기
  const googleUser = await axios
    .get(`https://www.googleapis.com/oauth2/v2/userinfo?access_token=${GoogleAccessToken}`, {
      headers: {
        Authorization: `Bearer ${GoogleAccessToken}`,
        accept: 'application/json' 
      },		
        })
        //정보 추출
const profileImg:string = googleUser.data.picture
const googleId:string = googleUser.data.id
const nickname:string = googleUser.data.name
const provider:string = 'google'
const email:string = googleUser.data.email
const exUser = await User.findOne({
  where : {googleId, provider}
})
//유저가 없을시 회원가입+로그인 유저가 있을시 바로 로그인
if(!exUser){
  const newUser = await User.create({googleId,nickname,provider,profileImg,email});
  const { userId } = newUser;
  googlejwt(userId)
}else{
const { userId } = exUser
  googlejwt(userId)
}
}catch(err){
  console.log(err)
  next(err)
}
}

 

백앤드는 프론트에서 받은 값을 가지고 다시 구글 유저정보를 받아오는 url로 axios 요청을 보내고 유저정보를 받아와서 저장 후 에쎄스토큰, 리프레쉬 토큰을 발급후 프론트에게 전달한다.

구현할때 조금 헷갈렸던 것은 프론트에서 넘겨주는 시크릿 토큰이 에쎄스 토큰인줄 알아서 axiox get요청을 보냈지만 401에러가 계속 나는거 였다. 이유를 알고보니 프론트 쪽에서 요청 경로를 다르게 보내서 토큰 값이 달라서 401에러가 나는거 였고, oauth2인증 방식을 공부를 해봐야겠다고 생각했다.

'항해 99' 카테고리의 다른 글

항해 99 87일차 12/14일  (0) 2022.12.15
항해 99 86일차 12/13일  (0) 2022.12.14
항해 99 84일차 12/11일  (0) 2022.12.12
항해 99 83일차 12/10일  (0) 2022.12.10
항해 99 82일차 12/09일  (0) 2022.12.10