OAuth popup cross-domain security React.js

前端 未结 2 1243
野趣味
野趣味 2021-02-13 21:19

I\'m interested in how to implement OAuth in React using popup (window.open).

For example I have:

  1. mysite.com — this is where I op
相关标签:
2条回答
  • 2021-02-13 21:47

    Suggested by Khanh TO. OAuth popup with localStorage. Based on react-oauth-popup.

    Scheme:

    Code:

    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;
    
    0 讨论(0)
  • 2021-02-13 21:48

    I once encounter an issue on my oauth login flow with window.open/window.opener bug on ms-edge

    My flow before this issue was

    • On login button click open a popup
    • After successful login the oauth app redirect to my domain's page
    • Then i call a function of the parent window from with in the popup (window.opener.fn) with data from oauth response and the parent window then close the child popup window

    My flow after this issue was

    • On login button click open a popup
    • Create a setinterval in case (window.opener is undefined)
    • After successful login the oauth app redirect to my domain's page
    • Check if window.opener is available then do #3 from the above flow and clearInterval
    • If window.opener is not available then since i am on my domains page i try to set localstorage and try to read the localstorage from inside the setInterval function in parent window then clear the localstorage and setInterval and proceed.
    • (for backward compatibility) If localstorage is also not available then set a client side cookie with the data with a short expiry (5-10 sec) time and try to read the cookie (document.cookie) inside the setInterval function in parent window and proceed.
    0 讨论(0)
提交回复
热议问题