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 등을 포함하는 문자열을 세 번째 매개변수로 기대합니다.개인적으로 나는 위에서 언급한 문자열로 변환되는 개체의 명시성을 선호합니다.
topandleftproperties have theautovalue - 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 areautothe popup will always spawn in the center, even if you changewidthorheight.
// 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.)