0

如果用户在我的 chrome 扩展(内置 React)中登录,我正在尝试重定向到特定路线。登录流程如下:

首先,用户通过 React 应用程序登录,并使用chrome.runtime.sendMessage扩展 id 作为参数将用户会话发送到 chrome 扩展。上面的代码如下所示:

/*global chrome*/
import React from 'react';
import './App.css';

import { Auth } from 'aws-amplify';

const App = () => {

  async function test() {
    const extensionId = 'extension_id';
    const session = await Auth.currentSession();
    console.log(session);
    chrome.runtime.sendMessage(extensionId, {session: session},
          function(response) {
             console.log(response);     
          });
    }

  const googleSignInHandler = (event) => {
    Auth.federatedSignIn({ provider: "Google" });
  }

  const signInHandler = async (event) => {
    Auth.federatedSignIn();
  }

  const signOutHandler = event => {
    Auth.signOut();
  }

  const sessionHandler = (event) => {
    test();
  }

  const userHandler = (event) => {
    const user = Auth.currentAuthenticatedUser();
    user.then(result => console.log(result)).catch(error => console.log(error));
  }

  return (
    <div>
          <button onClick={signOutHandler}>Signout</button>
          <button onClick={sessionHandler}>Send session to the extension</button>
          <button onClick={userHandler}>Check User</button>
          <button onClick={googleSignInHandler}>Sign in With Google</button>
          <br></br>
          <button onClick={signInHandler}>Sign in</button>
    </div>
  )
}

export default App;

一旦会话被发送到扩展,在background.js消息中被拦截,会话在创建 CognitoUser 对象后重建并附加到用户(如下所示:https ://stackoverflow.com/a/64325402/14410047 ) . 在此之后,登录确认消息被发送到弹出窗口,导致扩展重定向到/extension路由(我在扩展中使用 createMemoryHistory 进行路由),用户可以访问扩展的功能(默认路由重定向到 React 应用程序进行登录)。

这里的问题是,要重定向到/extension路由,我每次都必须从 React 应用程序发送会话,即使会话是在后台创建的。我决定使用 React Hooks 来检查会话是否已经存在于后台,在这种情况下,它应该重定向到/extension. 由于某种原因,这没有奏效。消息进入后台,但弹出窗口未收到确认消息。

Background.js

    // This grabs the session from the React app        
    chrome.runtime.onMessageExternal.addListener(
            async function (request, sender, sendResponse) {
                if (request.session) {
                    authenticateUser(request.session);
                } else {
                    console.log(request);
                }
                sendResponse("Session received");
        });
        
        //Re-build the session and authenticate the user
        export const authenticateUser = async (session) => {
            let idToken = new CognitoIdToken({
              IdToken: session.idToken.jwtToken
            });
            let accessToken = new CognitoAccessToken({
                AccessToken: session.accessToken.jwtToken
            });
            let refreshToken = new CognitoRefreshToken({
                RefreshToken: session.refreshToken.token
            });
            let clockDrift = session.clockDrift;
            const sessionData = {
              IdToken: idToken,
              AccessToken: accessToken,
              RefreshToken: refreshToken,
              ClockDrift: clockDrift
            }
            // Create the session
            let userSession  = new CognitoUserSession(sessionData);
            const userData = {
              Username: userSession.getIdToken().payload['cognito:username'],
              Pool: new CognitoUserPool({UserPoolId: "USER_POOL", ClientId: "CLIENT_ID"})
            }
            
            // Make a new cognito user
            cognitoUser = new CognitoUser(userData);
            // Attach the session to the user
            cognitoUser.setSignInUserSession(userSession);
            // If session exists, send a message to the popup
            cognitoUser.getSession(function(err, session) {
              if(session){
                chrome.runtime.sendMessage({
                  type: "SESSION_INFO",
                  message: "LOGGEDIN"
                })
                chrome.storage.local.set({ user: cognitoUser }, function() {
                                chrome.storage.local.get({user}, function(result) {
                                    console.log(result.user);
                                });
                            });
              } else {
                console.error("Error", err);
              }
            })
          }
          
    // function to check if user is Authenticated
    const isAuthenticated = async () => {
      return chrome.storage.local.get({user}, function(result) {
        let cogUser = result.user;
        return cogUser.getSession(function(err, session) {
          if (session) {
            return true;
          } else {
            return false;
          }
        })
      })
    }
   // This listener does not seem to be called 
   chrome.runtime.onMessage.addListener(async (request) => {
    if (request.type="REQ_SESSION_INFO") {
    let response = isAuthenticated().then((response) => {
      if (response) {
      // Send message to the popup
      chrome.runtime.sendMessage({
        type: "SESSION_RESPONSE",
        message: "LOGGEDIN"
      })
    } else {
      chrome.runtime.sendMessage({
            type: "SESSION_RESPONSE",
            message: "LOGGEDOUT"
          });
      }
      });
    }
  });

Popup.jsx

import React from 'react';
import logo from '../../assets/img/logo.svg';
import './Popup.css';
import {
  Router,
  Route,
  Switch,
  Redirect
} from 'react-router-dom';
import { createMemoryHistory } from "history";
import { Button } from './Button';
import { Blacklist } from './Blacklist';

const history = createMemoryHistory();

const Main = () => {
  return (
    <div>
    <Button />
    <Blacklist />
    </div>

  )
}

const SignIn = () => {
  return (
    <button onClick={() =>  {chrome.tabs.create({ url: "http://localhost:3001/" })}}>
                  Sign In</button>
  )
}

const GuardedRoute = ({ component: Component, auth, ...rest }) => (
    <Route {...rest} render={(props) => (
        auth === true
            ? <Component {...props} />
            : <Redirect to='/' />
    )} />
)

const Popup = () => {

  const [authState, setAuthState] = React.useState(false);

  React.useEffect(() => {
    chrome.runtime.sendMessage({ 
            type: "REQ_SESSION_INFO"
        });
    
    // Never executes
    chrome.runtime.onMessage.addListener((request) => {
    if (request.type=="SESSION_RESPONSE") {
      if (request.message =="LOGGEDIN") {
        setAuthState(true);
        history.push("/extension");
      } else if (request.message=="LOGGEDOUT") {
        setAuthState(false);
        console.log("Not logged in");
      }
    }
  });
  }, []);
  
  // This works fine (when session is sent from the React app to the background)
  chrome.runtime.onMessage.addListener((request) => {
    if (request.type=="SESSION_INFO") {
      if (request.message =="LOGGEDIN") {
        console.log("Login confirmed");
        setAuthState(true);
        history.push("/extension");
      }
    } 
  })

  return (
    <div className="App">
    <header className="App-header">
      <img src={logo} className="App-logo" alt="logo" />
        <Router history={history}>
          <Switch>
            <Route exact path="/">
              <SignIn />
            </Route>
            <GuardedRoute path="/extension" component={Main} auth={authState} />
          </Switch>
        </Router>
    </header>
    </div>
  );
};

export default Popup;
4

0 回答 0