AEB-labs / graphql-weaver

A tool to combine, link and transform GraphQL schemas
MIT License
240 stars 20 forks source link

Authenticating User at API Gateway and then redirecting them to microservices #54

Open shreyansh-zazz opened 5 years ago

shreyansh-zazz commented 5 years ago

I am trying to build an API Gateway with GraphQL for my microservices architecture. Here's how I am trying to implement this:

Following are the expected API Gateway features:

Following are the things is not expected from the API Gateway:

This framework is all cool, but I don't find any examples or methods through which I can achieve this. Maybe someone can guide me through.

Perhaps @Yogu you can help me.

Thanks

Yogu commented 5 years ago

To write custom authentication logic, you need to do two things:

Then, you can use a config like this:

const schema = weaveSchemas({
    endpoints: [, {
        namespace: 'M1',
        url: 'http://m1/...'
    }, {
        namespace: 'M2',
        client: new CustomHttpGraphQLClient('http://m2/...')
    }, /* ... */
    ]
});

I hope this helps

shreyansh-zazz commented 5 years ago

@Yogu Few doubts:

Yogu commented 5 years ago

CustomGraphQLClient would be your subclass of HttpGraphQLClient, something like this:


class CustomGraphQLClient extends HttpGraphQLClient {
    protected async getHeaders(document: DocumentNode, variables?: { [name: string]: any }, context?: any, introspect?: boolean): Promise<{ [index: string]: string }> {
        const request = context as Request;
        // implement your logic here for decoding the token based on the express request
        const regularHeaders = super.getHeaders(document, variables, context, introspect);

        return {
            ...regularHeaders,
            // add your headers here
        };
    }
}

Do I have to pass the client property for microservices M3 and M4 also?

I understood that M2, M3 and M4 are basically the same, so yes you would need to add endpoints with the custom client for all three of them.

shreyansh-zazz commented 5 years ago

@Yogu I understand that above mentioned solution will add a header (in which token data will be available for other to use) to the original request but I still don't understand how it will stop the request at the API Gateway if no JWT Token is found int the request header?

Yogu commented 5 years ago

It's completely up to you how you implement that method, you can just throw an Error if the user is not authenticated.

shreyansh-zazz commented 5 years ago

@Yogu Hey what if I am not using Typescript?

class CustomGraphQLClient extends HttpGraphQLClient {
    protected async getHeaders(document: DocumentNode, variables?: { [name: string]: any }, context?: any, introspect?: boolean): Promise<{ [index: string]: string }> {
        const request = context as Request;
        // implement your logic here for decoding the token based on the express request
        const regularHeaders = super.getHeaders(document, variables, context, introspect);

        return {
            ...regularHeaders,
            // add your headers here
        };
    }
}

Then how can I implement this custom class?

Yogu commented 5 years ago

Ah, just remove some parts:

class CustomGraphQLClient extends HttpGraphQLClient {
    async getHeaders(document, variables) {
        const request = context;
        // implement your logic here for decoding the token based on the express request
        const regularHeaders = super.getHeaders(document, variables, context, introspect);

        return {
            ...regularHeaders,
            // add your headers here
        };
    }
}

If you need to target an older version of JavaScript, just use a transpiler of your choice.