Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GraphQL error]: Authentication hook unauthorized this request #1048

Open
kiitosu opened this issue Jul 21, 2024 · 1 comment
Open

[GraphQL error]: Authentication hook unauthorized this request #1048

kiitosu opened this issue Jul 21, 2024 · 1 comment

Comments

@kiitosu
Copy link

kiitosu commented Jul 21, 2024

I followed frontend tutorial graphql with react https://hasura.io/learn/graphql/react/introduction/.
And I get authentication error with token I get with useAccessToken.

Base code I used is 698f187.
Error message is "[GraphQL error]: Authentication hook unauthorized this request " at TodoPrivateList.js:66.

When I hard code jwt like below that is gotten at https://hasura.io/learn/graphql/graphiql, I can query in localhost web site with npm start.

Why I get authentication error with token I get with useAccessToken? How can I handle token?

const createApolloClient = (authToken) => {
    console.log(`authToken is ${authToken}`)
    return new ApolloClient({
        link: new HttpLink({
            uri: 'https://hasura.io/learn/graphql',
            headers: {
                Authorization: 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik9FWTJSVGM1UlVOR05qSXhSRUV5TURJNFFUWXdNekZETWtReU1EQXdSVUV4UVVRM05EazFNQSJ9.eyJodHRwczovL2hhc3VyYS5pby9qd3QvY2xhaW1zIjp7IngtaGFzdXJhLWRlZmF1bHQtcm9sZSI6InVzZXIiLCJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbInVzZXIiXSwieC1oYXN1cmEtdXNlci1pZCI6ImF1dGgwfDYyZGYyN2E3ZGMwMTBhYjg3YTFlMmRiYSJ9LCJuaWNrbmFtZSI6ImtoMDQxMiIsIm5hbWUiOiJraDA0MTJAZ21haWwuY29tIiwicGljdHVyZSI6Imh0dHBzOi8vcy5ncmF2YXRhci5jb20vYXZhdGFyLzI2ZmMzZThmNTVlMjIwM2UzOTgzMzQyZmYwMzUyZmM1P3M9NDgwJnI9cGcmZD1odHRwcyUzQSUyRiUyRmNkbi5hdXRoMC5jb20lMkZhdmF0YXJzJTJGa2gucG5nIiwidXBkYXRlZF9hdCI6IjIwMjQtMDctMjFUMDg6Mjk6MTIuODYyWiIsImlzcyI6Imh0dHBzOi8vZ3JhcGhxbC10dXRvcmlhbHMuYXV0aDAuY29tLyIsImF1ZCI6IlAzOHFuRm8xbEZBUUpyemt1bi0td0V6cWxqVk5HY1dXIiwiaWF0IjoxNzIxNTUxNDc4LCJleHAiOjE3MjE1ODc0NzgsInN1YiI6ImF1dGgwfDYyZGYyN2E3ZGMwMTBhYjg3YTFlMmRiYSIsImF0X2hhc2giOiJLcUNDay04T192ZjVaNWRDdjdXMGhnIiwic2lkIjoiMVNVUl9iUDFpcy1aNktKd1NGMmY5WGc2Rk9kYlFtQTEiLCJub25jZSI6IlQ3QWU0YktzTTlYX2VBeS1aT0xMLlowTGZ0MzRNU3FpIn0.hoSkaLMAjFeycQB7yHGEOQUWvpZd2e4CR72B-Hv3iMBgQtWc5t0uXqZZmDYYPQxpD30ZrLVtytv0XI_qc8zQLdc_B759VCUfah2hQ_sxifwYntRUV41ZdyGFNPw_zqQa9hSF6npFHXRQrnff7EHmvDEKL8YSGrOq1zMDhkpBN72ZCZQjmwUT3swABA51KB4J6ZlKYhPodq9GoOSPzxmYwsvWiO2nvoj7wJFDlfX6aiNRGai3a9lypCEPHo-vSLcD9gUXMrdsi-aeuCmPoHpyiWThNeCklprFaPaO4yJSCFECGLCOqX3JFhC5NILNK7ZUQVyHkHRHxkbjgK7VYx4AhA'
            }
        }),
        cache: new InMemoryCache(),
    });
};

Diff patch is below.

diff --git a/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/App.js b/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/App.js
index 2199664..c88f7d4 100644
--- a/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/App.js
+++ b/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/App.js
@@ -1,4 +1,4 @@
-import React from "react";
+import React, {useState} from "react";
 import { useAuth0 } from "@auth0/auth0-react";
 
 import Header from "./Header";
@@ -9,9 +9,26 @@ import OnlineUsersWrapper from "./OnlineUsers/OnlineUsersWrapper";
 
 import useAccessToken from "../hooks/useAccessToken";
 
+import { ApolloClient, ApolloProvider, InMemoryCache, HttpLink } from '@apollo/client';
+
+const createApolloClient = (authToken) => {
+    console.log(`authToken is ${authToken}`)
+    return new ApolloClient({
+        link: new HttpLink({
+            uri: 'https://hasura.io/learn/graphql',
+            headers: {
+                Authorization: `Bearer ${authToken}`
+            }
+        }),
+        cache: new InMemoryCache(),
+    });
+};
+
+
 const App = () => {
   const idToken = useAccessToken();
   const { loading, logout } = useAuth0();
+  const [client] = useState(createApolloClient(idToken));
 
   if (loading) {
     return <div>Loading...</div>;
@@ -20,25 +37,28 @@ const App = () => {
   if (!idToken) {
     return <Login />;
   }
+
   return (
-    <div>
-      <Header logoutHandler={logout} />
-      <div className="row container-fluid p-left-right-0 m-left-right-0">
-        <div className="row col-md-9 p-left-right-0 m-left-right-0">
-          <div className="col-md-6 sliderMenu p-30">
-            <TodoPrivateWrapper />
-          </div>
-          <div className="col-md-6 sliderMenu p-30 bg-gray border-right">
-            <TodoPublicWrapper />
-          </div>
-        </div>
-        <div className="col-md-3 p-left-right-0">
-          <div className="col-md-12 sliderMenu p-30 bg-gray">
-            <OnlineUsersWrapper />
-          </div>
+    <ApolloProvider client={client}>
+        <div>
+            <Header logoutHandler={logout} />
+            <div className="row container-fluid p-left-right-0 m-left-right-0">
+                <div className="row col-md-9 p-left-right-0 m-left-right-0">
+                <div className="col-md-6 sliderMenu p-30">
+                    <TodoPrivateWrapper />
+                </div>
+                <div className="col-md-6 sliderMenu p-30 bg-gray border-right">
+                    <TodoPublicWrapper />
+                </div>
+                </div>
+                <div className="col-md-3 p-left-right-0">
+                <div className="col-md-12 sliderMenu p-30 bg-gray">
+                    <OnlineUsersWrapper />
+                </div>
+                </div>
+            </div>
         </div>
-      </div>
-    </div>
+    </ApolloProvider>
   );
 };
 
diff --git a/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/Todo/TodoPrivateList.js b/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/Todo/TodoPrivateList.js
index f1d43bc..cf84d9f 100644
--- a/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/Todo/TodoPrivateList.js
+++ b/tutorials/frontend/react-apollo-hooks/app-boilerplate/src/components/Todo/TodoPrivateList.js
@@ -1,26 +1,21 @@
 import React, { useState, Fragment } from "react";
-
 import TodoItem from "./TodoItem";
 import TodoFilters from "./TodoFilters";
+import {gql, useQuery} from '@apollo/client'
+const GET_MY_TODOS = gql`
+query getMyTodos {
+    todos(where: { is_public: { _eq: false} }, order_by: { created_at: desc }) {
+        id
+        title
+        created_at
+        is_completed
+    }
+}`;
 
 const TodoPrivateList = props => {
   const [state, setState] = useState({
     filter: "all",
     clearInProgress: false,
-    todos: [
-      {
-        id: "1",
-        title: "This is private todo 1",
-        is_completed: true,
-        is_public: false
-      },
-      {
-        id: "2",
-        title: "This is private todo 2",
-        is_completed: false,
-        is_public: false
-      }
-    ]
   });
 
   const filterResults = filter => {
@@ -32,11 +27,12 @@ const TodoPrivateList = props => {
 
   const clearCompleted = () => {};
 
-  let filteredTodos = state.todos;
+  const {todos} = props
+  let filteredTodos = todos
   if (state.filter === "active") {
-    filteredTodos = state.todos.filter(todo => todo.is_completed !== true);
+    filteredTodos = todos.filter(todo => todo.is_completed !== true);
   } else if (state.filter === "completed") {
-    filteredTodos = state.todos.filter(todo => todo.is_completed === true);
+    filteredTodos = todos.filter(todo => todo.is_completed === true);
   }
 
   const todoList = [];
@@ -61,4 +57,30 @@ const TodoPrivateList = props => {
   );
 };
 
-export default TodoPrivateList;
+const TodoPrivateListQuery = ()=> {
+    const { loading, error, data } = useQuery(GET_MY_TODOS)
+    if(loading) {
+        return <div>Loading...</div>
+    }
+    if (error) {
+        console.error(`[GraphQL error]: ${error.message}`);
+        if (error.graphQLErrors) {
+            error.graphQLErrors.forEach(({ message, locations, path }) =>
+                console.error(
+                    `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
+                )
+            );
+        }
+        if (error.networkError) {
+            console.error(`[Network error]: ${error.networkError}`);
+        }
+        if (error.message.includes("Authentication hook unauthorized this request")) {
+            return <div>Authentication Error! Please log in again.</div>;
+        }
+        return <div>Error!</div>;
+    }
+    return <TodoPrivateList todos={data.todos}/>;
+}
+
+export default TodoPrivateListQuery;
+export {GET_MY_TODOS}

TodoPrivateList.js

import React, { useState, Fragment } from "react";
import TodoItem from "./TodoItem";
import TodoFilters from "./TodoFilters";
import {gql, useQuery} from '@apollo/client'
const GET_MY_TODOS = gql`
query getMyTodos {
    todos(where: { is_public: { _eq: false} }, order_by: { created_at: desc }) {
        id
        title
        created_at
        is_completed
    }
}`;

const TodoPrivateList = props => {
  const [state, setState] = useState({
    filter: "all",
    clearInProgress: false,
  });

  const filterResults = filter => {
    setState({
      ...state,
      filter: filter
    });
  };

  const clearCompleted = () => {};

  const {todos} = props
  let filteredTodos = todos
  if (state.filter === "active") {
    filteredTodos = todos.filter(todo => todo.is_completed !== true);
  } else if (state.filter === "completed") {
    filteredTodos = todos.filter(todo => todo.is_completed === true);
  }

  const todoList = [];
  filteredTodos.forEach((todo, index) => {
    todoList.push(<TodoItem key={index} index={index} todo={todo} />);
  });

  return (
    <Fragment>
      <div className="todoListWrapper">
        <ul>{todoList}</ul>
      </div>

      <TodoFilters
        todos={filteredTodos}
        currentFilter={state.filter}
        filterResultsFn={filterResults}
        clearCompletedFn={clearCompleted}
        clearInProgress={state.clearInProgress}
      />
    </Fragment>
  );
};

const TodoPrivateListQuery = ()=> {
    const { loading, error, data } = useQuery(GET_MY_TODOS)
    if(loading) {
        return <div>Loading...</div>
    }
    if (error) {
        console.error(`[GraphQL error]: ${error.message}`);
        if (error.graphQLErrors) {
            error.graphQLErrors.forEach(({ message, locations, path }) =>
                console.error(
                    `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
                )
            );
        }
        if (error.networkError) {
            console.error(`[Network error]: ${error.networkError}`);
        }
        if (error.message.includes("Authentication hook unauthorized this request")) {
            return <div>Authentication Error! Please log in again.</div>;
        }
        return <div>Error!</div>;
    }
    return <TodoPrivateList todos={data.todos}/>;
}

export default TodoPrivateListQuery;
export {GET_MY_TODOS}

App.js

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

import Header from "./Header";
import Login from "./Auth/Login";
import TodoPrivateWrapper from "./Todo/TodoPrivateWrapper";
import TodoPublicWrapper from "./Todo/TodoPublicWrapper";
import OnlineUsersWrapper from "./OnlineUsers/OnlineUsersWrapper";

import useAccessToken from "../hooks/useAccessToken";

import { ApolloClient, ApolloProvider, InMemoryCache, HttpLink } from '@apollo/client';

const createApolloClient = (authToken) => {
    console.log(`authToken is ${authToken}`)
    return new ApolloClient({
        link: new HttpLink({
            uri: 'https://hasura.io/learn/graphql',
            headers: {
                Authorization: `Bearer ${authToken}`
            }
        }),
        cache: new InMemoryCache(),
    });
};


const App = () => {
  const idToken = useAccessToken();
  const { loading, logout } = useAuth0();
  const [client] = useState(createApolloClient(idToken));

  if (loading) {
    return <div>Loading...</div>;
  }

  if (!idToken) {
    return <Login />;
  }

  return (
    <ApolloProvider client={client}>
        <div>
            <Header logoutHandler={logout} />
            <div className="row container-fluid p-left-right-0 m-left-right-0">
                <div className="row col-md-9 p-left-right-0 m-left-right-0">
                <div className="col-md-6 sliderMenu p-30">
                    <TodoPrivateWrapper />
                </div>
                <div className="col-md-6 sliderMenu p-30 bg-gray border-right">
                    <TodoPublicWrapper />
                </div>
                </div>
                <div className="col-md-3 p-left-right-0">
                <div className="col-md-12 sliderMenu p-30 bg-gray">
                    <OnlineUsersWrapper />
                </div>
                </div>
            </div>
        </div>
    </ApolloProvider>
  );
};

export default App;
@praveenweb
Copy link
Member

Hi @kiitosu - The access token is being set using the following snippet here -

const accessToken = await getAccessTokenSilently({

const getAccessToken = async () => {
      const { audience, scope } = AUTH_CONFIG;

      try {
        const accessToken = await getAccessTokenSilently({
          audience,
          scope,
        });
        setIdToken(accessToken);
      } catch (e) {
        console.log(e.message);
      }
    };

I would start debugging there. Quick caveat: The tutorial is using older versions of Auth0 SDK, so I would double-check if it is using the right one since newer ones may have breaking changes.
Meanwhile, I will try running it from my side to see what could be wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants