I am trying to redirect to a specific route if the user is logged in in my chrome extension (built in React). The login flow is as follows:
First the user logs in through a React app, and sends the user session to the chrome extension using chrome.runtime.sendMessage with the extension id as the parameter. The code for the above is as shown:
/*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;
Once the session is sent to the extension, in background.js the Message is intercepted, where the session is rebuilt after creating a CognitoUser object and is attached to the user (as shown here: https://stackoverflow.com/a/64325402/14410047 ). After this a login confirmation message is sent to the popup which causes the extension to redirect to the /extension route (I am using createMemoryHistory in the extension for routing) where the user may access the extension's functionality (the default route redirects to the React app for login).
The problem here is that to redirect to the /extension route, I have to send the session each time from the React app, even though the session has been created in the background. I decided to use React Hooks to check if the session already exists in the background, in which case, it should redirect to /extension. This, for some reason, hasn't worked. The message goes to the background but the confirmation message is not received by the popup.
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;