wp-graphql/wp-graphql-jwt-authentication

Not authorized to access this customer

muhaimincs opened this issue · 6 comments

Hi

I'm trying to figure out how this plugin with React-Native. I believe I set it all right and I believe this has something to do with authorization. Appreciate if you guys can point me to the right direction on how to get it right with this query

query CustomerQuery($id: ID!) {
  customer(id: $id) {
    billing {
      address1
      address2
      city
      postcode
      state
      country
      phone
    }
  }
}

and here is how I set up the apollo client (apollo.ts)

import { ApolloClient, HttpLink, InMemoryCache, ApolloLink } from '@apollo/client';
import { asyncMap } from "@apollo/client/utilities";

import GRAPHQL_API_URL from './constants/Api';
import { getUserInfo, getToken, removeUserInfo, storeUserInfo } from './Utils'

// https://github.com/imranhsayed/woo-next/blob/master/components/ApolloClient.js
export const afterware = new ApolloLink((operation, forward) => {
  return asyncMap(forward(operation), async (response) => {
    const context = operation.getContext();
    const { response: { headers } } = context;
    const session = headers.get("woocommerce-session");
    const token = await getToken();

    if (session) {
      if ("false" === session) {
        console.log('invalid session', session)
        // await removeUserInfo();
      } else if (token !== session) {
        const userInfo = await getUserInfo();
        const updatedUserInfo = {
          ...userInfo,
          wooCommerceSession: headers.get("woocommerce-session")
        };
        storeUserInfo(updatedUserInfo);
      }
    }
    return response;
  });
});

const authMiddleware = new ApolloLink((operation, forward) => {
  return asyncMap(forward(operation), async (response) => {
    const token = await getToken();
    console.log('token for apollo', token);
    response.headers = {
      'Authorization': `Bearer ${token}`,
      // 'woocommerce-session': 'Session'
    };
    return response
  });
})

const httpLink = new HttpLink({
  uri: GRAPHQL_API_URL,
});

export const apolloClient = new ApolloClient({
  link: authMiddleware.concat(afterware.concat(httpLink)),
  cache: new InMemoryCache(),
});

@muhaimincs You need to add the woocommerce-session token to the middleware along with the Authorization token, in your example it's commented out with not value.

If you haven't authenticated the user with the login mutation, you need to have started a user session by adding an item to the cart with the addToCart mutation for the query you're trying to work. However, in order for this to work you need to be implementing the session token.

Are you using the following versions for each plugin?
WPGraphQL: v1.0
WooGraphQL: v0.7.0
WPGraphQL-JWT-Authentication: v0.4.0

The reason it was commented because I'm not sure what value should be stored in woocommerce-session? Would you guide me where can I retrieve those value

BTW, I don't have access to get the version number but I'm quite it just been installed for the wordpress version below
WP: 5.5.3

OK now I have come to understand a bit on how the afterware works. So here the modified one

export const afterware = new ApolloLink((operation, forward) => {
  return asyncMap(forward(operation), async (response) => {
    const context = operation.getContext();
    const { response: { headers } } = context;
    const session = await headers.get("woocommerce-session");
    const existingSession = await getSession();

    if (session) {
      if ("false" === session) {
        removeSession();
      } else if (existingSession !== session) {
        storeSession(session);
      }
    }
    return response;
  });
});

const authMiddleware = new ApolloLink((operation, forward) => {
  return asyncMap(forward(operation), async (response) => {
    const token = await getToken();
    const session = await getSession();
    console.log('GET SESSION', session)
    response.headers = {
      'Authorization': `Bearer ${token}`,
      'woocommerce-session': `Session ${session}`
    };
    return response
  });
})

But it still won't work when I start to do mutation on add cart and if I refetch the get cart queries, it still empty. Where else did I missed?

is it because I use asyncMap from @apollo/client/utilities?

I'm experiencing the same issue and providing the woocommerce token and the authentication token in the HTTP headers. Even took them to another tool to test outside of the website, and they aren't working.

http://[domain]/graphql?query=query GET_CUSTOMER_ORDER($customerId: Int) {
    customer(customerId: $customerId) {
      id
      orders {
        edges {
          node {
            id
            orderKey
            date
            status
            total
            customerNote
            paymentMethodTitle
            lineItems {
              edges {
                node {
                  product {
                    name
                    id
                  }
                }
              }
            }
          }
        }
      }
    }
  }&variables={
"customerId" : 1
}

Headers:

"authorization": token ? `Bearer ${token}
woocommerce-session": `Session ${ session }

Error:

{
-"errors": [
-{
"message": "Not authorized to access this customer",
-"extensions": {
"category": "user"
},
-"locations": [
-{
"line": 2,
"column": 5
}
],
-"path": [
"customer"
]
}
],
-"data": {
"customer": null
},
-"extensions": {
"debug": [ ]
}
}

I think I may have the clue on what was wrong with the above code.

is it because I use asyncMap from @apollo/client/utilities?

I used this and manually set the header to the response and this was wrong. So I did little modification to the way I sustain the session

import { setContext } from "@apollo/client/link/context";

const asyncSessionLink = setContext(
  request =>
    new Promise((success, fail) => {
      getSession().then(token => success({ headers: { Authorization: `Bearer ${token}` } }));
    })
);

I hope this may help the others in React-Native