项目作者: imhassane

项目描述 :
A simple blog api made using apollo federation as a gateway for the microservices
高级语言: JavaScript
项目地址: git://github.com/imhassane/apollo-federation-example.git
创建时间: 2020-05-13T14:46:23Z
项目社区:https://github.com/imhassane/apollo-federation-example

开源协议:

下载


Apollo Federation: Microservices with authentication

A simple blog api with authentication made using apollo federation as an api gateway for the microservices.

This project has been made for learning purposes. I’ll need to work on a personnal
project based on microservices using graphql and apollo.

It is a simple introduction to Apollo Federation.

I honestly love it and think it’s really really easy to understand and it helps me with
the problem I had with authentication in microservices.

I used to make http requests for token validation through my microservices and with
Federation, it’s just a lot easier with its context and request headers.
.

Installation

This project does not need database as I’m using hard coded data in arrays to replace it.

You can run this project on your machine by running this command below on your terminal:

git clone https://github.com/apollo-federation-example.git <YOUR_PROJECT_NAME>

Or just download this repository on your local machine.

The authentication part

Each service here is a normal apollo & graphql project. I usually handle authentication by
putting the current user in the context and that’s what I’m doing here.

  1. const server = new ApolloServer({
  2. gateway,
  3. subscriptions: false,
  4. context: async ({req}) => {
  5. let token = req.headers.authorization || null;
  6. if(token) {
  7. try {
  8. const {id} = await jwt.verify(token, "secret");
  9. const user = users.find(u => u.id === id);
  10. return { user };
  11. } catch(ex) {
  12. return {user: null};
  13. }
  14. }
  15. }
  16. });

If there is an authentication (here I’m calling it authorization even if it’s not really an authorization token) token, I just need to get the id inside the token and fetch the user who is matching the given id and then inject it into the context.

In my api gateway, I then need to inject the user inside each request’s headers. Here I’ve choosen to fetch it from the
database and stringify it instead of just passing the user’s id into the request. This will prevent fetching the user from
the database again when we will need it.

  1. const gateway = new ApolloGateway({
  2. serviceList: [
  3. {name: "users", url: "http://localhost:4001/graphql"},
  4. {name: "posts", url: "http://localhost:4002/graphql"},
  5. {name: "comments", url: "http://localhost:4003/graphql"}
  6. ],
  7. buildService: ({url}) => new RemoteGraphQLDataSource({
  8. url,
  9. willSendRequest: ({request, context}) => {
  10. if(context.user) request.http.headers.set("user", JSON.stringify(context.user));
  11. }
  12. })
  13. });

To use it inside a resolver, I have to put the user inside the context of each service again as in every graphql project.

  1. context: ({req}) => {
  2. // Fetching the user from the headers.
  3. const { user } = req.headers;
  4. if(user) {
  5. return { user: JSON.parse(user) };
  6. }
  7. }

And we can call it now from every resolver.

  1. Query: {
  2. // To get the current user,
  3. // We return the user inside the context :) :)
  4. me: (_parent, _args, {user}) => user
  5. }

It is that simple, I personnaly love @apollo/federation and the @apollo team.
They just made me love graphql.

LOVE EVERYONE…