DEV Community

suvel rathneswar⚛️
suvel rathneswar⚛️

Posted on

Redirect uri does not contain ? and hits an un-known page in React Router

🦨 If your application is adding "&state=" to the url after Keyclock is initialized, then this documentation might help you 🚑.


TLDR

👉 By default, when the responseMode is set to 'fragment', Keycloak adds the state parameter to the URL fragment. However, when the responseMode is set to 'query', the state parameter is added to the query string instead.

keycloak
    .init({ 
    onLoad: 'login-required',
    //add the below line 👇
    responseMode: 'query' 
    })
Enter fullscreen mode Exit fullscreen mode

👉 Alternate solution, use BrowerRouter * without responseMode* (default to 'fragment')


Sample project example

Dependencies information

    "keycloak-js": "^19.0.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^6.3.0",
    "react-scripts": "5.0.1",
    "universal-cookie": "^4.0.4"
Enter fullscreen mode Exit fullscreen mode

index.js

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

ReactDOM.render(
  <HashRouter>
    <App />
  </HashRouter>,
  document.getElementById('root')
);

Enter fullscreen mode Exit fullscreen mode

App.js

import './App.css';
import { Route, Routes, Navigate, Link } from 'react-router-dom';
import NotFound from './NotFound';
import components from './page';
import appRoutes from './appRoutes';

const { Login } = components;

function App() {
  return (
    <>
      <div style={{ display: 'flex', gap: '10px' }}>
        <Link to={'/login'}>Login</Link>
        <Link to={'/a'}>A</Link>
        <Link to={'/b'}>B</Link>
        <Link to={'/c'}>C</Link>
      </div>
      <hr />
      <Routes element>
        <Route path='/' element={<Navigate to={'/login'} />} />
        <Route path='login' element={<Login />} />
        {appRoutes}
        <Route path='*' element={<NotFound />} />
      </Routes>
    </>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

appRoutes.js

import { Route, Outlet, useLocation, useNavigate } from 'react-router-dom';
import components from './page';
import Cookies from 'universal-cookie';
import keycloak from './keyclock';

const { A, A1, A2, A3, B, C } =
  components;

const cookie = new Cookies();

const publicPath = ['/a', '/a/a1'];

const SecureRoutes = () => {
  const isGuestUser = JSON.parse(cookie.get('isGuest'));
  const location = useLocation();
  const navigate = useNavigate();

  if (!isGuestUser) {
    keycloak
      .init({ onLoad: 'login-required', responseMode: 'query' })
      .then((authenticated) => {
        if (authenticated) {
          cookie.set('isGuest', false);
        } else {
          cookie.set('isGuest', true);
        }
      })
      .catch((error) => {
        console.error('Failed to initialize Keycloak', error);
      });
  } else if (!publicPath.includes(location.pathname)) {
    alert('As guest you cannot access this ');
    console.log({ navigate });
  }

  return (
    <>
      <div>
        <div>Is Guest:{isGuestUser ? 'yes' : 'No'}</div>
        {!isGuestUser && (
          <button
            onClick={() =>
              keycloak.logout({ 
              //redirectUri:<URL to go when logout>
              redirectUri: 'http://localhost:3000/'
              })
            }
          >
            Logout
          </button>
        )}
      </div>
      <hr />
      <Outlet />
    </>
  );
};

const appRoutes = (
  <>
    <Route element={<SecureRoutes />}>
      <Route path='/a'>
        <Route index element={<A />} />
        <Route path='a1' element={<A1 />} />
        <Route path='a2' element={<A2 />} />
        <Route path='a3' element={<A3 />} />
      </Route>
      <Route path={'/b'} element={<B />} />
      <Route path='/c' element={<C />} />
    </Route>
  </>
);

export default appRoutes;

Enter fullscreen mode Exit fullscreen mode

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

While many AI coding tools operate as simple command-response systems, Qodo Gen 1.0 represents the next generation: autonomous, multi-step problem-solving agents that work alongside you.

Read full post →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

đź‘‹ Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay