KeyCloak OAuth2 + React JS Integration

Today, we will see how I integrated KeyCloak’s OAuth2 authentication with my React JS application. For those who don’t know (like me before doing this exercise), KeyCloak is a server that provides OAuth2 authentication very easily. We don’t need to worry about the hassles of setting up authentication manually. We simply use their APIs in the frontend to easily authenticate to our application. In this article, we will do the following: Create a KeyCloak server Create a Client configuration in the KeyCloak server Scaffold a Vite JS Project to write a React JS application Use the keycloak-js frontend library to authenticate to the Keycloak server Please note that I am not going to set up a “production” grade system here. This will be a very simple setup that helps us understand how to easily connect the client and server and get going. You may download the source code of this app from my GitHub repo: https://github.com/anushibin007/keycloak-vite-demo Step 1: Create a KeyCloak server To create a KeyCloak server, let’s use their official Docker image. Let’s write a docker compose file to make things easier to maintain. We need a keycloak application server and a db to persist the state. To do that, put the following items into a docker-compose.yml file: # docker-compose.yml services: keycloak-mysql: container_name: keycloak-mysql image: mysql:8 volumes: - keycloak-db-vol:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: keycloak MYSQL_USER: keycloak MYSQL_PASSWORD: password keycloak-server: container_name: keycloak image: quay.io/keycloak/keycloak:24.0.1 command: ["start-dev", "--import-realm"] environment: DB_VENDOR: MYSQL DB_ADDR: mysql DB_DATABASE: keycloak DB_USER: keycloak DB_PASSWORD: password KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin ports: - "8181:8080" volumes: - keycloak-server-vol:/opt/keycloak/data/import/ depends_on: - keycloak-mysql volumes: keycloak-db-vol: keycloak-server-vol: Start the compose by running docker compose up -d You should now be able to access the keycloak server at http://localhost:8181/ with the credentials mentioned above (username and password are both admin) Step 2: Create a Client in the KeyCloak server I hope you are logged in to the KeyCloak admin portal (at http://localhost:8181/admin/master/console/) Now, go to the “Clients” section on the left pane Click on “Create client” In the “General settings” step, the client type should be “OpenID Connect” Give the the Client ID as “vite-frontend” Click Next Now you are in the “Capability config” step Enable only the “Standard flow” option. Disable everything else. This is very important. Click Next Now you are in the “Login settings” step Fill the “Valid redirect URIs” as http://localhost:* Fill the “Web origins” as * Click “Save” Let’s allow user registration from the frontend. For that, In the KeyCloak admin portal, go to “Realm settings” from the left pane Then go to the “Login” tab Then enable the following items: User registration Forgot password Remember me Email as username The KeyCloak server is now completely set up. Let’s move on to the frontend. Step 3: Create a React JS application Let’s create a React JS application using the Vite JS scaffold. Run the following command: npm create vite@latest keycloak-react-client -- --template react The above command will scaffold a new Vite JS project. Let us now switch to that directory and install the required dependencies and start the dev server # switch to the client application folder cd keycloak-react-client # install the default dependencies npm install # install all the other libraries # required to run the keycloak integration npm install --save keycloak-js @react-keycloak/web react-router-dom # start the dev server npm run dev Now the frontend application should be running although it will just be showing a dummy application at http://localhost:5173 Step 4: Use the keycloak-js frontend library to authenticate to the Keycloak server The base is now laid. Let us now add business code to the frontend. Let us start with a simple login button // src/Login.jsx import { useKeycloak } from "@react-keycloak/web"; export default function Login() { const { keycloak } = useKeycloak(); return ( keycloak.login()}>Login ); } Now we will create a “secure” page that only logged in users can visit // src/SecurePage.jsx import { useKeycloak } from "@react-keycloak/web"; export default function SecurePage() { const { keycloak } = useKeycloak(); return ( Welcome, {keycloak.tokenParsed.e

Apr 29, 2025 - 10:23
 0
KeyCloak OAuth2 + React JS Integration

Image description

Today, we will see how I integrated KeyCloak’s OAuth2 authentication with my React JS application.

For those who don’t know (like me before doing this exercise), KeyCloak is a server that provides OAuth2 authentication very easily. We don’t need to worry about the hassles of setting up authentication manually. We simply use their APIs in the frontend to easily authenticate to our application.

In this article, we will do the following:

  1. Create a KeyCloak server
  2. Create a Client configuration in the KeyCloak server
  3. Scaffold a Vite JS Project to write a React JS application
  4. Use the keycloak-js frontend library to authenticate to the Keycloak server

Please note that I am not going to set up a “production” grade system here. This will be a very simple setup that helps us understand how to easily connect the client and server and get going.

You may download the source code of this app from my GitHub repo: https://github.com/anushibin007/keycloak-vite-demo

Step 1: Create a KeyCloak server

To create a KeyCloak server, let’s use their official Docker image.

  1. Let’s write a docker compose file to make things easier to maintain. We need a keycloak application server and a db to persist the state. To do that, put the following items into a docker-compose.yml file:
# docker-compose.yml
services:
    keycloak-mysql:
        container_name: keycloak-mysql
        image: mysql:8
        volumes:
            - keycloak-db-vol:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: keycloak
            MYSQL_USER: keycloak
            MYSQL_PASSWORD: password
    keycloak-server:
        container_name: keycloak
        image: quay.io/keycloak/keycloak:24.0.1
        command: ["start-dev", "--import-realm"]
        environment:
            DB_VENDOR: MYSQL
            DB_ADDR: mysql
            DB_DATABASE: keycloak
            DB_USER: keycloak
            DB_PASSWORD: password
            KEYCLOAK_ADMIN: admin
            KEYCLOAK_ADMIN_PASSWORD: admin
        ports:
            - "8181:8080"
        volumes:
            - keycloak-server-vol:/opt/keycloak/data/import/
        depends_on:
            - keycloak-mysql

