Keycloak 20.0.3 logout not working in react app (invalid redirect url) - reactjs

I am trying to authenticate my react app using keycloak. The app is not able to successfully logout. I have setup the admin console to contain the post logout redirect url to be http://localhost:7171. The URL that shows on clicking logout button
http://localhost:8080/realms/hype/protocol/openid-connect/logout?client_id=hypeclient&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A7171%2F&id_token_hint=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZRHVhc0pTT0dIOUh2ZnRvZGNhRktmRkxuOEZuWmkzSVN3eVBQenlzazFVIn0.eyJleHAiOjE2NzU1NjU1ODUsImlhdCI6MTY3NTU2NTI4NSwiYXV0aF90aW1lIjoxNjc1NTY1MjcyLCJqdGkiOiI1MjEyODZlZS1hNThiLTRhMTUtYTgyZS1jODU2ZmE4NWVkZTEiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL2h5cGUiLCJhdWQiOiJoeXBlY2xpZW50Iiwic3ViIjoiYzJhZTJiZWYtMjg2ZC00MDgzLTk3YTktMWEyM2YxNzQ4YzE0IiwidHlwIjoiSUQiLCJhenAiOiJoeXBlY2xpZW50Iiwibm9uY2UiOiI3NGUyMTk3Ni0zNzcwLTQzNWEtOTEzMC1lNGU2YWUyY2I4ZTIiLCJzZXNzaW9uX3N0YXRlIjoiYzAxZWJlYTEtMjAwYS00YzU3LTg2NTgtNjYyYTdjOTA5OThkIiwiYXRfaGFzaCI6IjNPczlxc0NucFdmYnFuRkNlZ1docmciLCJhY3IiOiIwIiwic2lkIjoiYzAxZWJlYTEtMjAwYS00YzU3LTg2NTgtNjYyYTdjOTA5OThkIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoia2FyYW4gc2hhaCIsInByZWZlcnJlZF91c2VybmFtZSI6ImthcmFuIiwiZ2l2ZW5fbmFtZSI6ImthcmFuIiwiZmFtaWx5X25hbWUiOiJzaGFoIn0.TFCh-dPE4h8HKpAapNv4socR7uAsKDnuVpqLiaZCguu1Vyztn_sUkrbaqFKJDeoIZv3XDzBDM5MezMvyRRkmiRIQTIbiTlYGgcNA5UkcwbeKioaowCWqYqyjG7A3D0lKNjf0MAF6PmWVrPJVbm8hYtQMVDHwWQ2vFTShnmMRJ2iTf4IeT1DDLANrLh3tMXeYMF2f9ZmvtNS72O-BICkD4uXPSyMiqnDgj_52UAdkEaLgkuv31TAYDAeVef-Rly8n7K5LG1MWytB2_-WrhwXwfxjymc9RH55Iy-1tvLUFceigO7XwQzffZYK5uJ9PXkbg3hlkr6QLVSXsiu8RYKQu9w
My Setup including the version looks like
Keycloak 20.0.3
Keycloak.js 20.0.3 via npm
react 18.2
App.JS
import React from "react";
import { ReactKeycloakProvider } from "#react-keycloak/web";
import keycloak from "./Keycloak";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Nav from "./components/Nav";
import WelcomePage from "./pages/Homepage";
import SecuredPage from "./pages/Securedpage";
import PrivateRoute from "./helpers/PrivateRoute";
function App() {
return (
<div>
<ReactKeycloakProvider authClient={keycloak}>
<Nav />
<BrowserRouter>
<Routes>
<Route exact path="/" element={<WelcomePage />} />
<Route path="/secured"
element={<PrivateRoute>
<SecuredPage />
</PrivateRoute>}/>
</Routes>
</BrowserRouter>
</ReactKeycloakProvider>
</div>
);
}
export default App;
Nav.JS
import React from "react";
import { useKeycloak } from "#react-keycloak/web";
const Nav = () => {
const { keycloak, initialized } = useKeycloak();
function loginHelper(){
console.log("login clicked");
keycloak.login();
};
function logoutHelper(){
console.log("login clicked");
keycloak.logout();
};
return (
<div>
<div className="top-0 w-full flex flex-wrap">
<section className="x-auto">
<nav className="flex justify-between bg-gray-200 text-blue-800 w-screen">
<div className="px-5 xl:px-12 py-6 flex w-full items-center">
<h1 className="text-3xl font-bold font-heading">
Keycloak React AUTH.
</h1>
<ul className="hidden md:flex px-4 mx-auto font-semibold font-heading space-x-12">
<li>
<a className="hover:text-blue-800" href="/">
Home
</a>
</li>
<li>
<a className="hover:text-blue-800" href="/secured">
Secured Page
</a>
</li>
</ul>
<div className="hidden xl:flex items-center space-x-5">
<div className="hover:text-gray-200">
{!keycloak.authenticated && (
<button
type="button"
className="text-blue-800"
onClick={() => loginHelper()}
>
Login
</button>
)}
{!!keycloak.authenticated && (
<button
type="button"
className="text-blue-800"
onClick={() => logoutHelper()}
>
Logout ({keycloak.tokenParsed.preferred_username})
</button>
)}
</div>
</div>
</div>
</nav>
</section>
</div>
</div>
);
};
export default Nav;
Keycloak.JS
import Keycloak from "keycloak-js";
const keycloak = new Keycloak({
url: "http://localhost:8080",
realm: "hype",
clientId: "hypeclient",
});
export default keycloak;
PrivateRoute.JS
import { useKeycloak } from "#react-keycloak/web";
const PrivateRoute = ({ children }) => {
const { keycloak } = useKeycloak();
const isLoggedIn = keycloak.authenticated;
console.log("checking auth access " + isLoggedIn);
return isLoggedIn ? children : null;
};
export default PrivateRoute;
I have tried following this link but it does not work. Admin console looks like

