Skip to content

Authentication in GraphQL queries

Both the GraphQL Module and the GraphQL Gateway module provide support for Authentication and accessing the current logged in user.

Introduction: Tiers from the point of view of authentication

Gateway Tier

It is the outmost facing tier, usually implemented using the GraphQL Gateway Module and Federation. The GraphQL Gateway Module itself is compatible with the Suite Authentication Module and thus also with Asp.Net authentication. On this tier the logged in information is received using OAuth2 standards, usually a Bearer Token. All standard authentication procedures should be done at this level, all other inner tiers must be agnostic to it.

The Current User HTTP Header

When forwarding request to the downstream services, the Gateway module will automatically send the current user ID, if there is one, on a custom HTTP Header called X-ITS-SUITE-USER.

Important

The Bearer Token, or any other standard auth information, is not forwarded to the inner tiers. As mentioned, all standard auth process is done on the Gateway tier.

The Application Tier

This is the intermediary tier, where services or queries are exposed and combined to provide support for an application. This tier is usually implemented using the GraphQL Module, taking advantage of its capabilities like automatically exposing MassTransit Messages as GraphQL Mutations, etc.

Information

As mentioned on the section linked above if the exposed message is configured to use the current user ID then it will be automatically required authentication, as authentication is the only way to have a current user. Other custom queries and mutation created on this tier that we want to be protected by authentication have to be configure on the Gateway. For more information, keep on reading below.

Current User on Suite Context

On this tier, the current user ID can be pulled from the SuiteContext as there is a middleware in charge of getting it from the X-ITS-SUITE-USER header that the Gateway sends, and setting it into the SuiteContext which can be injected through DI. There is an extension method called GetCurrentUserId on the MVCModule to easily get the current user ID from the SuiteContext.

C#
1
2
3
4
 if (suiteContext.GetCurrentUserId() is Guid userCorrelationId)
    {
       // Do something with the User ID.
    }

Downstream Tier

On this tier we have the microservices. Communication is done using the message broker. On this level there is no Authentication at all. If an action requires a current user ID, such information must be part of the message content as a field.

Requiring Authentication on Federated Queries

When creating queries on the downstream services (a.k.a. the microservices) that will be exposed to the outside, through a Gateway using Federation, we cannot configure authentication on the downstream. We have to setup the queries we want to be protect on the Gateway. This is not an arbitrary decision, it is imposed by the architecture, as mentioned above, the downstream services do not use authentication, all the authentication procedures have to happen at the Gateway level.

Protect all by default

We can configure all queries to require authentication by using the ConfigureAuth method on the GraphQLGatewayModuleOptions and calling RequireAuthenticationForAllQueries over the provided builder. We can add exceptions to the rule by calling the ExceptFor method and passing the query name as parameter.

C#
builder.DependsOn<GraphQLGatewayModule, GraphQLGatewayModuleOptions>(
    opts =>
        {
            opts.ConfigureAuth(auth =>
            {
                auth.RequireAuthenticationForAllQueries()
                .ExceptFor("assets")
                .ExceptFor("locations");
            });
        });
        }

Playground

Currently Banana Cake Pop doesn't support authentication flows, it is an upcoming feature. That being said, it does support sending HTTP Headers, so we can get our queries authenticated by sending the token on the standard HTTP Header Authorization. The content should be the word Bearer followed by the bearer token.

Authentication Header