admin管理员组

文章数量:1025526

I'm implementing authentication using Keycloak in React js app.

I'm using React Context to manage the global states in this case are the keycloackValue and authenticated in KeycloackContext.

Cases:

  1. When the app is running the first time, the app checks for keycloackValue and authenticated. The initial state for them are null and false.
  2. If keycloackValue and authenticated are null and false, the app would initialize the keycloak login page (by calling keycloak.init in KeycloackContext).
  3. If keycloackValue and authenticated are not null and true (means that the user is successfully login through keycloak), then the app will render all ponents in MyApp.js.
  4. If the user clicks the log out button in Header ponent, the app would set keycloackValue and authenticated into null and false also call the keycloak to log out the user. After that, the keycloak login page is called.

Problem:

I successfully logged in using keycloak. Then the app successfully rendered all ponents in MyApp.js.

The problem is when I clicked the log out button in Header.js, the keycloackValue and authenticated were successfully set to null and false also the keycloak successfully logged out. Then the app refreshed itself and rendered all ponents in MyApp.js (the app didn't call the keycloak login page).

Code:

index.js

import React from "react";
import ReactDOM from "react-dom";
import MyApp from './my/App'
import { KeycloackContextProvider } from "./my/contexts/KeycloackContext"
 
ReactDOM.render(
    <KeycloackContextProvider>
        <MyApp/>
    </KeycloackContextProvider>,
    document.getElementById("root")
);

KeycloackContext.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            checkLoginIframe: false,
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

MyApp.js

import React, { useContext } from 'react'
import {BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom'

import Header from './ponents/Header/Header'
import Tab from './ponents/Tab/Tab'

// CONTEXTS
import { KeycloackContext } from './contexts/KeycloackContext'

import Device from './pages/Device/Device'
import Stock from './pages/Stock/Stock'

const MyApp = () => {
    const { keycloackValue, authenticated } = useContext(KeycloackContext)

    return (
        (keycloackValue && authenticated) &&
        <div className='app-root'>
            <Router>
                <Header/>
                <Tab/>

                <Redirect from='/' to='/device'/>
                <Switch>
                    <Route exact path='/device'>
                        <Device/>
                    </Route>
                    <Route exact path='/stock'>
                        <Stock/>
                    </Route>
                </Switch>
            </Router>
        </div>
    )
}

export default MyApp

Header.js

import React, { useContext } from 'react'

// CONTEXTS
import { KeycloackContext } from '../../contexts/KeycloackContext'

const Header = () => {
    const { logout } = useContext(KeycloackContext)

    return (
        <div className='logout-popup-root'>
            <p className='logout-popup-username'>Username</p>
            <p className='logout-popup-email'>[email protected]</p>
            <div className='logout-popup-divider'></div>
            <div 
                className='logout-popup-logout-button'
                onClick={() => logout()}
            >
                Log Out
            </div>
        </div>
    )
}

export default Header

Related dependencies:

"keycloak-js": "^15.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"react-scripts": "3.2.0",

Note:

  1. I tried to use this code yesterday in another app. The app was fine (everything was running as I want). I don't know why this time the code was not running as the previous app.
  2. If this question is not clear enough, please let me know. I will update is as soon as possible.

Update:

  1. In the previous app (yesterday app), if I clicked the logout button, the app would refresh one time (from keycloak) and the keycloak login page appeared.
  2. In this app (today app), if I clicked the logout button, the app would refresh three times (from keycloak), the keycloak recognized the user is authenticated (keycloackValue and authenticated are not null and true), and the keycloak login page didn't appeared.

I'm implementing authentication using Keycloak in React js app.

I'm using React Context to manage the global states in this case are the keycloackValue and authenticated in KeycloackContext.

Cases:

  1. When the app is running the first time, the app checks for keycloackValue and authenticated. The initial state for them are null and false.
  2. If keycloackValue and authenticated are null and false, the app would initialize the keycloak login page (by calling keycloak.init in KeycloackContext).
  3. If keycloackValue and authenticated are not null and true (means that the user is successfully login through keycloak), then the app will render all ponents in MyApp.js.
  4. If the user clicks the log out button in Header ponent, the app would set keycloackValue and authenticated into null and false also call the keycloak to log out the user. After that, the keycloak login page is called.

Problem:

I successfully logged in using keycloak. Then the app successfully rendered all ponents in MyApp.js.

The problem is when I clicked the log out button in Header.js, the keycloackValue and authenticated were successfully set to null and false also the keycloak successfully logged out. Then the app refreshed itself and rendered all ponents in MyApp.js (the app didn't call the keycloak login page).

Code:

index.js

import React from "react";
import ReactDOM from "react-dom";
import MyApp from './my/App'
import { KeycloackContextProvider } from "./my/contexts/KeycloackContext"
 
ReactDOM.render(
    <KeycloackContextProvider>
        <MyApp/>
    </KeycloackContextProvider>,
    document.getElementById("root")
);

KeycloackContext.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            checkLoginIframe: false,
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

MyApp.js

import React, { useContext } from 'react'
import {BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom'

import Header from './ponents/Header/Header'
import Tab from './ponents/Tab/Tab'

// CONTEXTS
import { KeycloackContext } from './contexts/KeycloackContext'

import Device from './pages/Device/Device'
import Stock from './pages/Stock/Stock'

const MyApp = () => {
    const { keycloackValue, authenticated } = useContext(KeycloackContext)

    return (
        (keycloackValue && authenticated) &&
        <div className='app-root'>
            <Router>
                <Header/>
                <Tab/>

                <Redirect from='/' to='/device'/>
                <Switch>
                    <Route exact path='/device'>
                        <Device/>
                    </Route>
                    <Route exact path='/stock'>
                        <Stock/>
                    </Route>
                </Switch>
            </Router>
        </div>
    )
}

export default MyApp

Header.js

import React, { useContext } from 'react'

// CONTEXTS
import { KeycloackContext } from '../../contexts/KeycloackContext'

const Header = () => {
    const { logout } = useContext(KeycloackContext)

    return (
        <div className='logout-popup-root'>
            <p className='logout-popup-username'>Username</p>
            <p className='logout-popup-email'>[email protected]</p>
            <div className='logout-popup-divider'></div>
            <div 
                className='logout-popup-logout-button'
                onClick={() => logout()}
            >
                Log Out
            </div>
        </div>
    )
}

export default Header

Related dependencies:

"keycloak-js": "^15.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"react-scripts": "3.2.0",

Note:

  1. I tried to use this code yesterday in another app. The app was fine (everything was running as I want). I don't know why this time the code was not running as the previous app.
  2. If this question is not clear enough, please let me know. I will update is as soon as possible.

Update:

  1. In the previous app (yesterday app), if I clicked the logout button, the app would refresh one time (from keycloak) and the keycloak login page appeared.
  2. In this app (today app), if I clicked the logout button, the app would refresh three times (from keycloak), the keycloak recognized the user is authenticated (keycloackValue and authenticated are not null and true), and the keycloak login page didn't appeared.
Share Improve this question edited Aug 5, 2021 at 4:13 Jabal Logian asked Aug 5, 2021 at 3:50 Jabal LogianJabal Logian 2,3606 gold badges27 silver badges55 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

After trying and debugging for some days, finally I found the solution.

Just ment or remove checkLoginIframe: false in KeycloackContext.js. It fix the logout problem.

Keycloack.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            // checkLoginIframe: false, // remove checkLoginIframe here
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

I'm implementing authentication using Keycloak in React js app.

I'm using React Context to manage the global states in this case are the keycloackValue and authenticated in KeycloackContext.

Cases:

  1. When the app is running the first time, the app checks for keycloackValue and authenticated. The initial state for them are null and false.
  2. If keycloackValue and authenticated are null and false, the app would initialize the keycloak login page (by calling keycloak.init in KeycloackContext).
  3. If keycloackValue and authenticated are not null and true (means that the user is successfully login through keycloak), then the app will render all ponents in MyApp.js.
  4. If the user clicks the log out button in Header ponent, the app would set keycloackValue and authenticated into null and false also call the keycloak to log out the user. After that, the keycloak login page is called.

Problem:

I successfully logged in using keycloak. Then the app successfully rendered all ponents in MyApp.js.

The problem is when I clicked the log out button in Header.js, the keycloackValue and authenticated were successfully set to null and false also the keycloak successfully logged out. Then the app refreshed itself and rendered all ponents in MyApp.js (the app didn't call the keycloak login page).

Code:

index.js

import React from "react";
import ReactDOM from "react-dom";
import MyApp from './my/App'
import { KeycloackContextProvider } from "./my/contexts/KeycloackContext"
 
ReactDOM.render(
    <KeycloackContextProvider>
        <MyApp/>
    </KeycloackContextProvider>,
    document.getElementById("root")
);

KeycloackContext.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            checkLoginIframe: false,
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

MyApp.js

import React, { useContext } from 'react'
import {BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom'

import Header from './ponents/Header/Header'
import Tab from './ponents/Tab/Tab'

// CONTEXTS
import { KeycloackContext } from './contexts/KeycloackContext'

import Device from './pages/Device/Device'
import Stock from './pages/Stock/Stock'

const MyApp = () => {
    const { keycloackValue, authenticated } = useContext(KeycloackContext)

    return (
        (keycloackValue && authenticated) &&
        <div className='app-root'>
            <Router>
                <Header/>
                <Tab/>

                <Redirect from='/' to='/device'/>
                <Switch>
                    <Route exact path='/device'>
                        <Device/>
                    </Route>
                    <Route exact path='/stock'>
                        <Stock/>
                    </Route>
                </Switch>
            </Router>
        </div>
    )
}

export default MyApp

Header.js

import React, { useContext } from 'react'

// CONTEXTS
import { KeycloackContext } from '../../contexts/KeycloackContext'

const Header = () => {
    const { logout } = useContext(KeycloackContext)

    return (
        <div className='logout-popup-root'>
            <p className='logout-popup-username'>Username</p>
            <p className='logout-popup-email'>[email protected]</p>
            <div className='logout-popup-divider'></div>
            <div 
                className='logout-popup-logout-button'
                onClick={() => logout()}
            >
                Log Out
            </div>
        </div>
    )
}

export default Header

Related dependencies:

"keycloak-js": "^15.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"react-scripts": "3.2.0",

Note:

  1. I tried to use this code yesterday in another app. The app was fine (everything was running as I want). I don't know why this time the code was not running as the previous app.
  2. If this question is not clear enough, please let me know. I will update is as soon as possible.

Update:

  1. In the previous app (yesterday app), if I clicked the logout button, the app would refresh one time (from keycloak) and the keycloak login page appeared.
  2. In this app (today app), if I clicked the logout button, the app would refresh three times (from keycloak), the keycloak recognized the user is authenticated (keycloackValue and authenticated are not null and true), and the keycloak login page didn't appeared.

I'm implementing authentication using Keycloak in React js app.

I'm using React Context to manage the global states in this case are the keycloackValue and authenticated in KeycloackContext.

Cases:

  1. When the app is running the first time, the app checks for keycloackValue and authenticated. The initial state for them are null and false.
  2. If keycloackValue and authenticated are null and false, the app would initialize the keycloak login page (by calling keycloak.init in KeycloackContext).
  3. If keycloackValue and authenticated are not null and true (means that the user is successfully login through keycloak), then the app will render all ponents in MyApp.js.
  4. If the user clicks the log out button in Header ponent, the app would set keycloackValue and authenticated into null and false also call the keycloak to log out the user. After that, the keycloak login page is called.

Problem:

I successfully logged in using keycloak. Then the app successfully rendered all ponents in MyApp.js.

The problem is when I clicked the log out button in Header.js, the keycloackValue and authenticated were successfully set to null and false also the keycloak successfully logged out. Then the app refreshed itself and rendered all ponents in MyApp.js (the app didn't call the keycloak login page).

Code:

index.js

import React from "react";
import ReactDOM from "react-dom";
import MyApp from './my/App'
import { KeycloackContextProvider } from "./my/contexts/KeycloackContext"
 
ReactDOM.render(
    <KeycloackContextProvider>
        <MyApp/>
    </KeycloackContextProvider>,
    document.getElementById("root")
);

KeycloackContext.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            checkLoginIframe: false,
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

MyApp.js

import React, { useContext } from 'react'
import {BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom'

import Header from './ponents/Header/Header'
import Tab from './ponents/Tab/Tab'

// CONTEXTS
import { KeycloackContext } from './contexts/KeycloackContext'

import Device from './pages/Device/Device'
import Stock from './pages/Stock/Stock'

const MyApp = () => {
    const { keycloackValue, authenticated } = useContext(KeycloackContext)

    return (
        (keycloackValue && authenticated) &&
        <div className='app-root'>
            <Router>
                <Header/>
                <Tab/>

                <Redirect from='/' to='/device'/>
                <Switch>
                    <Route exact path='/device'>
                        <Device/>
                    </Route>
                    <Route exact path='/stock'>
                        <Stock/>
                    </Route>
                </Switch>
            </Router>
        </div>
    )
}

export default MyApp

Header.js

import React, { useContext } from 'react'

// CONTEXTS
import { KeycloackContext } from '../../contexts/KeycloackContext'

const Header = () => {
    const { logout } = useContext(KeycloackContext)

    return (
        <div className='logout-popup-root'>
            <p className='logout-popup-username'>Username</p>
            <p className='logout-popup-email'>[email protected]</p>
            <div className='logout-popup-divider'></div>
            <div 
                className='logout-popup-logout-button'
                onClick={() => logout()}
            >
                Log Out
            </div>
        </div>
    )
}

export default Header

Related dependencies:

"keycloak-js": "^15.0.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"react-scripts": "3.2.0",

Note:

  1. I tried to use this code yesterday in another app. The app was fine (everything was running as I want). I don't know why this time the code was not running as the previous app.
  2. If this question is not clear enough, please let me know. I will update is as soon as possible.

Update:

  1. In the previous app (yesterday app), if I clicked the logout button, the app would refresh one time (from keycloak) and the keycloak login page appeared.
  2. In this app (today app), if I clicked the logout button, the app would refresh three times (from keycloak), the keycloak recognized the user is authenticated (keycloackValue and authenticated are not null and true), and the keycloak login page didn't appeared.
Share Improve this question edited Aug 5, 2021 at 4:13 Jabal Logian asked Aug 5, 2021 at 3:50 Jabal LogianJabal Logian 2,3606 gold badges27 silver badges55 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

After trying and debugging for some days, finally I found the solution.

Just ment or remove checkLoginIframe: false in KeycloackContext.js. It fix the logout problem.

Keycloack.js

import React, { createContext, useState, useEffect } from 'react'

// KEYCLOACK
import Keycloak from 'keycloak-js'

const KeycloackContext = createContext()

const KeycloackContextProvider = (props) => {
    const [ keycloackValue, setKeycloackValue ] = useState(null)
    const [ authenticated, setAuthenticated ] = useState(false)

    const setKeycloack = () => {
        const keycloak = Keycloak({
            realm: process.env.REACT_APP_WULING_KEYCLOAK_REALM,
            url: process.env.REACT_APP_WULING_KEYCLOAK_URL,
            clientId: process.env.REACT_APP_WULING_KEYCLOAK_CLIENTID,
        })

        keycloak.init({
            onLoad: 'login-required', 
            // checkLoginIframe: false, // remove checkLoginIframe here
        }).then(authenticated => {
            setKeycloackValue(keycloak)
            setAuthenticated(authenticated)
        })
    }

    const logout = () => {
        setKeycloack(null)
        setAuthenticated(false)
        keycloackValue.logout()
    }

    useEffect(() => {
        setKeycloack()
    }, [])

    return (
        <KeycloackContext.Provider
            value={{
                keycloackValue,
                authenticated,
                logout
            }}
        >
            {props['children']}
        </KeycloackContext.Provider>
    )
}

export { KeycloackContextProvider, KeycloackContext }

本文标签: javascriptProblem in log out user using Keycloack in React js appStack Overflow