Gabriel Coach
Gabriel Coach

Reputation: 13

Okta Auth <Security/> Component seems to have a problem with reach-router

Here is the error that I get once I run the application.

ERROR in ./node_modules/@okta/okta-react/bundles/okta-react.esm.js 284:14-27

export ‘useRouteMatch’ (imported as ‘useRouteMatch’) was not found in ‘react-router-dom’ (possible exports: BrowserRouter, HashRouter, Link, MemoryRouter, NavLink, Navigate, Outlet, Route, Router, Routes, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, createRoutesFromChildren, createSearchParams, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, unstable_HistoryRouter, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams)

Here is what my code looks like in my Index.tsx file.

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "mdb-react-ui-kit/dist/css/mdb.min.css";

import { Security } from "@okta/okta-react";
import { OktaAuth } from "@okta/okta-auth-js";

const config = {
  clientId: "*********************",
  issuer: "https://****************/oauth2/default",
  redirectUri: "http://localhost:3000/login/callback",
  scopes: ["openid", "profile", "email"],
  pkce: true,
};

const oktaAuth = new OktaAuth(config);

const restoreOriginalUri = () => {
  // Callback function to restore URI during login
};

ReactDOM.render(
  <React.StrictMode>
    <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
      <App />
    </Security>
  </React.StrictMode>,
  document.getElementById("root")
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: 
reportWebVitals();

Upvotes: 1

Views: 4117

Answers (2)

nlbgr
nlbgr

Reputation: 21

I encountered the same problem, but here is my workaround.

First of all, this is not an official way, since react-router v6 is still not supported by okta. But with a few tricks it is possible to get okta-react running with react-router v6.

First you have to add the new <BrowserRouter> Tag in your index.js file:

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

After you have done that, you have to create a new component for secured routes. This component is quite simple, because it just checks if a user is logged in. If that is not the case you will be redirected to the login page. The check will be done with a hook provided by the okta-react library. We will setup the library later.

PrivateRoutes.js

import { Outlet, Navigate } from "react-router-dom";
import { useOktaAuth } from '@okta/okta-react';


const PrivateRoutes = () => {

    const { authState } = useOktaAuth();

    if(!authState) {
        return <div>Loading...</div>;
    }

    return (
        authState.isAuthenticated ? <Outlet /> : <Navigate to="/login"/>
    );
}

export default PrivateRoutes;

The last part is the App.js file. In this file we will setup the okta-react library and configure private and public routes. With the update from reacr-router v5 to react-router v6 quite a few things changed. If you want to know what changed and how that works I recomend the following article:

react-router v5 -> v6 migration guide

Important in the App.js file is, that <Security> Tag is wrapped around the <Routes> tag. Since the <Routes> Tag can only have <Route> Children (nested is possible but they have to be <Route>-Tags). A good tutorial for the private Routes in react-router v6 is the following Video (which provides the base for this post):

react-router v6 protected routes

The OktaAuth-Component is configured just like the official guide from okta describes it. The useHistory()-Stuff from react-router v5 is updated to useNavigate() from react-router v6. Here is my full App.js file:

App.js

import { Route, Routes, useNavigate } from 'react-router-dom';
import PrivateRoutes from './components/PrivateRoutes';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import { LoginCallback, Security } from '@okta/okta-react';

import Test from './pages/Test';
import Home from './pages/Home';
import Login from './pages/Login';


import './App.css';


const oktaAuth = new OktaAuth({
  issuer: process.env.REACT_APP_OKTA_ISSUER,
  clientId: process.env.REACT_APP_OKTA_CLIENT_ID,
  redirectUri: window.location.origin + '/login/callback'
});


function App() {
  const navigate = useNavigate();

  const restoreOriginalUri = async (_oktaAuth, originalUri) => {
    navigate(toRelativeUrl(originalUri || '/login', window.location.origin), {replace: true});
  }

  return (
    <div className="App">
      <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri} >
        <Routes>
          <Route element={ <PrivateRoutes />}>
          {/* PRIVATE_ROUTES_BEGIN */}
            <Route element={ <Home /> } path="/" exact/>
            <Route element={ <Test /> } path="/test"/>
          {/* PRIVATE_ROUTES_END */}
          </Route>
          <Route  element={ <Login /> } path="/login"/>
          <Route element={ <LoginCallback />} path="/login/callback"/>
        </Routes>
      </Security>
    </div>
  );
}

export default App;

Keep in mind, that the element of the new Route in react-router v6 takes HTML-Tags not just the "name" of the component

I hope this was kind of usefull. Again this is not the official way, but I did some testing to this topic and it works quite well for me. I still hope that okta releases official react-router v6 support in some time :)

Upvotes: 2

Peter Pajchl
Peter Pajchl

Reputation: 2709

I will go on a hunch and assume that you use newer react-router version than v5.

As per https://github.com/okta/okta-react/issues/187

@okta/okta-react currently only supports react-router v5. We are currently investigating v6 support

Upvotes: 1

Related Questions