volumes:
    keycloak-db-vol:
    keycloak-server-vol:
  1. Start the compose by running docker compose up -d

  2. You should now be able to access the keycloak server at http://localhost:8181/ with the credentials mentioned above (username and password are both admin)

Step 2: Create a Client in the KeyCloak server

  1. I hope you are logged in to the KeyCloak admin portal (at http://localhost:8181/admin/master/console/)
  2. Now, go to the “Clients” section on the left pane
  3. Click on “Create client”
  4. In the “General settings” step, the client type should be “OpenID Connect”
  5. Give the the Client ID as “vite-frontend”
  6. Click Next
  7. Now you are in the “Capability config” step
  8. Enable only the “Standard flow” option. Disable everything else. This is very important.
  9. Click Next
  10. Now you are in the “Login settings” step
  11. Fill the “Valid redirect URIs” as http://localhost:*
  12. Fill the “Web origins” as *
  13. Click “Save”

Let’s allow user registration from the frontend. For that,

  1. In the KeyCloak admin portal, go to “Realm settings” from the left pane
  2. Then go to the “Login” tab
  3. Then enable the following items:
  4. User registration
  5. Forgot password
  6. Remember me
  7. Email as username
  8. The KeyCloak server is now completely set up. Let’s move on to the frontend.

Step 3: Create a React JS application

Let’s create a React JS application using the Vite JS scaffold.

  1. Run the following command:
npm create vite@latest keycloak-react-client -- --template react
  1. The above command will scaffold a new Vite JS project. Let us now switch to that directory and install the required dependencies and start the dev server
# switch to the client application folder
cd keycloak-react-client

# install the default dependencies
npm install

# install all the other libraries
# required to run the keycloak integration
npm install --save keycloak-js @react-keycloak/web react-router-dom

# start the dev server
npm run dev
  1. Now the frontend application should be running although it will just be showing a dummy application at http://localhost:5173

Step 4: Use the keycloak-js frontend library to authenticate to the Keycloak server

The base is now laid. Let us now add business code to the frontend.

  1. Let us start with a simple login button
// src/Login.jsx
import { useKeycloak } from "@react-keycloak/web";

export default function Login() {
    const { keycloak } = useKeycloak();

    return (
        <div className="login">
            <button onClick={() => keycloak.login()}>Loginbutton>
        div>
    );
}
  1. Now we will create a “secure” page that only logged in users can visit
// src/SecurePage.jsx
import { useKeycloak } from "@react-keycloak/web";

export default function SecurePage() {
    const { keycloak } = useKeycloak();
    return (
        <div className="secure-page">
            <p>Welcome, {keycloak.tokenParsed.email}p>
            <p>Your access token (keep it safe!): {keycloak.token}p>
        div>
    );
}
  1. Let us now create a “SecurityGuy” component that will act as a a guard to either let us in or not
// src/SecurityGuy.jsx
import { useKeycloak } from "@react-keycloak/web";
import Login from "./Login";

export default function SecurityGuy({ children }) {
    const { keycloak } = useKeycloak();

    const isLoggedIn = keycloak.authenticated;

    return isLoggedIn ? children : <Login />;
}

What we are essentially doing here is, if we are logged in, we show the children components (check the next point to understand this concept) or else, we just show the Login page with the login button.

  1. Let us now add routes and config to our App.jsx file:
// src/App.jsx
import React from "react";
import { ReactKeycloakProvider } from "@react-keycloak/web";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import "./App.css";
import SecurityGuy from "./SecurityGuy";
import SecurePage from "./SecurePage";
import Keycloak from "keycloak-js";

const keycloak = new Keycloak({
    url: "http://localhost:8181",
    realm: "master",
    clientId: "vite-frontend",
});

function App() {
    return (
        <ReactKeycloakProvider authClient={keycloak}>
            <BrowserRouter>
                <Routes>
                    <Route
                        path="/"
                        element={
                            <SecurityGuy>
                                <SecurePage />
                            SecurityGuy>
                        }
                    />
                Routes>
            BrowserRouter>
        ReactKeycloakProvider>
    );
}

export default App;

Note that the highlighted section might vary for you if you are changing ports, etc. If you are strictly following this tutorial, then you can simply copy paste that code as it is.

Also, if you see in the above code, the SecurityGuy is kinda “guarding” the secure page. That is, only if we are logged in, we see the items inside the secure page. Else, we see the Login button.

  1. Finally, remove the “Strict mode” in main.jsx so that you don’t get any multiple-initialization errors. The exact error message is: “A ‘Keycloak’ instance can only be initialized once.“

I couldn’t figure out the “proper” way to fix this issue. If you know, please let me know. For now, let’s do this “hack”. I have removed the tags from the main.jsx file to disable “Strict mode”.

// src/main.jsx
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.jsx";

createRoot(document.getElementById("root")).render(<App />);

Test the authentication

  1. Access your frontend application at http://localhost:5173/
  2. You should see just the Login button because you are not logged in
  3. Click on the “Login” button
  4. This should take you to the KeyCloak login page
  5. Since we do not have any application users, let’s create one by clicking on the “Register” button
  6. Fill the mandatory fields with some dummy data and click on the “Register” button
  7. You should be logged in now and see an authentication token that was returned from the KeyCloak server

Homework

Try to implement a simple logout button to logout the user after you are logged in