OAuth 팝업 ~ 실용 가이드
야생에서 OAuth가 팝업 접근 방식을 사용하는 것은 놀라운 일이 아닙니다. 해결하기 쉬운 리디렉션은 여전히 발생하지만 용해되기 전에
access_token
를 기본 탭으로 다시 전달하는 생성된 팝업에서 발생합니다.This post is to be read as an enhancement of the previous one, so it has a slightly higher pacing. If in doubt, please refer to the accompanying code or the .
<a id="oauth-github-popup">Authenticate via GitHub (popup)</a>
<script>
const CLIENT_ID = "Iv1.395930440f268143";
const url = new URL("/login/oauth/authorize", "https://github.com");
url.searchParams.set("client_id", CLIENT_ID);
const cta = document.getElementById("oauth-github-popup");
cta.setAttribute("href", url);
cta.addEventListener("click", (event) => {
event.preventDefault();
// ...
접근성을 위해 GitHub OAuth 권한 부여 링크를 조합하고
<a>
태그에 첨부합니다. 그러나 클릭을 수신하여 기본 하드 리디렉션을 방지합니다.다음으로 Web APIwindow.open를 사용하여 팝업을 생성합니다.
width
, height
등을 포함하는 문자열을 세 번째 매개변수로 기대합니다.개인적으로 나는 위에서 언급한 문자열로 변환되는 개체의 명시성을 선호합니다.
top
andleft
properties have theauto
value - that's not in the specifications of the API, in fact it is interpreted by the following snippet as an instruction to place in the center of the relative axis. Basically if both areauto
the popup will always spawn in the center, even if you changewidth
orheight
.
// in the 'click' eventListener callback
const features = {
popup: "yes",
width: 600,
height: 700,
top: "auto",
left: "auto",
toolbar: "no",
menubar: "no",
};
const strWindowsFeatures = Object.entries(features)
.reduce((str, [key, value]) => {
if (value == "auto") {
if (key === "top") {
const v = Math.round(
window.innerHeight / 2 - features.height / 2
);
str += `top=${v},`;
} else if (key === "left") {
const v = Math.round(
window.innerWidth / 2 - features.width / 2
);
str += `left=${v},`;
}
return str;
}
str += `${key}=${value},`;
return str;
}, "")
.slice(0, -1); // remove last ',' (comma)
window.open(url, "_blank", strWindowsFeatures);
따라서 사용자는 멋진 GitHub 버튼을 클릭하고 팝업을 통해 인증합니다. 그러나 다음 기능을 가진 일부 페이지로 다시 보내도록 서버에 지시하는 것이 중요합니다.
access_token
window.opener
) 기억하세요: OAuth 콜백
사용자가 인증되면 GitHub는 OAuth 앱/GitHub 앱 생성에서 지정한 콜백 URL로 리디렉션합니다. 이에 대해서는 previous post 에서 자세히 설명합니다.
server.get("/oauth/github/login/callback", async (request, reply) => {
const { code } = request.query;
const exchangeURL = new URL("login/oauth/access_token", "https://github.com");
exchangeURL.searchParams.set("client_id", process.env.CLIENT_ID);
exchangeURL.searchParams.set("client_secret", process.env.CLIENT_SECRET);
exchangeURL.searchParams.set("code", code);
const response = await axios.post(exchangeURL.toString(), null, {
headers: {
Accept: "application/json",
},
});
const { access_token } = response.data;
const redirectionURL = new URL("popup", "http://localhost:3000");
redirectionURL.searchParams.set("access_token", access_token);
reply.status(302).header("Location", redirectionURL).send();
});
server.get("/popup", (request, reply) => {
return reply.sendFile("popup.html");
});
클라이언트는
/popup
로 리디렉션되고 popup.html
가 표시됩니다.<script>
if (window.opener == null) window.location = "/";
const access_token = new URL(window.location).searchParams.get(
"access_token"
);
window.opener.postMessage(access_token);
window.close();
</script>
window.opener
는 null
를 통해 페이지가 열리지 않은 경우 window.open
입니다. 이렇게 하면 사용자가 /popup
로 직접 라우팅하면 /
로 리디렉션됩니다.계산은 최소이며 꽤 빠릅니다. 스피너를 보여주는 것은 당신에게 좋은 일만 할 수 있습니다.
팁
SPA 및 해당 라우터 솔루션은 경로와 연결할 수 있는 몇 가지 방법
beforeEnter
을 제공합니다. 더 나은 경험을 제공하기 위해 거기에서 window.opener
값을 확인할 수 있습니다.거의 완료되었습니다! 팝업이
access_token
를 부모에게 다시 돌진하지만 듣고 있지 않습니다!window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== window.location.origin) {
console.warn(`Message received by ${event.origin}; IGNORED.`);
return;
}
const access_token = event.data;
}
예방책으로 다른 출처에서 오는 메시지는 무시하십시오. 코드에서
removeEventListener
를 고려하십시오.access_token
를 어딘가에 저장합니다. 이 시점에서 흐름은 .GitHub 앱 설치 및 권한 변경에도 이 패턴을 사용하는 것을 막을 수는 없습니다.
관련 게시물
콘택트 렌즈
Reference
이 문제에 관하여(OAuth 팝업 ~ 실용 가이드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/didof/oauth-popup-practical-guide-57l9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)