Skip to content

Instantly share code, notes, and snippets.

@ninanung
Last active September 20, 2023 16:16
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ninanung/2ad24c760e81401ed65f13f634a25e73 to your computer and use it in GitHub Desktop.
Save ninanung/2ad24c760e81401ed65f13f634a25e73 to your computer and use it in GitHub Desktop.
Github로 로그인하기!

Github로 로그인하기 feat.Vue and Node.js

1. Github로 로그인하기?

요즘들어 "~로 로그인하기" 가 많아지고 있다. 페이스북이나 구글이 대표적이고, 한국에서는 네이버도 많이 사용하며 개발자 관련 웹에서는 깃허브도 껴있는 경우가 많다. 이런 식의 다른 서비스를 통해 인증하는 방식을, OAuth 인증 방식이라고 하는 모양이다. 내가 회사 업무를 위해 사용하는 몇몇 소프트웨어도 이러한 인증을 지원하는 경우가 많다. 이 글에서는 그러한 인증을 구현하지는게 아니라 그러한 인증을 사용해 보자는 것에 목적을 둔다. 어떤 방식으로 인증하는지를 직접 사용해보고 OAuth방식 인증의 절차를 알아보는 기회도 될것이다.

2. 목표

목표
위와 같이 버튼을 누르면 Github에서 인증을 실행하고 관련 데이터를 받아오는 동작을 구현해 볼 것이다.

3. 동작시키기

서론이 길었으니 구현으로 빨리 넘어가보자. 해당 글을 이해하기 위해서는 Node.jsVue에 대한 기본적인 지식이 있어야 하며, 그렇다는 전제하에 진행한다. Vue에 대해서는 사실 몰라도 될 수준으로만 작성할 것이며 정말 설명이 필요한 부분은 따로 얘기하고 넘어가겠다. 만약 코드를 확인하고 싶으면 언제든지 작성자의 Github 저장소에서 확인할 수 있다.

3-0. 앞서

코드를 작성하기에 앞서서 먼저 해두어야 할 단계가 있다.

  1. 당연하지만 Github계정이 필요하다. 만약 없다면 만들어두자.
  2. 또 당연하지만 Vue와 Node가 준비되어 있어야 한다.
  3. Github에서 OAuth App이라는 것을 만들고 몇가지 준비를 해야한다. 깃허브 계정이 있다면 로그인 후 해당링크에서 아래 단계를 수행할 수 있다.
  • New OAuth App 버튼을 눌러서 새로운 App을 등록해야 한다. 그러면 아래와 같은 창이 나온다.
    만들기
  • Application nameApplication description 은 그냥 해당 App의 이름과 설명을 명시하는 부분이니 대충 적어도 된다. 중요한건 Homepage URLcallback URL 이다. Homepage URL 에는 구동시킬 페이지의 주소를 적으면 된다. 우리는 Node.js를 이용할 것이기 때문에 기본 로컬서버인 http://localhost:3000 을 적으면된다. callback URL 은 나의 깃허브 계정을 이 앱(우리의 연습용 앱)에서 사용하겠다는 인증등록에 대한 허가의 증거로 반환값을 줄 URL을 설정한다. 이에 대한 자세한 설명을 후에 할것이기 때문에 우선은 http://localhost:3000/githublogin 으로 설정하여 생성하자.
    아이디
  • 위의 이미지는 생성된 App으로 들어간 화면이다. 아래에 보면 Client IDClient Secret 이 보일것이다. 이 두가지는 등록된 App의 열쇠와 같다. 흔히들 Key값 이라고 하는 특정한 문자열이다. 앞으로의 코딩에서 필요한 것이므로 텍스트를 복사해서 확인하기 쉬운곳에 옮겨두자.

3-1. Node.js 설정하기

Node를 설치하는 단계부터 설명할 필요는 없을 것같다. 모듈이나 기타 설정을 해보자. 우선은 아래의 커맨드를 실행해서 필요한 모듈을 설치한다.

npm install --save axios connect-history-api-fallback cors randomstring

axios : http request에 사용하는 모듈. 개인적으로는 request 같은 모듈보다 더 편하다고 생각함.
connect-history-api-fallback : 우리는 Vue를 통한 프론트엔드를 만들거기 때문에 라우팅을 적용하기 위해서 필요한 모듈이다. 링크참고
cors : Node는 기본적으로 서버 내에서 다른 서비스로의 http request를 허가하지 않는다. 이를 허가하기 위한 모듈.
randomstring : 무작위 문자열을 만들어주는 모듈.