Try changing
valid post logout urls to +
valid redirect urls to http://localhost:7171*

Related

White Blank Screen after using import { Link } from "react-router-dom";

This is exactly the code I copied in the video tutorial but I don't know why I got a blank white screen on my browser while the other (original) code doesn't get a blank screen after importing the { Link } from "react-router-dom"; How do you fix this? I can't find any solutions.
Here is my App.js
import React from "react";
import Navbar from "./components/Nav/Navbar";
function App () {
return (
<div>
<Navbar/>
</div>
);
}
export default App;
This is my Navbar.jsx
import React from "react";
import { Link } from "react-router-dom";
import Logo from "../../assets/Logo.png";
const Navbar = () => {
return (
<nav className="bg-white">
<div className="flex items-center font-medium justify-around">
<div>
<img src={Logo} alt="logo" className="md:cursor-pointer" />
</div>
<ul>
<li>
<Link to="/" className="py-7 px-3 inline-block">
Home
</Link>
</li>
</ul>
</div>
</nav>
);
};
export default Navbar;

i want to build sidebar on my own but the function don't work

Sorry for my bad English speak please help me to build a responsive sidebar menu. when i try to build a sidebar menu responsive I reach this type of error : TypeError: document.getElementByClassName is not a function. I haven't an idea where's the error exactly so this is my code of the sidebar menu:
import React from 'react';
import {useEffect} from 'react';
import SideNav, { Toggle, Nav, NavItem, NavIcon, NavText } from '#trendmicro/react-sidenav';
import '#trendmicro/react-sidenav/dist/react-sidenav.css';
import {listProducts} from '../actions/productActions';
import {useSelector, useDispatch} from 'react-redux';
function w3_open() {
document.getElementByClassName("sidebar").style.width = "100%";
document.getElementByClassName("sidebar").style.display = "block";
}
function w3_close() {
document.getElementByClassName("sidebar").style.display = "none";
}
export default function SideBarMenu() {
const dispatch = useDispatch();
useEffect(()=> {
dispatch(listProducts);
}, [])
const productList = useSelector((state) => state.productList);
const {products} = productList;
console.log(products);
return (
<div className="wrapper" >
<div className="section">
<div className="top_navbar">
<div className="hamburger">
<a href="#">
<i className="fa fa-bars" onClick={w3_open(), w3_close()} ><span className="bar-icon"> All products </span></i>
</a>
</div>
</div>
</div>
<div className="sidebar">
profile image & text
menu item
</div>
</div>
)
}
and this is the app.js file :
import React from 'react';
import {BrowserRouter, Routes, Route} from 'react-router-dom';
import HomePage from './Pages/HomePage';
import ProductPage from './Pages/productPage';
import SideBarMenu from './components/SideBarMenu';
function App() {
return (
<BrowserRouter>
<div className="grid-container" >
<header className="row" >
<div>
<a className="brand" href="/">My shop</a>
</div>
<div>
Cart
Sign In
</div>
</header>
<main>
<SideBarMenu ></SideBarMenu>
<Routes>
<Route path='/product/:id' element={<ProductPage /> } />
<Route path='/' element={<HomePage />} exact />
</Routes>
</main>
<footer className="row center" >All right reserved</footer>
</div>
</BrowserRouter>
);
}
export default App;
document.getElementByClassName(...) doesn't exist in JavaScript. You should use document.getElementsByClassName(...) (notice the plural in Elements).
Replace document.getElementByClassName("sidebar") with document.getElementsByClassName("sidebar")[0].
Update
To fix the error that you have right now, I would suggest to use a variable and useState Hook to display or hide the sidebar.
Example:
const [open, setOpen] = useState(false)
const handleSidebar = () => {
setOpen(!open)
}
return(
<div className = "wrapper" >
<div className = "section">
<div className = "top_navbar">
<div className = "hamburger">
<a href = "#">
<i className="fa fa-bars" onClick = {handleSidebar}><span className = "bar-icon"> All products </span></i>
</a>
</div>
</div>
</div>
{ open
? <div className = "sidebar">
profile image & text menu item
</div>
: null
}
</div>
)

