728x90

우선 우리는 node 기반의 서버로, express에서 소셜로그인을 구현하였다.

passport와 같은 추가 라이브러리는 사용하지 않았고, OAuth 기반으로 구현하였으며, 해당 원리에 대해서는 블로그에 이미 정리해두었으니 참고하면 된다!

 

github 소셜로그인 진행에 앞서서, github에 user 등록하는 방법에 대해서도 이미 블로그에 정리해두었으니, 해당링크에서 유저등록 부분까지만 참고하여 진행한 이후에 실제 코드만 여기서 참고하면 될것 같다!

 

-> 위의 링크에서도 기재해두었지만 나의 방법은 정답이 아니니까, 서버 사이드에서 소셜로그인을 구현하고자 할 때 express.js를 사용한다면 이 게시글을 참고하면 좋을듯 하다. 

 

 

우선 나는 아래의 순서로 소셜로그인을 구현했다. 각 단계에 대해서 코드와 함께 정리해보려 한다.

 

1 . 내 서비스의 client에서  소셜서비스를 진행하고자 하는 내 서비스의 server 주소로 이동한다. 

여기서 중요한 점은 axios 같은 라이브러리로 어떠한 요청을 보내는게 아니라 진짜 말그대로 a 태그로 주소를 이동하는 것이다.

 

[client 코드]

1
2
3
 <div className="social-login-div">
    <a href={'http://localhost:4000/auth/github'}>Log in with Github</a>
 </div>
cs

-> 왜이렇게 해줘야 할까? 에 대해서 처음에 이해를 못했고 한참 헤맸다. 

 그리고 내 나름대로 정리한 로직은 이렇다!

내 서비스의 server와 소셜서비스가 통신하는 과정이 마치 client와 server가 통신하는 모양새와 비슷하다고 생각했다. 따라서 내 서비스의 client는 잠깐 소셜로그인을 위해, client의 역할을 server에 넘겨주는 것이다. 

 

내 client의 포트는 3000번이었고, 서버가 4000번이었는데, 서버로 통신이 아닌 주소 이동으로 역할을 넘겨주는 것이다. 

해당 과정을 통해 server는 잠깐 client화 된다.

 

 

2. server로 페이지 이동이 되자마자, 소셜서비스로의 get 요청이 일어난다. 그 api 주소가 바로 /auth/github 인것이다.

 

[server 코드]

/auth/github.js 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const github = {
  clientID: process.env.GITHUB_CLIENT_ID,
  clientSecret: process.env.GITHUB_CLIENT_SECRET,
  redirectUri: 'http://localhost:4000/auth/github/callback',
};
 
module.exports = {
  get: (req, res) => {
    const githubAuthUrl =
      'https://github.com/login/oauth/authorize?client_id=' +
      github.clientID +
      '&redirect_uri=' +
      github.redirectUri;
 
    res.redirect(githubAuthUrl);
  },
};
cs

-> 위의 코드를 통해 소셜서비스로 get 요청이 가게되고, 그 때의 쿼리파라미터로 client ID와 redirect URI 가 간다.

그리고 이를 바탕으로 소셜서비스에서는 맞는 정보인지 확인하고 redirect URI로 redirect 될때 request token을 내 서비스의 server로 보내준다.

 

 

3. server에서는 해당 쿼리에서 request token을 뽑아내고 소셜 서비스에 access token을 요청하는 통신을 진행한다.

 

/auth/github/callback.js 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module.exports = {
  get: async (req, res) => {
    const { session, query } = req;
    const { code } = query;
 
    console.info('==== session ====requestCode====');
    console.log(session, code);
 
    const url = `https://github.com/login/oauth/access_token?client_id=${github.clientID}&client_secret=${github.clientSecret}&code=${code}`;
    try {
      const access_token = await axios({
        method: 'POST',
        url: url,
        headers: {
          'content-type''application/json',
        },
      });
      console.log(`response.data:${access_token.data}`);
      let access_token_split = access_token.data.split('&')[0].split('=')[1];
      console.log(`access_token:${access_token_split}`);
    
    // access token이 받아져 오면 4번 과정이 진행되어야 하는 코드자리
    
    } catch (error) {
      return res.json(error.data);
    }
  },
};
cs

 

4. 받아온 access token만을 쿼리에서 잘 분리해 내서 소셜서비스에 해당 토큰을 바탕으로 유저의 데이터를 요청한다.

해당 코드의 위치는 위의 코드 예시에서 표시된 부분에 기재하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
    try {
        const userResponse = await axios({
          method: 'GET',
          url: 'https://api.github.com/user',
          headers: {
            Authorization: `token ${access_token_split}`,
          },
        });
        console.log('social login result:', userResponse.data);
        // 받아온 유저 데이터를 DB에 저장하는 코드 
      } catch (error) {
        res.status(500);
      }
cs

 

5. 이제 server의 client의 역할이 끝이 났다. 유저 데이터를 받아오는 순간 server는 다시 server로써 DB에 유저 정보를 잘 저장하면 된다.

해당 코드도 위의 코드에 표시해둔 부분에 기재하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
       users
          .findOrCreate({
            where: { email: userResponse.data.id },
            defaults: {
              password: hash(userResponse.data.node_id),
              githubId: userResponse.data.login,
              kind_login: 'social',
            },
          })
          .then(([result]) => {
            session.userid = result.dataValues.id;
            console.log('session:', session);
            res.redirect('http://localhost:3000/');
          })
          .catch((err) => {
            console.log('err');
          });
cs

-> 여기서 가장 중요한! 이렇게 그냥 DB에 저장한다고 끝이 아니다. 그러면 서비스의 페이지는 여전히 서버 포트의 페이지에 머물러있게 되는 것이다. 여기서 res.redirect('http://localhost:3000/'); 해당 코드가 매우 중요하다. 즉 client에게 다시 제 역할을 돌려주며 서비스 페이지도 바뀌어야 하는 것이다. 

 -> 따라서 redirect로 페이지 변환을 해주고, 이때 client에 전달주어야 하는 내부 서비스의 token 값은 쿼리파라미터로 전달주면 된다!

728x90

+ Recent posts