qs axios randomstring 모듈은 따로 서버에서 설정할 필요가 없이 임포트 해서 사용하면 되지만 다른 두개는 필요하다.

  • connect-history-api-fallback 은 아래의 코드를 참고하면 된다. app.js 파일참고
var connectHistoryApiFallbsck = require('connect-history-api-fallback');
var app = express();
app.use(connectHistoryApiFallbsck())
  • cors 는 아래의 코드를 참고하면 된다. 다만 주의할 점이 있는데, app.use(cors()) 를 통해 해당 모듈을 참조하도록 할때 라우트를 참조하는 부분보다 먼저 나와야 한다. 조금 설명하자면, 명시된 서버 주소로부터 외부로의 http request를 요청하는 것을 허가하겠다는 뜻이다.
const cors = require('cors');
app.use(cors({origin:"http://localhost:3000"}));
  • express앱을 만들어주는 CLI를 사용하면 기본적으로 두가지 서버 설정이 아래와 같이 되어있을 것이다.
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));

jade 를 사용하지 않고 Vue로 빌드한 파일을 사용할 것이기 때문에, 그것을 이렇게 바꾸자

app.set('view engine', 'html');
app.use(express.static(path.join(__dirname, 'dist')));
var express = require('express');
var path = require('path');
var router = express.Router();

router.get('/', function (req, res, next) {
  res.sendFile(path.join('../dist/test.html'))
});

module.exports = router;

3-2. Vue 설정하기

Vue역시 설치하고 프로젝트 생성하는 부분은 생략하겠다. 몇가지 모듈을 설치하자.

npm install --save axios vue-router

vue-router : Vue에서의 라우팅에 사용할 모듈.

  • vue-router 부분을 명시적으로 설정해야 하는데. main.js 파일에 코드를 추가하면 아래와 같다. main.js 파일참고
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import NotFound from './components/NotFound.vue'
import Main from './components/Main.vue'
import GithubLogin from './components/logins/github/GithubLogin.vue';
import User from './components/logins/User.vue';

Vue.config.productionTip = false
Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'history',
    routes: [
        { path: '/', name: 'main', component: Main },
        { path: '/githublogin', name: 'githublogin', component: GithubLogin },
        { path: '/user', name: 'user', component: User},
        { path: '*', component: NotFound },
    ]
})

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

App.vue 파일의 template 부분도 아래와 같이 변경하자. App.vue 파일참고

<template>
    <div id="app">
        <router-view></router-view>
    </div>
</template>

설명을 추가하자면, vue-router 를 통해서 Vue는 라우팅을 사용할 수 있다. main.js 파일에서 더한 코드는 그것을 명시하여 프로젝트에 추가하는 코드이며 App.vue 에서 변경한 템플릿은 라우트에 따라서 다른 페이지를 보여준다. <router-view></router-view>의 부분에 보여줄 컴포넌트들이 렌더링된다.

3-3. 버튼 만들기

나는 Vue로 만들기 싫은데요? 혹은 그 정도는 이미 할 수 있어요! 라고 한다면 사실 이 부분은 건너뛰어도 된다. 다른 프레임워크로 만들거나 그냥 HTML을 사용하거나 어쩄든 자신이 원하는 방식으로 만들어보자. 나는 Vue를 이용해서 다른 서비스의 OAuth를 시도해볼 생각이라 필요없는 Google이나 Facebook관련 코드가 있지만 무시하자. 바로 위의 Vue설정 부분에서 main.js 파일에 { path: '/', name: 'main', component: Main } 를 추가했다. 이는 사용자가 http://localhost:3000/ 로 접속했을 시 Main.vue 컴포넌트를 렌더링 하겠다는 말이다. 바로 그 컴포넌트는 매우 간단하다.

  • main.vue 전체코드. 그냥 Buttons.vue 파일을 불러와서 렌더링할 뿐이다.
<template>
    <Buttons />
</template>

<script>
import Buttons from './Buttons.vue'

export default {
    components: { Buttons }
}
</script>
  • Buttons.vue 전체코드. 문자열 요소들을 가지는 배열인 services 를 받아서 for문으로 LoginButton.vue 컴포넌트를 각각 렌더링한다.
<template>
    <div class='body'>
        <li class='li' v-for='(service, index) in services' :key=index>
            <login-button :index=index :service=service />
        </li>
    </div>
</template>

