Search code examples
graphqlapolloroleshasuracode-generation

How to handle X-Hasura-Role with graphql codegen


Good morning,

I have an Angular WebApp that uses GraphQL codegen with (apollo-angular plugin and all the typescript plugins). Everything works fine but I want to handle Hasura Roles and Hasura User ID. From Hasura Console everything is configured correctly and working.

Only thing I am missing is how to handle this on the front end. I need to add X-Hasura-Role and X-Hasura-User-Id headers to every request sent to Hasura. Is there a way to do this with graphql-codegen? What is the right way to do this?

I know I can add the headers section on the codegen.yml, but obviously the role and userid are dynamic so I cannot hardcode anything there.

Should I use maybe a customFetch component? This component, thought, should only intercept every request sent to Hasura and add the headers needed. I have no idea how to do this so I hope you can help me (I also hope there is a better solution)

Best regards


Solution

  • When you create your Apollo client instance in the Angular application you can set it up to pass along the Authorization header which should contain the user's id and their roles.

    There are examples of this in the Angular Apollo docs. Eg:

    import { NgModule } from '@angular/core';
    import { HttpClientModule } from '@angular/common/http';
    import { Apollo, APOLLO_OPTIONS } from 'apollo-angular';
    import { HttpLink } from 'apollo-angular/http';
    import { InMemoryCache,ApolloLink } from '@apollo/client/core';
    import { setContext } from '@apollo/client/link/context';
    
    const uri = '/graphql';
    
    export function createApollo(httpLink: HttpLink) {
      const basic = setContext((operation, context) => ({
        headers: {
          Accept: 'charset=utf-8'
        }
      }));
    
      const auth = setContext((operation, context) => {
        const token = localStorage.getItem('token');
    
        if (token === null) {
          return {};
        } else {
          return {
            headers: {
              Authorization: `JWT ${token}`
            }
          };
        }
      });
    
      const link = ApolloLink.from([basic, auth, httpLink.create({ uri })]);
      const cache = new InMemoryCache();
    
      return {
        link,
        cache
      }
    }
    
    @NgModule({
      exports: [
        HttpClientModule,
      ],
      providers: [{
        provide: APOLLO_OPTIONS,
        useFactory: createApollo,
        deps: [HttpLink]
      }]
    })
    export class GraphQLModule {}
    
    

    It is up to you to ensure that the JWT token that will be passed along with your request is available in the front end. Ultimately you're going to have to implement some kind of authentication approach to allow the user to sign in and pass the token to your front end application.

    More information is available in the Hasura Docs for Authentication

    There are also a number of tutorials and guides for integrating with different third party auth providers