如果用户在我的 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;