<script>
import LoginButton from './LoginButton.vue';

export default {
    components: { LoginButton },
    data() {
        return {
            services: ['github', 'facebook', 'google']
        }
    },
}
</script>

<style scoped>
    .body {
        list-style: none; width: 400px;
        margin: 0 !important;
        position: relative;
        left: calc(50% - 200px); right: calc(50% - 200px);
    }
    .li {
        width: 400px; margin: 0;
    }
</style>
  • LoginButton.vue 전체코드. 버튼 하나하나를 렌더링하며 버튼을 누를 시 axios 를 이용해서 Node.js서버로 http request를 보낸다. 버튼은 여기까지가 끝이다.
<template>
    <button class='button' v-on:click='buttonClick' >
        <img class='image' :src='require("../assets/" + service + ".png")' />
        {{'Login with ' + service }}
    </button>
</template>

<script>
/* eslint-disable no-console */
import axios from 'axios'

export default {
    props: [ 'service', 'index' ],
    methods: {
        buttonClick: function() {
            axios.get('http://localhost:3000/' + this.service)
            .then(function(res) {
                window.location.href = res.data;
            })
            .catch(function(err) {
                console.log(err)
            })
        }
    },
}
</script>

<style scoped>
    .button {
        width: 400px; height: 50px; font-weight: bold;
        font-size: 30px; background: #6D7E85;
        color: white; border-radius: 10px; margin-top: 10px;
        display: flex; align-items: center; justify-content: center;
    }
    .button:hover {
        cursor: pointer;
    }
    .image {
        width: 40px; height: auto;
    }
</style>

3-4. 깃허브에 인증 시도하기

자, 이제 여기부터가 조금 복잡한 단계이다. 서버와 클라이언트를 왔다갔다 하게 된다. 먼저, 버튼의 LoginButton.vue 에서 버튼을 클릭하면 발생시킬 함수를 이렇게 작성했었다.

buttonClick: function() {
    axios.get('http://localhost:3000/' + this.service)
    .then(function(res) {
        window.location.href = res.data;
    })
    .catch(function(err) {
        console.log(err)
    })
}

이 코드는 Node서버의 /github get request를 시도하고, 성공할 경우 인증을 시도할 Github의 URL을 받아서 리다이렉트 시킨다. 자, request를 보낸 서버의 코드를 보자.

  • github.js 파일 코드의 일부이다. 이 파일은 Node.js의 app.js 파일에서 app.use() 를 통해 이미 참조하여 가지고 있다는 전제하에 설명한다. 위에서 app.js 파일 링크를 올렸으니 다시 확인해 보아도 된다. github.js 파일참고
router.get('/', function(req, res, next) {
    state = rs.generate();
    const url = 'https://github.com/login/oauth/authorize?';
    const query = qs.stringify({
        client_id: client.CLIENT_ID,
        redirect_uri: client.HOST + 'githublogin',
        state: state,
        scope: 'user:email',
    });
    const githubAuthUrl = url + query;
    res.send(githubAuthUrl)
});

line 2 : 기억이 날지 모르겠지만, 처음에 randomstring 이라는 모듈을 설치했다. 모듈을 rs 라는 이름으로 불러와서 rs.generate() 를 이용해 만든 임의의 문자열을 전역변수에 저장하고 인증을 주고받는 도중에 내가 보낸 요청에 대한 답이 맞는지 확인하는 일종의 암호로 사용할 것이다.
line 3 : 주소를 보면 짐작 하겠지만 Github에 인증을 신청할 기본 주소를 url 이라는 변수에 저장했다.
line 4 : qsquerystring 이라는 Node의 자체 모듈을 불러온 것이다. 간단히 쿼리스트링을 만들어주는 기능을 한다. qs.stringify 를 이용해서 객체를 문자열화 시킬것이다.
line 5 : client_id 를 우리는 본적이 있다. 처음에 Github에서 App을 생성했을 때 받은 두개의 키값중 하나이다. 나는 그걸 따로 파일을 만들어서 불러오는 방식으로 사용했다. 자신이 만든 App의 client_id 를 넣으면 된다.
line 6 : redirect_uri 역시 App을 생성할 때 작성했던 부분이다. callback URL 로 작성했던 URL을 이곳에 넣으면 된다.
line 7 : line 2에서 만든 바로 그 state 이다.
line 8 : 이 부분은 조금 까다로운 설정인데, 인증을 통해 어디까지 권한을 받을건지 정하는 부분이다. user:email이라는 것은 사용자의 email에 대한 권한을 받겠다는 것이다. 이 연습을 통해서는 이메일만 허가할 것이다. 더 자세하게는 관련문서를 확인해보라.
line 9~10 : line 3,4를 통해 만든 문자열을 합쳐서 하나의 URL로 만들어 request에 대한 응답을 보낸다.

