keycloak Single-sign-on not working with react application

Viewed 3884

If the keycloak user used by my react application is already signed in via another application then it shouldn't ask for authentication again via my react application (since SSO).how can i achieve this ??please provide solution to it.

i am using keycloak to authenticate a react application.keycloak authentication is working fine.tried with single-sign-on but its not working.i want that react application to work with keycloak single-sign-on i.e when keycloak user is loginned it should not ask again for login credentials.react application should work with single-sign-on.how can i achieve this ??please provide solution to it.

below is my keycloak.json

     {
       "realm": "Google-Auth",
       "auth-server-url": "http://localhost:8180/auth",
       "ssl-required": "external",
       "resource": "googledemo",
       "public-client": true,
       "confidential-port": 0
     }

below is secured.js

    `import React, { Component } from 'react';
      import UserInfo from './UserInfo';
     import Logout from './Logout';
     import Keycloak from 'keycloak-js';

     class Secured extends Component {

       constructor(props) {
         super(props);
         this.state = { keycloak: null, authenticated: false };
       }

       componentDidMount() {
         const keycloak = Keycloak('/keycloak.json');
         keycloak.init({onLoad: 'login-required'}).then(authenticated => {
           this.setState({ keycloak: keycloak, authenticated: authenticated })
         })
       }

       render() {
         if(this.state.keycloak) {
           if(this.state.authenticated) return (
             <div>
               <p>
                 This is a Keycloak-secured component of your application. You shouldn't be able to                   
        unless you've authenticated with Keycloak.
      </p>
      <UserInfo keycloak={this.state.keycloak} />
      <Logout keycloak={this.state.keycloak} />
    </div>
  ); else return (<div>Unable to authenticate!</div>)
}
return (
  <div>Initializing Keycloak...</div>
);
       }
     }

     export default Secured;
1 Answers

I have come across a similar scenario. I used the same keycloak-js package as well. Instead of using that in component, you can try to create a service from it

import Keycloak from "keycloak-js";

const _kc = new Keycloak('/keycloak.json');

/**
 * Initializes Keycloak instance and calls the provided callback function if successfully authenticated.
 *
 * @param onAuthenticatedCallback
 */
const initKeycloak = (onAuthenticatedCallback) => {
  _kc.init({
    onLoad: 'check-sso',
    silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
    pkceMethod: 'S256',
  })
    .then((authenticated) => {
      if (authenticated) {
      onAuthenticatedCallback();
      } else {
        doLogin();
      }
    })
};

const doLogin = _kc.login;

const doLogout = _kc.logout;

const getToken = () => _kc.token;

const isLoggedIn = () => !!_kc.token;

const updateToken = (successCallback) =>
  _kc.updateToken(5)
    .then(successCallback)
    .catch(doLogin);

const getUsername = () => _kc.tokenParsed?.preferred_username;

const hasRole = (roles) => roles.some((role) => _kc.hasRealmRole(role));

const UserService = {
  initKeycloak,
  doLogin,
  doLogout,
  isLoggedIn,
  getToken,
  updateToken,
  getUsername,
  hasRole,
};

export default UserService;

And then use the index to initiate this keycloak service and pass the render of your application as a call back.

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import HttpService from "./services/HttpService";
import UserService from "./services/UserService";

const renderApp = () => ReactDOM.render(<App/>, document.getElementById("app"));

UserService.initKeycloak(renderApp);
HttpService.configure();

Related