GraphQL federated authentication from multiple servers

Viewed 10

I have multiple databases built with pretty much the exact same stack express + mongo and the same data schema across all of them.

I would like there to be 1 endpoint where a user can login and rather than route the request to 1 database that it scans all of the databases for a matching user record.

I have enabled graphQL on all the servers and I have created a unified endpoint based off some tutorial for stitching graphql schemas, however i dont think i need to stitch the schemas as they are all basically the same.

Is what i want to do achievable ? I know some folks might suggest that i just go ahead and build a custom SSO feature but it goes a bit more complicated than that with my infrastructure setup and how we need to scale it later.

    'use strict';

    const express = require('express');
    const { graphqlHTTP } = require('express-graphql');
    const { introspectSchema } = require('@graphql-tools/wrap');
    const { stitchSchemas } = require('@graphql-tools/stitch');
    const { fetch } = require('cross-fetch');
    const { print } = require('graphql');
    const serverless = require('serverless-http');
    const bodyParser = require('body-parser')

    const { loadSchema } = require('@graphql-tools/load');
    const { GraphQLFileLoader } =  require('@graphql-tools/graphql-file-loader');

    function makeRemoteExecutor(url, token) {
    return async ({ document, variables }) => {
        const query = print(document);
        const fetchResult = await fetch(url, {
        method: 'POST',
        headers: { 
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + token    
        },
        body: JSON.stringify({ query, variables }),
        });
        return fetchResult.json();
    }
    }

    async function makeGatewaySchema() {

        const server1 = makeRemoteExecutor('http://localhost:7777/graphql', 'fnAEQdRZVpACRMEEM1GKKYQxH2Qa4TzLKusTW2gN');
        const server2 = makeRemoteExecutor('http://localhost:8888/graphql', 'fnAEQdSdXiACRGmgJgAEgmF_ZfO7iobiXGVP2NzT');
        const server3 = makeRemoteExecutor('http://localhost:9999/graphql', 'fnAEQdR0kYACRWKJJUUwWIYoZuD6cJDTvXI0_Y70');

        const parseSchema = await loadSchema('./parseSchema.graphql',{
        loaders: [new GraphQLFileLoader()]
        })    

        return stitchSchemas({
            subschemas: [
            {
                schema: parseSchema,
                executor: server1,
            },
            {
                schema: parseSchema,
                executor: server2
            },
            {
                schema: parseSchema,
                executor: server3
            },
            ],
            
            typeDefs: 'type Query { heartbeat: String! }',
            resolvers: {
            Query: {
                heartbeat: () => 'OK'
            }
            }
        });
    }

    const app = express();

    app.use(bodyParser.json());
    app.use(
    '/graphql',
    graphqlHTTP(async (req) => {
        const schema = await makeGatewaySchema().catch((e) => console.log(e));
        return {
        schema,
        // context: { authHeader: req.headers.authorization },
        graphiql: true,
        }
    }),
    );

    app.listen(4000);
    console.log('Running a GraphQL API server at http://localhost:4000/graphql');


    module.exports.handler = serverless(app);
0 Answers
Related