자 여기까지 했으면 인증을 시도하는 부분은 끝이다. 서버를 실행하고 localhost:3000 으로 접속하면 버튼이 나오고 버튼을 누르면 Github인증 페이지로 넘어가 질 것이다.
페이지
이런 페이지를 마주하게 되는데 초록색 버튼을 누르면 내 Github계정을 우리가 만든 앱에서 사용가능하도록 하가하게 된다. 그럼 자동으로 callback URL 에 설정한 주소로 사용자를 리다이렉트 시키는데, 이때 Github API 요청에 사용할 토큰을 받는데 사용할 정보를 쿼리스트링으로 만들어서 같이 넘긴다. 다만 이 단계에서는 아무것도 일어나지 않는다. 아직 아무런 설정을 해주지 않았으니 말이다. 다음으로 넘어가보자.

3-5. API사용을 위한 토큰 받기

계속 이어가자면, 우리는 callback URLhttp://localhost:3000/githublogin 으로 설정했다. 게다가 Vue를 사용중이기 때문에 connect-history-api-fallback 을 설정하였으므로 콜백은 서버가 아닌 프론트엔드로 들어오게 된다. 그걸 위한 설정을 프론트엔드의 main.js 에서 설정을 해 두었는데, { path: '/githublogin', name: 'githublogin', component: GithubLogin } 와 같이 라우트르 넣어주었다. 해당 라우트에 사용된 GithubLogin.vue 파일을 확인해 보도록 하자.

  • GithubLogin.vue 파일의 전체코드
<template>
    <div>
        <h1>GITHUBLOGIN</h1>
    </div>
</template>

<script>
/* eslint-disable no-console */
import axios from 'axios'

export default {
    methods: {
        redirect: function(url) {
            window.location.href = url;
        }
    },
    created() {
        const redirect = this.redirect;
        axios.get('http://localhost:3000/github/login?code=' + this.$route.query.code + '&state=' + this.$route.query.state)
        .then(function(res) {
            if(!res.data) {
                alert('something went wrong. can\'t get access token.');
                redirect('/')
            }
            redirect('/user?token=' + res.data + '&service=github')
        })
        .catch(function(err) {
            alert('something went wrong. request failed.');
            console.log(err)
            redirect('/')
        })
    },
    beforeRouteEnter(to, from, next) {
        if(to.query) {
            if(to.query.code && to.query.state) {
                next()
            } else {
                alert('there\'s no query data.')
                next('/')
            }
        } else {
            alert('there\'s no query data.')
            next('/')
        }
    }
}
</script>

콜백을 받았을 때 어떤 순서로 실행되는지를 알아보자. 우선은 beforeRouteEnter 함수를 통해 해당 페이지로 들어오는 경로에 쿼리스트링이 없다면 경고를 보여준 후 다시 처음 URL로 돌려보낸다. 만약 콜백으로 들어온 경우에는 다연히 쿼리정보가 있기 때문에 다음에는 created 함수가 실행된다. 이는 해당 Vue 컴포넌트가 만들어질 경우에 자동으로 실행되는 자체 함수인데, 이 파일에서는 해당 코드를 통해 서버에 get request를 시도한다. URL은 http://localhost:3000/github/login/ 이며 쿼리를 같이 넘기도록 되어있다. 쿼리정보는 Github에서 콜백으로 받은 code 정보와 우리가 처음에 넘겼던 임의의 문자열 state 이다. 한번 서버 코드를 확인해 보자.

  • github.js 파일 코드의 일부이다. 4. 깃허브에 인증 시도하기 에서 이미 본 파일이지만 라우트가 다르다.
router.get('/login', function(req, res, next) {
    const returncode = req.query.code;
    const returnstate = req.query.state;
    if(state !== returnstate) {
        res.send(false);
    }
    const host = 'https://github.com/login/oauth/access_token?'
    const queryString = qs.stringify({
        client_id: client.CLIENT_ID,
        client_secret: client.CLIENT_SECRET,
        code: returncode,
        redirect_uri: client.HOST + 'githublogin',
        state: state,
    })
    const authurl = host + queryString;
    axios.post(authurl)
    .then(function(resp) {
        const token = qs.parse(resp.data).access_token;
        res.send(token)
    })
    .catch(function(err) {
        console.log(err);
    })
});

line 2~6 : 클라이언트에서 request를 통해 넘긴 쿼리정보를 각각 returncodereturnstate 변수에 저장하고, 우리가 처음에 정한 statereturnstate 가 같은지를 확인한다. 보통은 당연히 같아야 하며, 단순히 보안을 위한 절차이다.
line 7~15 : 4. 깃허브에 인증 시도하기 의 서버부분 코드와 같은 단계다. 토큰을 요청할 Github주소를 변수에 저장하고 querystring 모듈을 이용해서 필요한 데이터를 문자열화 한다. client_idclient_secret 그리고 redirect_uri 역시 이전에 설명한 것 처럼 Github에서 App을 생성할때 넣은 callback URL 과 받은 카값을 넘기면 된다. codestate 는 line 2에서 만든 변수를 사용하면 된다. 마지막줄은 그렇게 만들어진 문자열 두개로 요청할 URL을 만든다.
line 16~23 : 어? 서버에서 request를 사용하네? 라고 생각할 수도 있지만 이것을 위한 설정을 우리는 이미 한적이 있다. 1. Node.js 설정하기 에서 cors 모듈을 통해 서버에서 다른 서비스로 request요청을 허가해 두었다. axios 를 통해 이전 코드에서 만든 URL로 post request를 보낸다. 성공할 경우 API요청에 사용할 토큰을 반환하고, 받은 토큰은 다시 클라이언트로 반환한다.

  • 자, 다시 Vue코드로 돌아오자. GithubLogin.vue 코드의 일부이다.
axios.get('http://localhost:3000/github/login?code=' + this.$route.query.code + '&state=' + this.$route.query.state)
.then(function(res) {
    if(!res.data) {
        alert('something went wrong. can\'t get access token.');
        redirect('/')
    }
    redirect('/user?token=' + res.data + '&service=github')
})

created 함수에서 이 코드를 통해 서버로 요청을 보냈던 것을 기억해 내자. 요청이 성공할 경우 서버에서 토큰을 반환하는 것을 확인했다. 해당 코드에서는 토큰을 받아서 쿼리스트링에 포함시킨 뒤 http://localhost:3000/user 로 리다이렉트한다. 여기까지가 Github에 토큰을 요청하고 받는 부분이다. 거의 다 왔다. 이제 마지막으로 API를 요청해서 사용자의 email정보를 받아서 보여주기만 하면 된다.

3-6. API 요청하기

리다이렉트 한 http://localhost:3000/user 주소는 Vue의 main.js 파일에서 { path: '/user', name: 'user', component: User} 로 설정했다. 아마 이 코드는 이제 익숙할 것이다. 컴포넌트를 불러오는 라우팅 코드이다. 컴포넌트는 User 이다. 빠르게 확인해보자

  • User.vue 파일의 전체코드.
<template>
    <div>
        <h1>USER</h1>
    </div>
</template>

<script>
/* eslint-disable no-console */
import axios from 'axios'

export default {
    methods: {
        redirect: function(url) {
            window.location.href = url
        }
    },
    created() {
        const redirect = this.redirect;
        if(this.$route.query.service === 'github') {
            axios.get('http://localhost:3000/github/user?token=' + this.$route.query.token)
            .then(function(resp) {
                alert(resp.data + '! login success!');
            })
            .catch(function(err) {
                console.log(err)
                redirect('/')
            })
        }
    },
    beforeRouteEnter(to, from, next) {
        if(to.query) {
            if(to.query.service) {
                next()
            } else {
                alert('there\'s no query data.')
                next('/')
            }
        } else {
            alert('there\'s no query data.')
            next('/')
        }
    }
}
</script>

보면 알겠지만, GithubLogin.vue 파일의 코드와 거의 같다. axios 요청으로 반환한 값을 alert() 함수로 보여주는 것 말고는 완전히 같다고 해도 무리가 없다. beforeRouteEnter 는 넘어가겠다. 같은 코드다. created 함수 부분의 코드도 완전히 같은 원리지만, 서버로 요청하는 URL이 http://localhost:3000/github/user 이고 이번에는 쿼리스트링으로 GithubLogin.vue 에서 넘겨준 토큰을 서버로 넘긴다. 딱 예상이 가겠지만, 맞다. 서버도 코드가 비슷하다. 확인해 보자

  • 이제는 익숙한 github.js 파일 코드의 일부이다.
