Skip to main content

React Auth0 Graphql

Hxb-react-auth0-graphql

Get Started

Initialize

Create an application React:

  • Using optional yarn package
    yarn create react-app auth0-react-graphql

Install package

  • Using optional yarn package

    yarn add @apollo/client @auth0/auth0-react @auth0/auth0-spa-js graphql img-loader react-router-dom react-dom sass-loader typescript

    yarn add -D @babel/preset-react @babel/preset-typescript @types/react eslint-config-react-app react-error-overlay sass

Connect react with grahpql through apollo

  • In index.js import package @apollo/client and @auth0/auth0-react:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    import { Auth0Provider } from "@auth0/auth0-react";
    import {
    ApolloClient,
    ApolloProvider,
    createHttpLink,
    InMemoryCache
    }
    from '@apollo/client';
    import { setContext } from '@apollo/client/link/context';
    import {BrowserRouter} from 'react-router-dom'

    const httpLink = createHttpLink({
    uri: process.env.HXB_GRAPHQL || 'http://localhost:3001/graphql',
    });
    const authLink = setContext((_, { headers }) => {
    const token = localStorage.getItem('token');
    return {
    headers: {
    ...headers,
    authorization: token ? `Bearer ${token}` : "",
    }
    }
    });

    const client = new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache()
    });

    ReactDOM.render(
    <React.StrictMode>
    <BrowserRouter>
    <ApolloProvider client={client}>
    <Auth0Provider
    domain="hexabase.jp.auth0.com"
    clientId="5uBLgkFDuFhA4ZsMr6JwZgqWvfbQge59"
    >
    <App />
    </Auth0Provider>
    </ApolloProvider>
    </BrowserRouter>
    </React.StrictMode>,
    document.getElementById('root')
    );
    reportWebVitals();

- Example Login Auth0 Graphql with Hexabase

- Create UI for Login auth0:

  • Customize src/components/Login/ButtonLoginAuth0.tsx:

    import { useAuth0 } from "@auth0/auth0-react";

    type PamramButtonLogin = {
    connection: string,
    img: string,
    alt: string,
    titleName: string
    }

    const ButtonLoginAuth0 = ({connection, img, alt, titleName}: PamramButtonLogin) => {
    const { loginWithRedirect } = useAuth0();
    return (
    <div className="button-auth0">
    <button onClick={() => loginWithRedirect({
    redirectUri: window.location.origin + '/login-callback',
    connection: connection
    })}>
    {titleName}
    <img src={img} alt={alt}/>
    </button>
    </div>
    )
    }
  • Customize src/pages/Login/index.tsx:

    import './style.scss'
    import ButtonLoginAuth0 from '../../components/Login/ButtonLoginAuth0'

    function LoginPage() {
    const messError = localStorage.getItem('errorLogin')
    localStorage.setItem('errorLogin', '')
    return (
    <div className="form-block">
    {messError && messError?.length > 0 ? ( <div className="Erorr"> asda{messError}</div>) : (<></>)}
    <div className="form-block-login">
    <form action="" className="form-login">
    <hr className="tag-hr"/>
    <div className="block-auth0">
    <span>Login with:</span>
    <div>
    <ButtonLoginAuth0
    connection='google-oauth2'
    img='/icons/google.svg'
    alt='alt'
    titleName='Google'
    ></ButtonLoginAuth0>
    </div>
    </div>
    </form>
    </div>
    </div>
    );
    }

    export default LoginPage;

- Create syntax graphql:

  • create get user info, login with auth0 src/graphql/auth.ts

    import { gql } from "@apollo/client";
    export const USERINFO = gql`query UserInfo {
    userInfo {
    username
    email
    profile_pic
    u_id
    current_workspace_id
    is_ws_admin
    user_roles {
    r_id
    role_name
    role_id
    p_id
    application_id
    application_name
    application_display_order
    }
    }
    }`;

    export const LOGIN_MUTATION = gql`
    mutation Login($loginInput: LoginInput!) {
    login(loginInput: $loginInput) {
    token
    }
    }
    `;

    export const LOGIN_AUTH0_MUTATION = gql`
    mutation LoginAuth0($auth0Input: Auth0Input!) {
    loginAuth0(auth0Input: $auth0Input) {
    token
    }
    }
    `;
  • create types for user src/types/user.ts

    export type UserRoles = {
    r_id: string,
    role_name: string,
    role_id: string,
    p_id: string,
    application_id: string,
    application_name: boolean,
    application_display_order: UserRoles
    };
    export type UserInfo = {
    username: string,
    email: string,
    profile_pic?: string,
    u_id: string,
    current_workspace_id: string,
    is_ws_admin: boolean,
    user_roles?: [UserRoles]
    };
    export type UserInfoRes = {
    userInfo: UserInfo
    };

- Handle login auth0 with graphql:

  • Handle login auth0 graphql for hexabase src/pages/Login/LoginCallback.tsx

    import {
    useNavigate,
    useLocation,
    } from "react-router-dom";
    import './style.scss'
    import ButtonLoginAuth0 from '../../components/Login/ButtonLoginAuth0'
    import axios from "axios";
    import {LOGIN_AUTH0_MUTATION} from '../../graphql/auth';
    import { useMutation } from "@apollo/client";
    import { useAuth0 } from "@auth0/auth0-react";
    import { useEffect, useState } from "react";
    import { Route, Navigate, Outlet } from 'react-router-dom';
    type Res = {
    loginAuth0: loginAuth0,
    }

    type loginAuth0 = {
    token: string
    }

    const LoginCallback = ()=> {
    const {user, getIdTokenClaims } = useAuth0();
    const [loginAuth0, { data, loading, error }] = useMutation<Res>(LOGIN_AUTH0_MUTATION);

    useEffect(() => {
    async function getToken() {
    const idTokenClaims = await getIdTokenClaims()
    if(idTokenClaims && idTokenClaims.__raw){
    await loginAuth0({
    variables:{
    auth0Input:{
    token: idTokenClaims.__raw
    }
    }
    })
    } else {
    console.log("Error get idTokenClaims")
    }
    }

    getToken()
    },[getIdTokenClaims, loginAuth0, user]);

    if (loading){
    return <h2>Loading!...</h2>
    }

    if (error){
    localStorage.setItem('errorLogin', 'Login auth0 error')
    return (<Navigate to="/login"/>)
    }

    if(data && data.loginAuth0 && data.loginAuth0.token){
    localStorage.setItem('token', data.loginAuth0?.token)
    }

    return (
    <>
    {
    data && !loading && !error ? (
    <Navigate to="/" />
    ) : (
    <>
    </>
    )
    }
    </>
    );

    }
    export default LoginCallback;

- Main app:

  • Finnal: export App.tsx:

    import * as React from "react";
    import {
    Routes,
    Route,
    } from "react-router-dom";
    import { Dashboard, LoginPage, LoginCallback } from './pages/'

    import PrivateRoute from './components/RouterPrivate/PrivateRoute'
    function App() {

    return (
    <React.StrictMode>
    <Routes>
    <Route path="/login" element={<LoginPage />} ></Route>
    <Route path="/login-callback" element={<LoginCallback />} ></Route>
    <Route
    path="/"
    element={
    <PrivateRoute>
    <Dashboard />
    </PrivateRoute>
    }
    />
    </Routes>
    </React.StrictMode>
    );
    }

    export default App;

- Run project:

  yarn start

Example: Hexabase Auth0 React Graphql