2

I have a problem. I need to login in Keycloak, but i don't want to use default pages from Keycloak. I have pages for "sign-in" and "sign-up". I wrote requests and can recieve access token for user, but what i should to do next? I use @react-keycloak/ssr and keycloak-js

This is _app.tsx

import './globals.css';
import '@fortawesome/fontawesome-free/css/all.css'
import Head from 'next/head';
import { Header } from "../shared/components/header/header";
import Footer from "../shared/components/footer/footer";

import cookie from 'cookie';
import type { IncomingMessage } from 'http';
import type { AppContext } from 'next/app';
import { SSRKeycloakProvider, SSRCookies } from '@react-keycloak/ssr';


const keycloakCfg = {
  url: `https://${process.env.AUTH_HOST}/auth`,
  realm: 'myrealm',
  clientId: 'react-client',
}

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

  console.log(cookies);
  const initOptions = {
    onLoad: 'check-sso',
    checkLoginIframe: false,
    flow: 'implicit',
  }

  return (
      <>
        <Head>
          <link rel="preconnect" href="https://fonts.googleapis.com" />
          <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
          <link
            href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700;800&display=swap"
            rel="stylesheet" />
          <link rel="icon" type="image/png" href="/favicon.png" />
        </Head>
        <Header />
        <SSRKeycloakProvider
          keycloakConfig={keycloakCfg}
          persistor={SSRCookies(cookies)}
          initOptions={initOptions}
        >
          <Component {...pageProps} />
        </SSRKeycloakProvider>
        <Footer />
      </>
  );
}

function parseCookies(req?: IncomingMessage) {
  if (!req || !req.headers) {
    return {}
  };
  return cookie.parse(req.headers.cookie || '');
}

MyApp.getInitialProps = async (context: AppContext) => {
  return {
    cookies: parseCookies(context?.ctx?.req),
  }
}

sign-in/index.tsx

import Form from '../../shared/components/form/form';
import styles from './sign-in.module.scss';
import Input from '../../shared/components/input/input';
import Checkbox from '../../shared/components/checkbox/checkbox';
import Button from '../../shared/components/button/button';
import React, { useEffect } from 'react';
import Head from 'next/head';
import { PAGE_TITLES } from '../../shared/constants/titles.const';
import BottomPanel from '../../shared/components/bottom-panel/bottom-panel';
import Link from 'next/link';

import { useKeycloak } from '@react-keycloak/ssr';
import { KeycloakInstance } from 'keycloak-js';
import { useRouter } from 'next/router';
import { getToken } from '../../shared/utils/keycloak-functions';

export default function SignIn() {
  const links = [
    {
      text: 'News',
      url: '/news'
    },
    {
      text: 'Community',
      url: '/news'
    },
    {
      text: 'Development',
      url: '/news'
    }
  ];
  
  // if user is authenticated rediretc to '/'
  const router = useRouter();
  const { keycloak } = useKeycloak<KeycloakInstance>();
  useEffect(() => {
    if (keycloak?.authenticated) router.push('/');
  });
  
  async function login() {
    const tokens = await getToken();
    if (tokens) {
      console.log(tokens);
      router.push('/');
    } 
  }
  
  return (
    <>
      <Head>
        <title>{PAGE_TITLES.signIn}</title>
      </Head>
        <main className={styles.page}>
          <Form>
            <h2 className={styles.heading}>Sign in</h2>
            <label className={styles.formRow}>
              <span className={styles.label}>Email</span>
              <Input name="username"/>
            </label>
            <label className={styles.formRow}>
              <span className={styles.label}>Password</span>
              <Input type="password" name="password"/>
            </label>
            <div className={styles.checkboxOuter}>
              <Checkbox>Remember me</Checkbox>
            </div>
            <br />
            <div className={styles.buttonOuter}>
              <Button action={() => login() }>Login</Button>
            </div>
            <div className={styles.formFooter}>
              <Link href="/sign-up">
                <a>Register</a>
              </Link>
            </div>
          </Form>
          <BottomPanel links={links} />
        </main>
    </>
  );
}

and this is a function getToken

export async function getToken() {
    const tokenEndpoint = `https://localhost/auth/realms/myrealm/protocol/openid-connect/token`;
    const fields = document.querySelectorAll('input');
    const username = fields[1].value;
    const password = fields[2].value;
    const body = `client_id=${client_id}&username=${username}&password=${password}&grant_type=password&scope=openid`;
    let token;
    const res = await fetch(tokenEndpoint, {
      method: "POST",
      body: body,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }).then((response) => response.json())
      .then((responseJSON) => {
        token = responseJSON;
      });
    
    return token;
  }

Can i somehow set access token to initOptions in SSRKeycloakProvider? When i login through default page, Keycloak redirects me to http://localhost:3000/ and everything is OK. I can see idToken and refreshToken. But when i recive accessToken, keycloak doesn't consider me authorized. Maybe i should to set some values in cookie? Help me, please. I'm tired of this task. Thanks

0 Answers0