[javascript] OAuth 팝업 도메인 간 보안 React.js
팝업 ( window.open
)을 사용하여 React에서 OAuth를 구현하는 방법에 관심이 있습니다.
예를 들어
mysite.com
— 팝업을 여는 곳입니다.passport.mysite.com/oauth/authorize
— 팝업.
주요 질문은 window.open
(팝업)과 (팝업) 사이의 연결을 만드는 방법입니다. window.opener
도메인 간 보안으로 인해 window.opener가 null이므로 더 이상 사용할 수 없습니다.
⇑
window.opener
는 (보안상의 이유로) 다른 호스트로 이동 할 때마다 제거, 주위 방법이 없습니다. 가능한 경우 프레임에서 결제하는 것이 유일한 옵션입니다. 최상위 문서는 동일한 호스트에 있어야합니다.
계획:
가능한 해결책:
2019 년에 가장 권장되는 방법은 무엇입니까?
반작용에 대한 래퍼 – https://github.com/Ramshackle-Jamathon/react-oauth-popup
답변
Khanh TO가 제안합니다 . localStorage를 사용한 OAuth 팝업 를 기반으로 반응-OAuth를-팝업 .
계획:
암호:
oauth-popup.tsx:
import React, {PureComponent, ReactChild} from 'react'
type Props = {
width: number,
height: number,
url: string,
title: string,
onClose: () => any,
onCode: (params: any) => any,
children?: ReactChild,
}
export default class OauthPopup extends PureComponent<Props> {
static defaultProps = {
onClose: () => {},
width: 500,
height: 500,
url: "",
title: ""
};
externalWindow: any;
codeCheck: any;
componentWillUnmount() {
if (this.externalWindow) {
this.externalWindow.close();
}
}
createPopup = () => {
const {url, title, width, height, onCode} = this.props;
const left = window.screenX + (window.outerWidth - width) / 2;
const top = window.screenY + (window.outerHeight - height) / 2.5;
const windowFeatures = `toolbar=0,scrollbars=1,status=1,resizable=0,location=1,menuBar=0,width=${width},height=${height},top=${top},left=${left}`;
this.externalWindow = window.open(
url,
title,
windowFeatures
);
const storageListener = () => {
try {
if (localStorage.getItem('code')) {
onCode(localStorage.getItem('code'));
this.externalWindow.close();
window.removeEventListener('storage', storageListener);
}
} catch (e) {
window.removeEventListener('storage', storageListener);
}
}
window.addEventListener('storage', storageListener);
this.externalWindow.addEventListener('beforeunload', () => {
this.props.onClose()
}, false);
};
render() {
return (
<div onClick={this.createPopup)}>
{this.props.children}
</div>
);
}
}
app.tsx
import React, {FC} from 'react'
const onCode = async (): Promise<undefined> => {
try {
const res = await <your_fetch>
} catch (e) {
console.error(e);
} finally {
window.localStorage.removeItem('code'); //remove code from localStorage
}
}
const App: FC = () => (
<OAuthPopup
url={<your_url>}
onCode={onCode}
onClose={() => console.log('closed')}
title="<your_title>">
<button type="button">Enter</button>
</OAuthPopup>
);
export default App;
답변
MS-Edge의 window.open/window.opener 버그로 oauth 로그인 흐름에 문제가 발생했습니다.
이 문제 이전의 흐름은
- 로그인 버튼을 클릭하면 팝업 열기
- 로그인에 성공하면 oauth 앱이 내 도메인 페이지로 리디렉션됩니다
- 그런 다음 oauth 응답의 데이터와 부모 창에서 팝업 (window.opener.fn)에서 부모 창의 기능을 호출 한 다음 자식 팝업 창을 닫습니다.
이 문제 이후의 흐름은
- 로그인 버튼을 클릭하면 팝업 열기
- 경우에 setinterval을 작성하십시오 (window.opener가 정의되지 않음)
- 로그인에 성공하면 oauth 앱이 내 도메인 페이지로 리디렉션됩니다
- window.opener가 사용 가능한지 확인한 다음 위의 흐름에서 3 번을 수행하고 clearInterval
- window.opener를 사용할 수없는 경우 내 도메인 페이지에 있으므로 localstorage를 설정하고 부모 창의 setInterval 함수 내부에서 localstorage를 읽으려고 시도하고 localstorage 및 setInterval을 지우고 진행하십시오.
- (이전 버전과의 호환성을 위해) 로컬 저장소도 사용할 수없는 경우 짧은 만료 (5-10 초) 시간으로 데이터를 사용하여 클라이언트 쪽 쿠키를 설정하고 부모 창의 setInterval 함수 내에서 쿠키 (document.cookie)를 읽으십시오. 발하다.