router.get('/user', function(req, res, next) {
    const config = {
        headers: {
            Authorization: 'token ' + req.query.token,
            'User-Agent': 'Login-App'
        }
    }
    axios.get('https://api.github.com/user/public_emails', config)
    .then(function(resp) {
        res.send(resp.data[0].email);
    })
    .catch(function(err) {
        console.log(err)
    })
});

line 2~7 : Github로 보낼 API요청에 사용할 header정보를 미리 설정한다. 쿼리로 받은 토큰을 인증정보에 넘기고 User-Agent 에 나의 앱에서 보낸다는 것을 명시한다. User-Agent 에 우리는 앱에서 보내는 것을 명시하고 있지만 일반 유저 입장에서 API요청을 보낼때는 자신의 Github아이디를 넣어야 한다. User-Agent 란 결국 누가 Github서버로 API 요청을 보냈는가?(누구인가? 누가 기침소리를 내었어?) 를 판단하고자 하는 것이다.
line 8~14 : 이제는 익숙하다 못해 지루해진 axios 모듈로 get request를 보내는 코드이다. 보내는 URL과 끝에 line 2~7에서 설정한 config 변수를 같이 보내주는 것을 주의하자. 요청이 성공할 경우 { email: 'ninanung@naver.com', primary: true, verified: true, visibility: 'public' } 와 같은 값을 받게된다. 이 코드에서는 그 중 email값만 빼서 다시 클라이언트로 반환한다. email주소 이외에 primary나 verified가 궁금하면 Github에서 문서를 찾아보자.

  • 서버로부터 email주소를 반환받았다. User.vue 코드로 돌아오면.
axios.get('http://localhost:3000/github/user?token=' + this.$route.query.token)
.then(function(resp) {
    alert(resp.data + '! login success!');
})

로그인이 되었다는 증거로 alert(resp.data + '! login success!'); 를 통해 이메일을 띄우고 끝이다.

3-7. 마무리

이제 코드는 모두 작성했다. 사실 이 부분은 Vue를 알고있다면 이미 아는 사실이겠지만, 터미널에서 npm run build 커맨드를 통해서 우리의 Vue프로젝트를 빌드하고 빌드된 결과물을 서버가 있는 폴더로 옮겨야 한다. 그래야 처음 설정한 HTML설정에 따라서 서버가 특정 동작에 따라 페이지를 불러올 수 있다. Vue프로젝트에서 빌드된 dist 폴더를 서버폴더의 app.js 가 있는 root경로로 옮겨서 npm start 커맨드를 통해 실행하고 아무 브라우져나 켜서 localhost:3000 로 접속하면 동작하는 페이지를 볼 수 있을 것이다.

4. 끝

어라? email주소만 띄우고 끝이야? 라고 하겠지만 더 복잡한 API는 알아서 알아보고 구현하도록 하자. 어차피 이 글을 통해 다 다룰수도 없고 의미도 없다. 본인이 원하는 기능을 찾아서 사용하자. 하지만 Github의 OAuth인증방식은 전부 확인해 보았다.

  1. App을 생성하도록 하고 사용자가 Github로 로그인하기를 시도하면 키값과 state와 콜백 주소를 쿼리스트링으로 넘겨서 인증을 시도한다.
  2. 사용자가 App에서 데이터를 확인하는 것을 허가하면 code를 념겨서 API 요청에 필요한 code를 전달한다.
  3. 전달받은 code와 App의 정보를 같이 넘기면 토큰을 발급해준다.
  4. App은 해당 토큰을 이용해서 사용자와 관련된 API를 사용하여 App내부에서 유용하게 사용할 수 있다.

한가지 유의해야 할 점은 넘겨받은 토큰은 그대로 사라지지 않도록 어딘가에 저장해 놓아야 한다. 안그러면 매번 API 콜을 할때마다 토큰을 발급받아야 하는데 이는 멍청한 짓이다. 이건 연습코드이기 때문에 그냥 사라지도록 만들었지만, 원래는 이러면 안된다. 토큰이란 고유한 값이어야 한다.

5. 참고

How to do 3-legged OAuth with GitHub, a general guide by example with Node.js 이 글을 굉장히 많이 참고했다. 잘 쓰여진 글이다. 영어로 쓰여진 글이지만 참고해도 좋을 것이다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment