<aside> ❔ 참고 페이지
https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
</aside>
settings → developer settings → OAuth Apps에서 만들면됨
<aside> ❕ github 로그인 기능을 쓰기 위해선 유저가 자신의 정보를 서버로 보내줘야 한다.
그리고 정보를 받는 것을 유저에게 물어보는 페이지로 리다이렉트한다.
</aside>
요청하려면 아래 URL로 redirect
이 때 파라미터를 함께 전달
const baseUrl = "<https://github.com/login/oauth/authorize>";
const configs = {
client_id: process.env.GTIHUB_CLIENT_ID,
allow_signup: "false",
scope: "read:user user:email",
};
const params = new URLSearchParams(configs);
const url = `${baseUrl}?${params}`;
client_id : URL에 포함되는 공개된 ID
scope: 얻어올 수 있는 정보의 범위, 공백으로 여러개 넣을 수 있음.
https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
유저가 허가하면 callback 주소(세팅 페이지에서 지정했음)로 리다이렉트 시켜줌.
이 때 이후 사용할 토큰 값으로 code
를 query에 포함시켜준다.
받은 code를 가지고 github API에 접근하기 위해 access token을 요청해야 한다.
code
와 함께 POST 요청을 보낸다.
https://github.com/login/oauth/access_token
const baseUrl = "<https://github.com/login/oauth/access_token>";
const configs = {
client_id: process.env.GTIHUB_CLIENT_ID,
client_secret: process.env.GITHUB_SECRET,
code: req.query.code,
};
const params = new URLSearchParams(configs).toString();
const url = `${baseUrl}?${params}`;
const data = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
},
});
const json = await data.json();
리턴값 (json)
{
access_token: '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',
token_type: 'bearer',
scope: 'read:user,user:email'
}
access_token으로 github API를 통해 user정보를 요청한다.
이 때 원하는 정보를 얻을 수 있는 url로 요청 각각을 요청하면 된다.
Public user data
https://api.github.com/user
Authorization:
token ${access_token}`` 추가const { access_token } = json;
const githubApiUrl = "<https://api.github.com>";
const userData = await (
await fetch(`${githubApiUrl}/user`, {
method: "GET",
headers: {
Authorization: `token ${access_token}`,
},
})
).json();
Email https://docs.github.com/en/rest/reference/users#list-email-addresses-for-the-authenticated-user
https://api.github.com/user/emails
Authorization:
token ${access_token}`` 추가const emailData = await (
await fetch(`${githubApiUrl}/user/emails`, {
method: "GET",
headers: {
Authorization: `token ${access_token}`,
},
})
).json();
const email = emailDataList.find(
(emailData) => emailData.primary === true && emailData.verified === true
);
github 로그인이 아닌 다른 방식들로 로그인 했던 유저의 경우 같은 이메일을 사용할 때 별도의 예외 처리를 해주어야 한다.
github API로 받은 이메일 정보에서 verified, primary가 true인 이메일을 볼 수 있는데 이는 해당 이메일이 인증이 완료되었다는 의미이다. 즉 해당 이메일의 소유가 현재 유저라는 것이 확인되었다는 뜻이다.
그래서 이미 다른 방식으로 가입된 이메일을 사용할 경우 verified, primary 값을 확인 후 로그인을 허용한다.
const verifiedEmailObj = emailDataList.find(
(emailData) => emailData.primary === true && emailData.verified === true
);
if (!verifiedEmailObj) {
return res.redirect("/login");
}
const existingUser = await User.findOne({ email: verifiedEmailObj.email });
if (existingUser) {
...
} else {
// make new account data
}
return res.redirect('/');