Impersonation and user switching

Impersonation and user switching are features of the Neo4j database and driver which allow for query execution in a different context to the initial connection.

Impersonation

Impersonation still authenticates with the database as the original configured user, but runs the query in the context of an impersonated user. When impersonating a user, the query is run within the complete security context of the impersonated user and not the authenticated user (home database, permissions etc).

Consider the following an example of how to impersonate a different user per request. Here the user to impersonate is taken from a HTTP header User:

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { Neo4jGraphQL } from "@neo4j/graphql";
import neo4j from "neo4j-driver";

const typeDefs = `#graphql
    type Movie {
        title: String!
    }
`;

const driver =  neo4j.driver(
    "neo4j://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const neo4jGraphql = new Neo4jGraphQL({
    typeDefs,
    driver,
});

const schema = await neo4jGraphql.getSchema();

const server = new ApolloServer({
  schema,
});

const { url } = await startStandaloneServer(server, {
  // Your async context function should async and return an object
  context: async ({ req }) => ({
    sessionConfig: {
        impersonatedUser: req.headers.user,
    },
  }),
});

console.log(`🚀  Server ready at: ${url}`);
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { Neo4jGraphQL, Neo4jGraphQLContext } from "@neo4j/graphql";
import neo4j from "neo4j-driver";

const typeDefs = `#graphql
    type Movie {
        title: String!
    }
`;

const driver =  neo4j.driver(
    "neo4j://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const neo4jGraphql = new Neo4jGraphQL({
    typeDefs,
    driver,
});

const schema = await neo4jGraphql.getSchema();

const server = new ApolloServer<Neo4jGraphQLContext>({
  schema,
});

const { url } = await startStandaloneServer(server, {
  // Your async context function should async and return an object
  context: async ({ req }) => ({
    sessionConfig: {
        impersonatedUser: req.headers.user,
    },
  }),
});

console.log(`🚀  Server ready at: ${url}`);

User switching

User switching completely switches the user authenticating with the database for the given session, without the performance cost of instantiating an entire new driver instance.

An example of configuring user switching on a per request basis can be found in the example below. Note that the username and password are provided in HTTP headers User and Password, but this would not be recommended for production use:

import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { Neo4jGraphQL } from "@neo4j/graphql";
import neo4j from "neo4j-driver";

const typeDefs = `#graphql
    type Movie {
        title: String!
    }
`;

const driver =  neo4j.driver(
    "neo4j://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const neo4jGraphql = new Neo4jGraphQL({
    typeDefs,
    driver,
});

const schema = await neo4jGraphql.getSchema();

const server = new ApolloServer({
  schema,
});

const { url } = await startStandaloneServer(server, {
  // Your async context function should async and return an object
  context: async ({ req }) => ({
    sessionConfig: {
        auth: neo4j.auth.basic(req.headers.user, req.headers.password),
    },
  }),
});

console.log(`🚀  Server ready at: ${url}`);
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { Neo4jGraphQL, Neo4jGraphQLContext } from "@neo4j/graphql";
import neo4j from "neo4j-driver";

const typeDefs = `#graphql
    type Movie {
        title: String!
    }
`;

const driver =  neo4j.driver(
    "neo4j://localhost:7687",
    neo4j.auth.basic("username", "password")
);

const neo4jGraphql = new Neo4jGraphQL({
    typeDefs,
    driver,
});

const schema = await neo4jGraphql.getSchema();

const server = new ApolloServer<Neo4jGraphQLContext>({
  schema,
});

const { url } = await startStandaloneServer(server, {
  // Your async context function should async and return an object
  context: async ({ req }) => ({
    sessionConfig: {
        auth: neo4j.auth.basic(req.headers.user, req.headers.password),
    },
  }),
});

console.log(`🚀  Server ready at: ${url}`);