728x90

github social 로그인 구현을 연습해보면서, 실제 소셜로그인에 대해서 이해하고 정리하려 한다.

 

Github 등록하기

github의 소셜로그인 서비스를 이용하기 위해서는 github의 OAuth를 사용해야하고 따라서 등록 과정을 거쳐야 한다.

  • 보통 검색창에 바로 사용하고자 하는 소셜서비스와 OAuth 를 검색하면 해당 페이지로 바로 들어갈 수 있다.
  • github의 경우, OAuth 등록을 위해서는
    : 로그인 -> my page의 setting -> developer setting -> OAuth Apps 클릭
  • 그러면 하단의 화면이 나온다.

  • a. Client ID: 내가 구현 할 어플리케이션인 Client를 식별 할 수 있는 ID
    b. Client Secret: 내가 구현 할 어플리케이션인 Client를 식별 할 수 있는 PW (절대, 코드에 노출되면 안되는 정보, 보안 이슈)
    c. Authorized Redirect URL: Resource Server가 권한을 부여하는 과정에서 Authorized Code를 전달해 줄 경로, (' Authorized rediret URIs로 Authorized Code 전달해줘~')

해당 정보가 Github와 내가 만든 서비스 사이에서 공유한다. 이 정보들은 외부에 노출되면 안된다!
또 중요한 것은

  • Homepage URL: 내 서비스의 URL
  • Authorizatiton callback URL: 사용자가 Github 로그인을 하면 redirect될 페이지의 주소.

user가 github에 내가 만든 서비스의 접근을 승인

[프론트] 깃헙 로그인 버튼 코드를 구현한다. 해당 코드는 a 태그로 되어있고 href는 개발한 서버의 auth api의 주소가 담겨있다.
아마 아래와 같은 href 주소를 버튼을 프론트에서 작성해야 한다.

1
2
3
4
5
<body>
    <a
      href="https://github.com/login/oauth/authorize?client_id=[위에서 받은 client id]&redirect_uri=[위에 나와있는 redirect url]"
      >GitHub 아이디로 로그인</a>
  </body>
cs

사용자가 깃헙 로그인 버튼을 누르면 위의 링크로 가게되고, 보이는 화면은
github을 통해 해당 서비스에 로그인하는 것을 허용할 것인지에 대한 화면이다

-> Authorize 버튼을 누르면 내가 사용자들을 redirect 시키고자 github OAuth에 등록한 링크로 이동하게 된다.

 

Github에게서 Access Token 받기

사용자가 승인을 하게 되면서 등록된 url로 redirect 될 때 전달되는 response의 header에 'https://[redirect URL인 callbackURL]?code=[Authorization Code]' 형식으로 Authorization Code를 준다. 이 code를 client_id와 client_secret과 함께 Github API auth api에 Post하면 access_token을 리턴 할 것이다. 서버에서는 해당 Access token을 요청하는 fetch 메소드를 작성해야한다.


이는 즉, 서비스의 server는 서비스의 client 입장에서는 서버의 위치이므로 client의 버튼 이벤트를 받는 get 이벤트를 동작 시키지만, 동시에 소셜 서비스에 인증을 요청하는 post 메소드를 보내는 client 역할을 하기도 한다. 따라서 하단의 코드를 보면 get 메소드 안에 axio모듈을 통해, post를 보내고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// GitHub에 OAuth 앱을 등록한 후, 발급받은 client id 및 secret을 입력한다. 
const clientID = process.env.GITHUB_CLIENT_ID
const clientSecret = process.env.GITHUB_CLIENT_SECRET
 
const app = express()
 
app.get('/callback', (req, res) => {
  //'/callback': 인증 정보를 바탕으로 access token을 받아올 수 있도록 도와주는 라우터이다.
  const requestToken = req.query.code //이 req.query.code가 위의 'code=[Authorization Code]' 에 해당한다.
  axios({
    method: 'post',
    url: `https://github.com/login/oauth/access_token?client_id=${clientID}&client_secret=${clientSecret}&code=${requestToken}`,
    headers: {
      accept: 'application/json',
    },
  }).then((response) => {
    const accessToken = response.data.access_token //Github가 access_token을 응답으로 줄 것이다. 
    res.redirect(`/welcome.html?access_token=${accessToken}`) //그리고 이렇게 accessToken을 받은 사용자에 한해서만 welcome 페이지로 리다이렉트 된다. 
    //그리고 welcome 페이지를 구성하는 client에서 get fetch를 통해 token및 데이터를 받아오게 된다.
  }).catch((err) => {
      console.error(err)
  })
})
cs

 

더 간단하게 작성하면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const response = await axios.post(
    'https://github.com/login/oauth/access_token',
    {
      code,
      client_id, // SAFU application의 정보
      client_secret, // SAFU application의 정보
    },
    {
      headers: {
        accept: 'application/json',
      },
    },
  );
 
   //Github가 access_token을 응답으로 줄 것이다. 
  const token = response.data.access_token;
cs

이렇게 post 메소들를 통해서 알게된 데이터를 서버에서는 ORM 함수를 통해 DB에 저장해주고, client에서는 하단의 코드를 통해서 로그인에 성공한 페이지에서 get fetch를 통해서 access token등, 로그인에 성공했을 때 받을 수 있는 정보를 받아온다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// GitHub API를 통해 사용자 정보를 받아올 수 있다. 
  fetch('//api.github.com/user', {
    headers: {
      // 이와 같이 Authorization 헤더에 `token ${token}`과 같이
      // 인증 코드를 전송하는 형태를 가리켜 Bearer Token 인증이라고 한다.
      Authorization: 'token ' + token
    }
  })
    .then(res => res.json())
    .then(res => { 
      // 이 응답에 대한 문서는 GitHub 공식 문서를 참조하세요
      // https://developer.github.com/v3/users/#get-the-authenticated-user
 
      document.body.innerText = `${res.name}님 환영합니다!`
    })
cs

더 간단하게 작성하면

1
2
3
4
5
6
const { data } = await axios.get('https://api.github.com/user', {
    headers: {
      Authorization: `token ${token}`,
    },
  });
 
cs

 

 

+) 추가

하지만 실제로 소셜로그인 코드를 구현하면서 위의 코드가 완전히 정답이 아니라는 사실을 알았다.

 

1) 프론트 사이드에서 위와 같은 모든 과정을 clinet에서 진행하고, 소셜로 부터 받은 데이터를 서버에 post method를 보내서 DB에 저장하고 세션/쿠키 인증을 받는 방법

2) 위의 방법 처럼 적절히 프론트와 서버에서 혼용해서 진행 ( 프론트에서 소셜서비스로 우선 redirect URL을 보내고, 이후 token 값들로 유저 데이터를 받아오고 저장하는 모든 과정을 서버에서 진행

3) 프론트에서는 소셜로그인 버튼 클릭에 대한 a 태그만 구현하고, 이후 clientID와 redirect URL 을 바탕으로 소셜서비스와 통신하고 유저 정보를 받아오는 모든 과정을 서버에서 진행

 

우리는 서비스 자체의 성격상, 서비스의 client는 브라우저의 view와 서비스의 server와의 통신에 집중하는 것이 좋을 것이라 판단하여,

3)번의 방법을 택했다.

 

이에 대해 구현한 코드와 설명은 아래 링크를 참고!

 

Express에서 github 소셜로그인 구현

Python Flask에서 카카오 소셜로그인 구현

728x90

+ Recent posts