简体   繁体   中英

How can I use Keycloak in Next.js?

I'm trying to authenticate in Keycloak in Next.js using @react-keycloak/nextjs but once I pass the login it keeps sending me back to the Keycloak server and returning to the main page until it gives me an error because my token key is expired. This is my _app.js :

import { ApolloProvider } from '@apollo/react-hooks'
import CssBaseline from '@material-ui/core/CssBaseline'
import { ThemeProvider } from '@material-ui/core/styles'
import { Persistors, SSRKeycloakProvider } from '@react-keycloak/nextjs'
import Layout from 'components/layout/Layout'
import { useApollo } from 'lib/apolloClient'
import KeycloakLoading from 'components/KeycloakLoading'
import {
  keycloakCfg,
  keycloakProviderInitConfig,
  onKeycloakLogout,
  onKeycloakTokens,
} from 'lib/keycloak'
import Head from 'next/head'
import PropTypes from 'prop-types'
import React from 'react'
import theme from 'styles/theme'
import 'leaflet/dist/leaflet.css'
import 'react-leaflet-markercluster/dist/styles.min.css'
import 'styles/styles.css'
import 'styles/animations.css'
import '../styles/globals.css'

// export function reportWebVitals(metric) {
//   // These metrics can be sent to any analytics service
//   console.log(metric)
// }

export default function MyApp(props) {
  const { Component, pageProps, cookies } = props

  const apolloClient = useApollo(pageProps.initialApolloState)

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side')
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles)
    }
  }, [])

  return (
    <React.Fragment>
      <Head>
        <title>My page</title>
        <meta
          name="viewport"
          content="minimum-scale=1, initial-scale=1, width=device-width"
        />
      </Head>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <SSRKeycloakProvider
          keycloakConfig={keycloakCfg}
          persistor={Persistors.Cookies(cookies)}
          initConfig={keycloakProviderInitConfig}
          onTokens={onKeycloakTokens}
          onAuthLogout={onKeycloakLogout}
          LoadingComponent={
            <React.Fragment>
              <KeycloakLoading />
            </React.Fragment>
          }
        >
          <ApolloProvider client={apolloClient}>
            <Layout>
              <Component {...pageProps} />
            </Layout>
          </ApolloProvider>
        </SSRKeycloakProvider>
      </ThemeProvider>
    </React.Fragment>
  )
}

MyApp.propTypes = {
  Component: PropTypes.elementType.isRequired,
  pageProps: PropTypes.object.isRequired,
  cookies: PropTypes.any,
}

And this is my Keycloak configuration

export const keycloakCfg = {
  realm: APP_CONSTANTS.KEYCLOAK_REALM,
  url: `${APP_CONSTANTS.KEYCLOAK_HOST}/auth`,
  clientId: APP_CONSTANTS.KEYCLOAK_CLIENT_ID,
}
export const keycloakProviderInitConfig = {
  onLoad: 'login-required',
}

If anyone could point out what is wrong or alternatively tell me another way to use Keycloak in next.

React-keycloak/nextjs is deprecated in favor of react-keycloak/ssr. I followed the examples here: https://www.npmjs.com/package/@react-keycloak/ssr and was able to fully authenticate without issue.

I'm not sure what is causing your looping issues but it doesn't look like you are using the required cookie parser or passing them into the props via getInitialProps so that may be a good place to start.

An alternative would be: Next-Auth has implemented a keycloak provider which would make your life much easier protecting both Frontend and Backend. Just specify keycloak options/configs in _app.js and you all set.

import {signOut, getSession, useSession } from 'next-auth/react';

export default function Home() {
  let session = useSession();
  console.log(session);
  return (
    <div >
      <button onClick={() => {
        console.log(session);
        signOut();
        console.log(session);
      }}> Sign Out </button>
      <h1>H1 test</h1>
    </div>
  )
}

export const getServerSideProps = async (ctx) => {

  const backendSession = await getSession(ctx)

  console.log(backendSession);
  return {
    props: {

    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM