Reputation: 31
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
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:
3001
,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