kisa_2001
kisa_2001

Reputation: 31

Why i can't attach authorization to header in apollo client? (Nestjs, Graphql, Apollo)

I'm trying to bind frontend user registration and authorization to my Nestjs/Graphql server. The functionality of creation and authorization works, I create a user and put an access token in the cookie. But the problem is that I can't navigate through closed endpoints because Apollo doesn't allow me to attach the token to the request headers.

My server on backend (main.ts):

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true });
  app.useGlobalPipes(new ValidationPipe())
  app.useGlobalGuards(new JwtAuthGuard(new Reflector()))
  app.enableCors({
    origin: 'http://localhost:3000',
    credentials: true,
    allowedHeaders: 'Origin,X-Requested-With,Content-Type,Accept,Authorization,authorization'
  })

  await app.listen(3001);
}

bootstrap();

Graphql module in AppModule:

GraphQLModule.forRoot({
      autoSchemaFile: join(process.cwd(), 'src/schema/gql'),
      sortSchema: true,
      driver: ApolloDriver
    })

Apollo client on a frontend:

import { parseCookies } from 'nookies'
import { setContext } from '@apollo/client/link/context';
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'

const cookies = parseCookies()

const httpLink = createHttpLink({
    uri: 'http://localhost:3001/graphql'
});

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

export const client = new ApolloClient({
    cache: new InMemoryCache(),
    credentials: 'same-origin',
    link: authLink.concat(httpLink)
})

My Rrequest Headers:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate, br Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7 Cache-Control: max-age=0 Connection: keep-alive Cookie: access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImVxMUBnbWFpbC5jb20iLCJzdWIiOjUsImlhdCI6MTY1NzM2NTI2OSwiZXhwIjoxNjU3MzY4ODY5fQ.AdbThqNQl746P-T653jkpvdKXTdrVOsj0SUsjzoTQDo DNT: 1 Host: localhost:3000 Referer: http://localhost:3000/playlists sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36

Upvotes: 2

Views: 1118

Answers (1)

W.S.
W.S.

Reputation: 1505

The reason why your setup doesn't work is probably because HttpOnly is set to true for your cookies and therefore aren't accessible through the JavaScript Document.cookie API. So your authLink doesn't have any effect. So, if you want to include it in the headers you either set HttpOnly to false, which is not preferred, or you store the token in LocaleStorage after authentication.

However as the cookies are set by your server, you can just make sure the cookies are send over to the server, by including credentials within your requests. The credentials however should be set within createHttpLink instead of ApolloClient.

But:

  • your graphql server is running at port 3001,
  • your frontend app is served through port 3000.

So credentials : same-origin won't include the headers, as different ports are different origins. Set credentials to include, instead of same-origin. On the server, the token can be accessed through the request.cookies instead of the http-headers. You don't need to parseCookies on the client side.

Upvotes: 1

Related Questions