getting "Missing required parameter 'client_id'" error in react-google-login

I inserted my client id correctly and it did work
but suddenly it's not working until now even though I didn't change any codes in <GoogleLogin />
Also it works in blank React when I tested but not working in this project
exact error message is Uncaught qw {message: "Missing required parameter 'client_id'", xM: true, stack: "gapi.auth2.ExternallyVisibleError: Missing require…YZKdHMHzzbYNF1G7KSEIjXaBQQw/cb=gapi.loaded_0:1:15"}
import React, { useState } from "react";
import "./CSS/Header.css";
import { BrowserRouter as Router, Link } from "react-router-dom";
import { GoogleLogin } from "react-google-login";
export default function Header() {
const responseGoogle = (response) => {
console.log(response);
};
return (
<Router>
<div id="header">
<div id="id"></div>
<h2 id="header_title">title</h2>
<div id="contents">
<h4 className="content">
<Link
to="/"
onClick={() => {
window.location.href = "/";
}}
>
HOME
</Link>
</h4>
<h4 className="content">
<Link
to="/history"
onClick={() => {
window.location.href = "/history";
}}
>
History
</Link>
</h4>
<GoogleLogin
clientid=[myclientid]
buttonText="Login"
onSuccess={responseGoogle}
isSignedIn={true}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
</div>
</div>
</Router>
);
}
You should use clientId instead of clientid for the prop

React hook issue. Is not re-render one component

I have created a global provider with a reducer that is holding the user state.
When the user login successfully I dispatch and update the state, setting login=true. It is working perfectly in all components except for the top component where is not updating. I don't see any problem. Any idea what might be the problem?
// index.js
import './styles/tailwind.css';
import './styles/index.css';
import React from 'react';
import ReactDOM from 'react-dom';
import {StateProvider } from "./store";
import App from './App';
import * as serviceWorker from './serviceWorker';
const app = (
<StateProvider>
<App />
</StateProvider>
);
ReactDOM.render(app, document.getElementById('root'));
//store.js - the provider that update the state
import React, {createContext, useReducer} from 'react';
const initialState = {
login:false,
token:'',
refreshToken:'',
user:{}
};
const store = createContext(initialState);
const { Provider } = store;
const StateProvider = ( { children } ) => {
const [state, dispatch] = useReducer((state, action) => {
switch(action.type) {
case 'login user':
state.login = true;
state.token = action.token;
state.refreshToken = action.refreshToken;
return state;
default:
throw new Error();
};
}, initialState);
return <Provider value={{ state, dispatch }}>{children}</Provider>;
};
export { store, StateProvider }
//App.js ---- in this page is not working, the rerendering doesn't happend and login remain false only in this component
import React, {useState, useContext, useEffect} from 'react';
import { store } from "./store";
import logo from './svg/book.svg';
import { BrowserRouter, Route, NavLink } from "react-router-dom";
import Classes from './components/school/Classes.js';
import Students from './components/school/Students.js';
import Home from './components/school/Home.js';
import Cards from './components/Cards.js';
import Login from "./components/Login";
function App() {
const globalState = useContext(store);
const login = globalState.state.login;
console.log(globalState);
const message = (login) ? "Welcome user" : "You are not loged in";
return (
<div>
<p>{message}</p>
<BrowserRouter>
<header className="grid grid-cols-1 sm:grid-cols-2">
<div className="flex align-middle"><img src={logo} className="h-12 p-1"></img>Bucharest Hi School
</div>
<div className="flex flex-wrap mr-5">
<NavLink to="/" className="w-full sm:w-1/4 text-center sm:text-right p-2" href="#" >Home</NavLink>
<NavLink to="/classes" className="w-full sm:w-1/4 text-center sm:text-right p-2" href="#" >Classes </NavLink>
<NavLink to="/students" className="w-full sm:w-1/4 text-center sm:text-right p-2" href="#">Students</NavLink>
<NavLink to="/statistics" className="w-full sm:w-1/4 text-center sm:text-right p-2" href="#">Statistics</NavLink>
<NavLink to="/logout" className="w-full sm:w-1/4 text-center sm:text-right bg-black text-white p-2" href="#">Logout</NavLink>
<NavLink to="/login" className="w-full sm:w-1/4 text-center sm:text-center bg-white rounded text-center p-2" href="#">Login</NavLink>
</div>
</header>
<div className="flex w-full flex-wrap justify-center my-10">
<Route exact path="/" component={Home} />
<Route path="/classes" component={Classes} />
<Route path="/students" component={Students} />
<Route path="/login" component={Login} />
</div>
</BrowserRouter>
</div>
);
}
export default App;
Thanks
You are mutating the state and returning same object in the reducer function, due to which your component assumes the data has never been changed.
Please make sure you return new object whenever you update your state, in your case you could use return { ...state }; instead of return state; in your reducer.

React Page Refresh the Whole Page after Clicking on a link

I've just started using reactJS and i am integrating an HTML admin template in react which has header, sidebar, footer and the main section content.
One thing i'm a bit curious is whenever i click links in the main section content, only the specific section dynamically loads, but when i click on links in sidebar the entire page reloads, why is it so? Below is the code that i'm following
App.js
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import Header from './Components/Header';
import Content from './Components/Content';
import Footer from './Components/Footer';
import Sidebar from './Components/Sidebar';
const App = () => {
return(
<BrowserRouter>
<Header/>
<Sidebar/>
<Content/>
<Footer/>
</BrowserRouter>
);
}
export default App;
Header.jsx
import React from 'react';
import logo from '../stack.png';
const Header = () => {
return(
<nav>
</nav>
);
}
export default Header;
Sidebar.jsx
import React from 'react';
import { Link } from 'react-router-dom';
const Sidebar = () => {
return(
<aside>
<div className="main-menu menu-fixed menu-dark menu-accordion menu-shadow" data-scroll-to-active="true">
<div className="main-menu-content">
<ul className="navigation navigation-main" id="main-menu-navigation" data-menu="menu-navigation">
<li style={{'margin': '25px 0 0 0'}} className="active nav-item">
<Link to="/dashboard">
<i className="ft-home"></i>
<span className="menu-title">
Dashboard
</span>
</Link>
</li>
<li className="nav-item"></i><span className="menu-title" data-i18n="">Create</span>
<ul className="menu-content">
<li className=" menu-item">
<Link to="/create">
<span className="menu-title">
Create New
</span>
</Link>
</li>
<li className=" menu-item">
<Link to="/createxyz">
<span className="menu-title">
Create XYZ
</span>
</Link>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
);
}
export default Sidebar;
Content.jsx
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Dashboard from './Dashboard';
import Enter from './Enter';
import Enterxyz from './Enterxyz';
const Content = () => {
return(
<Switch>
<Route exact path="/" component={Dashboard} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/create" component={Enter} />
<Route path="/createxyz" component={Enterxyz} />
</Switch>
);
}
export default Content;
Footer.jsx
import React from 'react';
function Footer()
{
return(
<footer className="footer footer-static footer-light navbar-border">
<p className="clearfix blue-grey lighten-2 text-sm-center mb-0 px-2">
<span className="float-md-left d-block d-md-inline-block">© 2020
<a className="text-bold-800 grey darken-2" href="">
xyz
</a> (All Rights Reserved)
</span>
</p>
</footer>
);
}
export default Footer;
Code snippet in import Enter from './Enter';
import React from 'react';
import { Link } from 'react-router-dom';
const Enter = () => {
return(
<div className="app-content content">
<div className="content-wrapper">
<div className="content-body">
<div className="row">
<div className="col-md-12">
<div className="card" style={{'height': 'auto'}}>
<div className="card-header">
<h4 className="card-title" id="basic-layout-form">Create New Client</h4>
<a className="heading-elements-toggle"><i className="fa fa-ellipsis-v font-medium-3"></i></a>
<div className="heading-elements">
<ul className="list-inline mb-0">
<li><Link to="/dashboard">Dashboard</Link></li>
<li><i className="ft-chevrons-right"></i></li>
<li><a>Create</a></li>
<li><i className="ft-chevrons-right"></i></li>
<li><Link to="/create">Enter New</Link></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Enter;
in the Enter code snippet there are 2 links(Breadcrumbs) when i click on them the page loads dynamically without refresh.
But when i click on the links in sidebar, the entire page reloads to display the content, why is it so? What is wrong?

Resources