3

I'm trying to connect my react app to a hasura backend api with Apollo Client, but I recieve the following error:

Error: GraphQL error: Malformed Authorization header

I have no idea what is causing it.

I know I'm getting a valid id token from Cognito because I can paste it into the Hasura console and it works fine.

I really just pasted the apollo authorization example into my index.js file and put in my uri. I started out using apollo-boost, but went to apollo-client because of the same error. It didn't help, obviously. I've scoured the internet and can't find anything that seems to relate to this, which probably means I'm doing something stupid.

Here's my apollo-client code from my index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import ApolloClient from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloProvider } from 'react-apollo';
import { Auth } from 'aws-amplify';

async function getSession() {
    Auth.currentSession().then(res=>{
        let idToken = res.getIdToken()
        let jwt = idToken.getJwtToken()
        //if I console log jwt here I can paste it into hasura and it works
        return jwt
      })
  }

const token = getSession()

//copied from apollo docs:
const httpLink = createHttpLink({
    uri: 'https://api.example.com/v1/graphql',
  });

const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : "",
      }
    }
  });

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

here's the error:

Error: GraphQL error: Malformed Authorization header
at new ApolloError (bundle.esm.js:76)
at ObservableQuery.getCurrentResult (bundle.esm.js:200)
at ObservableQuery.currentResult (bundle.esm.js:163)
at Query._this.getQueryResult (react-apollo.esm.js:247)
at finish (react-apollo.esm.js:434)
at Query.render (react-apollo.esm.js:441)
at finishClassComponent (react-dom.development.js:15319)
at updateClassComponent (react-dom.development.js:15274)
at beginWork (react-dom.development.js:16262)
at performUnitOfWork (react-dom.development.js:20279)
at workLoop (react-dom.development.js:20320)
at renderRoot (react-dom.development.js:20400)
at performWorkOnRoot (react-dom.development.js:21357)
at performWork (react-dom.development.js:21267)
at performSyncWork (react-dom.development.js:21241)
at requestWork (react-dom.development.js:21096)
at scheduleWork (react-dom.development.js:20909)
at Object.enqueueForceUpdate (react-dom.development.js:11632)
at Query.push../node_modules/react/cjs/react.development.js.Component.forceUpdate (react.development.js:355)
at Query._this.updateCurrentData (react-apollo.esm.js:214)
at Object.error (react-apollo.esm.js:197)
at notifySubscription (Observable.js:157)
at onNotify (Observable.js:196)
at SubscriptionObserver.error (Observable.js:253)
at bundle.esm.js:541
at Array.forEach (<anonymous>)
at iterateObserversSafely (bundle.esm.js:540)
at Object.onError [as error] (bundle.esm.js:482)
at invoke (bundle.esm.js:1532)
at bundle.esm.js:1565
at bundle.esm.js:1986
at Set.forEach (<anonymous>)
at bundle.esm.js:1984
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (bundle.esm.js:1982)
at bundle.esm.js:2109
at Object.next (Observable.js:333)
at notifySubscription (Observable.js:152)
at onNotify (Observable.js:196)
at SubscriptionObserver.next (Observable.js:248)
at bundle.esm.js:1079
at Set.forEach (<anonymous>)
at Object.next (bundle.esm.js:1078)
at notifySubscription (Observable.js:152)
at onNotify (Observable.js:196)
at SubscriptionObserver.next (Observable.js:248)
at notifySubscription (Observable.js:152)
at onNotify (Observable.js:196)
at SubscriptionObserver.next (Observable.js:248)
at bundle.esm.js:107

Plus I get errors from the browser because the query didn't return anything.

Here's what chrome console has in the graphql header:

General:
Request URL: https://api.example.com/v1/graphql
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: 137.242.2.135:8080
Referrer Policy: no-referrer-when-downgrade

Response:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS
Access-Control-Allow-Origin: https://example.com
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=UTF-8
Date: Thu, 18 Jul 2019 17:42:21 GMT
Server: Caddy, Warp/3.2.27

Request
Provisional headers are shown
Access-Control-Request-Headers: authorization,content-type
Access-Control-Request-Method: POST
Origin: https://example.com
Referer: https://example.com/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36

Any help would be appreciated.

Chris S
  • 31
  • 1
  • 2
  • Is the query triggering this error a standard query, or a subscription? Also, the headers you're showing are for the pre-flight request, and not the *actual* request, which should be the one following. Any chance you could post the headers from that subsequent request (which should normally contain your 'authorization' header). – Thomas Hennes Jul 19 '19 at 16:18
  • Also, how are you handling the 'authorization' header on the API side? – Thomas Hennes Jul 19 '19 at 16:21

1 Answers1

2

The value assign to token is of type Promise and not a string as you expect.

Since getSession() is an async function, therefor it returns a promise.

This line:

const token = getSession()

assigns the promise and not its resolved value to the token.

You need to wait for the promise to resolve before assigning the result to token.

Tal Z
  • 3,170
  • 17
  • 30